@ainyc/canonry 4.180.7 → 4.180.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/assets/agent-workspace/skills/canonry/SKILL.md +13 -10
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +7 -6
- package/assets/assets/{AuditHistoryPanel-B1lmI7wm.js → AuditHistoryPanel-qiuqNGvG.js} +1 -1
- package/assets/assets/{BacklinksPage-Bw61uQu8.js → BacklinksPage-D-g5f0Xv.js} +1 -1
- package/assets/assets/{HistoryPage-D8z9-NkT.js → HistoryPage-q8_pCuOs.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-CXX9GFj8.js → MeasurementPropertyPage-C_wMjUZe.js} +1 -1
- package/assets/assets/ProjectPage-33THfDtC.js +9 -0
- package/assets/assets/{RunRow-DXHy16T3.js → RunRow-D5hatdlY.js} +1 -1
- package/assets/assets/{RunsPage-D2aE620i.js → RunsPage-Bj2snMM3.js} +1 -1
- package/assets/assets/SettingsPage-Cf5YgyJv.js +1 -0
- package/assets/assets/SiteHealthSection-D8RLvMAE.js +4 -0
- package/assets/assets/{TrafficPage-DFHWgvkU.js → TrafficPage-CotJ14le.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DxjyRL8Y.js → TrafficSourceDetailPage-BcxYX-uq.js} +1 -1
- package/assets/assets/{extract-error-message-BdXUZQW9.js → extract-error-message-Bxt42scd.js} +1 -1
- package/assets/assets/index-BlILyZJ5.js +86 -0
- package/assets/assets/index-DXCQf5s1.css +1 -0
- package/assets/assets/{react-sigma_core.esm.min-DAcOZae7.js → react-sigma_core.esm.min-DxZINEmi.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-XYTSKRO3.js → chunk-G7M2KM7Q.js} +2 -2
- package/dist/{chunk-VZO6CLHY.js → chunk-GFVZOVG3.js} +105 -64
- package/dist/{chunk-RXXZ5BU5.js → chunk-GN2G7VFK.js} +24 -1
- package/dist/{chunk-CWXPBQR5.js → chunk-IM4HFNGF.js} +7 -5
- package/dist/{chunk-WJFBNCVD.js → chunk-ZJ2VGTYU.js} +197 -95
- package/dist/cli.js +187 -96
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-MEPYXRBS.js → intelligence-service-IURLYRB3.js} +2 -2
- package/dist/mcp.js +3 -3
- package/package.json +10 -10
- package/assets/assets/ProjectPage-BaN_rvoV.js +0 -9
- package/assets/assets/SettingsPage-BiiFqarS.js +0 -1
- package/assets/assets/SiteHealthSection-DCH2Ejtc.js +0 -4
- package/assets/assets/index-BuEq5Rhg.css +0 -1
- package/assets/assets/index-CSictO9U.js +0 -83
|
@@ -480,6 +480,7 @@ import {
|
|
|
480
480
|
mentionStateFromAnswerMentioned,
|
|
481
481
|
missingDependency,
|
|
482
482
|
modelIdsEquivalent,
|
|
483
|
+
nextScheduleUpdatedAt,
|
|
483
484
|
noProvider,
|
|
484
485
|
noQueries,
|
|
485
486
|
normalizeIdTokens,
|
|
@@ -558,7 +559,9 @@ import {
|
|
|
558
559
|
runtimeStateMissing,
|
|
559
560
|
schedulableRunKindSchema,
|
|
560
561
|
scheduleDtoSchema,
|
|
562
|
+
scheduleExpectedUpdatedAtSchema,
|
|
561
563
|
scheduleUpsertRequestSchema,
|
|
564
|
+
scheduleVersionConflict,
|
|
562
565
|
seedCollapseWarning,
|
|
563
566
|
segmentCrawlerHits,
|
|
564
567
|
serializeRunError,
|
|
@@ -643,10 +646,10 @@ import {
|
|
|
643
646
|
wordpressSchemaDeployResultDtoSchema,
|
|
644
647
|
wordpressSchemaStatusResultDtoSchema,
|
|
645
648
|
wordpressStatusDtoSchema
|
|
646
|
-
} from "./chunk-
|
|
649
|
+
} from "./chunk-GN2G7VFK.js";
|
|
647
650
|
|
|
648
651
|
// src/intelligence-service.ts
|
|
649
|
-
import { eq as eq62, desc as desc27, asc as
|
|
652
|
+
import { eq as eq62, desc as desc27, asc as asc12, and as and51, ne as ne8, or as or14, inArray as inArray22, gte as gte15, lte as lte13, isNull as isNull9, sql as sql25, exists } from "drizzle-orm";
|
|
650
653
|
|
|
651
654
|
// ../db/src/client.ts
|
|
652
655
|
import { mkdirSync } from "fs";
|
|
@@ -11346,6 +11349,13 @@ function pruneProviderModelsForProviders(models, providers) {
|
|
|
11346
11349
|
|
|
11347
11350
|
// ../api-routes/src/projects.ts
|
|
11348
11351
|
async function projectRoutes(app, opts) {
|
|
11352
|
+
const notifyProjectCreated = (projectId, projectName) => {
|
|
11353
|
+
try {
|
|
11354
|
+
opts.onProjectCreated?.(projectId, projectName);
|
|
11355
|
+
} catch (error) {
|
|
11356
|
+
app.log.error({ error, projectId, projectName }, "Project-created callback failed after commit");
|
|
11357
|
+
}
|
|
11358
|
+
};
|
|
11349
11359
|
app.post("/projects", async (request, reply) => {
|
|
11350
11360
|
requireAdminSession(request);
|
|
11351
11361
|
if (request.principal?.projectId) {
|
|
@@ -11440,6 +11450,7 @@ async function projectRoutes(app, opts) {
|
|
|
11440
11450
|
return true;
|
|
11441
11451
|
});
|
|
11442
11452
|
if (!inserted) throw alreadyExists("Project", name);
|
|
11453
|
+
notifyProjectCreated(id, name);
|
|
11443
11454
|
opts.onProjectUpserted?.(id, name);
|
|
11444
11455
|
const created = app.db.select().from(projects).where(eq5(projects.id, id)).get();
|
|
11445
11456
|
return reply.status(201).send(formatProject(created));
|
|
@@ -11559,6 +11570,7 @@ async function projectRoutes(app, opts) {
|
|
|
11559
11570
|
entityId: id
|
|
11560
11571
|
});
|
|
11561
11572
|
});
|
|
11573
|
+
notifyProjectCreated(id, name);
|
|
11562
11574
|
opts.onProjectUpserted?.(id, name);
|
|
11563
11575
|
const created = app.db.select().from(projects).where(eq5(projects.id, id)).get();
|
|
11564
11576
|
return reply.status(201).send(formatProject(created));
|
|
@@ -13481,11 +13493,20 @@ function normalizeProviders(values) {
|
|
|
13481
13493
|
return [...new Set(values.map((value) => value.trim().toLocaleLowerCase("en")).filter(Boolean))].sort();
|
|
13482
13494
|
}
|
|
13483
13495
|
function resolveRunProviderSelection(input) {
|
|
13496
|
+
return resolveRunnableProviderSelection(input).selectedProviders;
|
|
13497
|
+
}
|
|
13498
|
+
function resolveRunnableProviderSelection(input) {
|
|
13499
|
+
const availableProviders = normalizeProviders(input.runnableProviders ?? []);
|
|
13484
13500
|
const requested = normalizeProviders(input.requestedProviders ?? []);
|
|
13485
|
-
if (requested.length) return requested;
|
|
13486
13501
|
const project = normalizeProviders(input.projectProviders ?? []);
|
|
13487
|
-
|
|
13488
|
-
|
|
13502
|
+
const selectedProviders = requested.length > 0 ? requested : project.length > 0 ? project : availableProviders;
|
|
13503
|
+
const available = new Set(availableProviders);
|
|
13504
|
+
return {
|
|
13505
|
+
availableProviders,
|
|
13506
|
+
selectedProviders,
|
|
13507
|
+
runnableProviders: selectedProviders.filter((provider) => available.has(provider)),
|
|
13508
|
+
selectionSource: requested.length > 0 ? "request" : project.length > 0 ? "project" : "instance"
|
|
13509
|
+
};
|
|
13489
13510
|
}
|
|
13490
13511
|
function providerRoster(tx, params) {
|
|
13491
13512
|
return resolveRunProviderSelection({
|
|
@@ -14146,22 +14167,18 @@ function answerVisibilityPreflightError(input) {
|
|
|
14146
14167
|
if (input.trackedQueryCount === 0) {
|
|
14147
14168
|
return noQueries(input.projectName);
|
|
14148
14169
|
}
|
|
14149
|
-
const
|
|
14150
|
-
|
|
14151
|
-
|
|
14152
|
-
|
|
14153
|
-
|
|
14154
|
-
|
|
14155
|
-
if (runnableProviders.length > 0) return null;
|
|
14170
|
+
const selection = resolveRunnableProviderSelection({
|
|
14171
|
+
requestedProviders: input.requestedProviders,
|
|
14172
|
+
projectProviders: input.projectProviders,
|
|
14173
|
+
runnableProviders: input.runnableProviderNames
|
|
14174
|
+
});
|
|
14175
|
+
if (selection.runnableProviders.length > 0) return null;
|
|
14156
14176
|
return noProvider(input.projectName, {
|
|
14157
|
-
availableProviders,
|
|
14158
|
-
selectedProviders,
|
|
14159
|
-
selectionSource:
|
|
14177
|
+
availableProviders: selection.availableProviders,
|
|
14178
|
+
selectedProviders: selection.selectedProviders,
|
|
14179
|
+
selectionSource: selection.selectionSource
|
|
14160
14180
|
});
|
|
14161
14181
|
}
|
|
14162
|
-
function normalizeProviderNames(providerNames) {
|
|
14163
|
-
return [...new Set(providerNames.map((name) => name.trim().toLowerCase()).filter(Boolean))];
|
|
14164
|
-
}
|
|
14165
14182
|
function parseRunTriggerRequest(value) {
|
|
14166
14183
|
const result = runTriggerRequestSchema.safeParse(value);
|
|
14167
14184
|
if (result.success) return result.data;
|
|
@@ -17463,6 +17480,13 @@ async function measurementDraftRoutes(app, opts = {}) {
|
|
|
17463
17480
|
state,
|
|
17464
17481
|
nextAction,
|
|
17465
17482
|
mode: activeSchemaVersion === 1 ? "active-v1" : activeSchemaVersion === 2 ? "active-v2" : draft ? "draft-only" : "simple",
|
|
17483
|
+
// This project-readable response is also the dashboard's readiness
|
|
17484
|
+
// source. The boolean exposes no instance capability inventory and uses
|
|
17485
|
+
// the exact provider-selection decision enforced by run preflight.
|
|
17486
|
+
answerVisibilityProviderReady: resolveRunnableProviderSelection({
|
|
17487
|
+
projectProviders: project.providers,
|
|
17488
|
+
runnableProviders: opts.getRunnableProviderNames?.()
|
|
17489
|
+
}).runnableProviders.length > 0,
|
|
17466
17490
|
activeRevision: active?.revision ?? null,
|
|
17467
17491
|
activeSchemaVersion,
|
|
17468
17492
|
draft: draft ? { etag: measurementDraftEtag(draft.etagVersion), updatedAt: draft.updatedAt } : null
|
|
@@ -20809,6 +20833,13 @@ function stripIpv6Brackets2(value) {
|
|
|
20809
20833
|
// ../api-routes/src/apply.ts
|
|
20810
20834
|
async function applyRoutes(app, opts) {
|
|
20811
20835
|
const allowLoopback = opts?.allowLoopbackWebhooks === true;
|
|
20836
|
+
const notifyProjectCreated = (projectId, projectName) => {
|
|
20837
|
+
try {
|
|
20838
|
+
opts?.onProjectCreated?.(projectId, projectName);
|
|
20839
|
+
} catch (error) {
|
|
20840
|
+
app.log.error({ error, projectId, projectName }, "Project-created callback failed after commit");
|
|
20841
|
+
}
|
|
20842
|
+
};
|
|
20812
20843
|
app.post("/apply", async (request, reply) => {
|
|
20813
20844
|
const parsed = projectConfigSchema.safeParse(request.body);
|
|
20814
20845
|
if (!parsed.success) {
|
|
@@ -20885,6 +20916,7 @@ async function applyRoutes(app, opts) {
|
|
|
20885
20916
|
}
|
|
20886
20917
|
assertProviderModelScope(request, target?.providerModels ?? {}, providerModels, specProviders);
|
|
20887
20918
|
let projectId;
|
|
20919
|
+
const lifecycle = { projectCreated: false };
|
|
20888
20920
|
let scheduleAction = null;
|
|
20889
20921
|
let aliasesChanged = false;
|
|
20890
20922
|
app.db.transaction((tx) => {
|
|
@@ -20923,6 +20955,7 @@ async function applyRoutes(app, opts) {
|
|
|
20923
20955
|
});
|
|
20924
20956
|
} else {
|
|
20925
20957
|
projectId = crypto21.randomUUID();
|
|
20958
|
+
lifecycle.projectCreated = true;
|
|
20926
20959
|
tx.insert(projects).values({
|
|
20927
20960
|
id: projectId,
|
|
20928
20961
|
name,
|
|
@@ -20992,7 +21025,7 @@ async function applyRoutes(app, opts) {
|
|
|
20992
21025
|
timezone: resolvedSchedule.timezone,
|
|
20993
21026
|
providers: config.spec.schedule?.providers ?? [],
|
|
20994
21027
|
...specEnabled === void 0 ? {} : { enabled: specEnabled },
|
|
20995
|
-
updatedAt: now
|
|
21028
|
+
updatedAt: nextScheduleUpdatedAt(existingSched.updatedAt, Date.parse(now))
|
|
20996
21029
|
}).where(eq22(schedules.id, existingSched.id)).run();
|
|
20997
21030
|
} else {
|
|
20998
21031
|
tx.insert(schedules).values({
|
|
@@ -21039,6 +21072,9 @@ async function applyRoutes(app, opts) {
|
|
|
21039
21072
|
});
|
|
21040
21073
|
}
|
|
21041
21074
|
});
|
|
21075
|
+
if (lifecycle.projectCreated) {
|
|
21076
|
+
notifyProjectCreated(projectId, config.metadata.name);
|
|
21077
|
+
}
|
|
21042
21078
|
if (scheduleAction) {
|
|
21043
21079
|
opts?.onScheduleUpdated?.(scheduleAction, projectId, SchedulableRunKinds["answer-visibility"]);
|
|
21044
21080
|
}
|
|
@@ -30765,6 +30801,12 @@ var scheduleKindQueryParameter = {
|
|
|
30765
30801
|
description: 'Schedulable run kind. Defaults to "answer-visibility" for backward compatibility.',
|
|
30766
30802
|
schema: { $ref: "#/components/schemas/SchedulableRunKind" }
|
|
30767
30803
|
};
|
|
30804
|
+
var scheduleExpectedUpdatedAtQueryParameter = {
|
|
30805
|
+
name: "expectedUpdatedAt",
|
|
30806
|
+
in: "query",
|
|
30807
|
+
description: "Delete only the schedule version carrying this exact updatedAt timestamp. A mismatch returns 409.",
|
|
30808
|
+
schema: { type: "string", format: "date-time" }
|
|
30809
|
+
};
|
|
30768
30810
|
var runsListKindQueryParameter = {
|
|
30769
30811
|
name: "kind",
|
|
30770
30812
|
in: "query",
|
|
@@ -33025,7 +33067,13 @@ var routeCatalog = [
|
|
|
33025
33067
|
timezone: stringSchema,
|
|
33026
33068
|
providers: stringArraySchema,
|
|
33027
33069
|
enabled: booleanSchema,
|
|
33028
|
-
sourceId: stringSchema
|
|
33070
|
+
sourceId: stringSchema,
|
|
33071
|
+
expectedUpdatedAt: {
|
|
33072
|
+
type: "string",
|
|
33073
|
+
format: "date-time",
|
|
33074
|
+
nullable: true,
|
|
33075
|
+
description: "Update only this exact version; null creates only while absent. Omit for legacy unconditional behavior."
|
|
33076
|
+
}
|
|
33029
33077
|
}
|
|
33030
33078
|
}
|
|
33031
33079
|
}
|
|
@@ -33034,7 +33082,18 @@ var routeCatalog = [
|
|
|
33034
33082
|
responses: {
|
|
33035
33083
|
200: jsonResponse("Schedule updated.", "ScheduleDto"),
|
|
33036
33084
|
201: jsonResponse("Schedule created.", "ScheduleDto"),
|
|
33037
|
-
400: errorResponse("Invalid payload (e.g. sourceId missing for kind=traffic-sync, or providers set for kind=traffic-sync).")
|
|
33085
|
+
400: errorResponse("Invalid payload (e.g. sourceId missing for kind=traffic-sync, or providers set for kind=traffic-sync)."),
|
|
33086
|
+
409: errorResponse("The schedule changed since the caller loaded it.")
|
|
33087
|
+
}
|
|
33088
|
+
},
|
|
33089
|
+
{
|
|
33090
|
+
method: "get",
|
|
33091
|
+
path: "/api/v1/projects/{name}/schedules",
|
|
33092
|
+
summary: "List schedules",
|
|
33093
|
+
tags: ["schedules"],
|
|
33094
|
+
parameters: [nameParameter],
|
|
33095
|
+
responses: {
|
|
33096
|
+
200: jsonArrayResponse("Schedules returned.", "ScheduleDto")
|
|
33038
33097
|
}
|
|
33039
33098
|
},
|
|
33040
33099
|
{
|
|
@@ -33053,10 +33112,11 @@ var routeCatalog = [
|
|
|
33053
33112
|
path: "/api/v1/projects/{name}/schedule",
|
|
33054
33113
|
summary: "Delete a schedule",
|
|
33055
33114
|
tags: ["schedules"],
|
|
33056
|
-
parameters: [nameParameter, scheduleKindQueryParameter],
|
|
33115
|
+
parameters: [nameParameter, scheduleKindQueryParameter, scheduleExpectedUpdatedAtQueryParameter],
|
|
33057
33116
|
responses: {
|
|
33058
33117
|
204: { description: "Schedule deleted." },
|
|
33059
|
-
404: errorResponse("Schedule not found.")
|
|
33118
|
+
404: errorResponse("Schedule not found."),
|
|
33119
|
+
409: errorResponse("The schedule changed since the caller loaded it.")
|
|
33060
33120
|
}
|
|
33061
33121
|
},
|
|
33062
33122
|
{
|
|
@@ -37818,7 +37878,7 @@ async function telemetryRoutes(app, opts) {
|
|
|
37818
37878
|
|
|
37819
37879
|
// ../api-routes/src/schedules.ts
|
|
37820
37880
|
import crypto25 from "crypto";
|
|
37821
|
-
import { and as and31, eq as eq38 } from "drizzle-orm";
|
|
37881
|
+
import { and as and31, asc as asc7, eq as eq38 } from "drizzle-orm";
|
|
37822
37882
|
function parseKindParam(raw) {
|
|
37823
37883
|
if (raw === void 0 || raw === null || raw === "") return SchedulableRunKinds["answer-visibility"];
|
|
37824
37884
|
const parsed = schedulableRunKindSchema.safeParse(raw);
|
|
@@ -37827,6 +37887,12 @@ function parseKindParam(raw) {
|
|
|
37827
37887
|
}
|
|
37828
37888
|
return parsed.data;
|
|
37829
37889
|
}
|
|
37890
|
+
function parseExpectedUpdatedAtParam(raw) {
|
|
37891
|
+
if (raw === void 0) return void 0;
|
|
37892
|
+
const parsed = scheduleExpectedUpdatedAtSchema.safeParse(raw);
|
|
37893
|
+
if (!parsed.success) throw validationError("Invalid expectedUpdatedAt timestamp");
|
|
37894
|
+
return parsed.data;
|
|
37895
|
+
}
|
|
37830
37896
|
async function scheduleRoutes(app, opts) {
|
|
37831
37897
|
app.put("/projects/:name/schedule", async (request, reply) => {
|
|
37832
37898
|
const project = resolveProject(app.db, request.params.name);
|
|
@@ -37840,7 +37906,7 @@ async function scheduleRoutes(app, opts) {
|
|
|
37840
37906
|
});
|
|
37841
37907
|
}
|
|
37842
37908
|
const kind = parsedBody.data.kind ?? parseKindParam(request.query?.kind);
|
|
37843
|
-
const { preset, cron, timezone, providers, enabled, sourceId } = parsedBody.data;
|
|
37909
|
+
const { preset, cron, timezone, providers, enabled, sourceId, expectedUpdatedAt } = parsedBody.data;
|
|
37844
37910
|
if (kind === SchedulableRunKinds["traffic-sync"]) {
|
|
37845
37911
|
if (!sourceId) {
|
|
37846
37912
|
throw validationError('"sourceId" is required when kind is "traffic-sync"');
|
|
@@ -37888,11 +37954,16 @@ async function scheduleRoutes(app, opts) {
|
|
|
37888
37954
|
throw validationError(`Invalid cron expression: ${cronExpr}`);
|
|
37889
37955
|
}
|
|
37890
37956
|
}
|
|
37891
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
37892
37957
|
const enabledBool = enabled !== false;
|
|
37893
|
-
const
|
|
37894
|
-
|
|
37895
|
-
|
|
37958
|
+
const mutation = app.db.transaction((tx) => {
|
|
37959
|
+
const existing = tx.select().from(schedules).where(and31(eq38(schedules.projectId, project.id), eq38(schedules.kind, kind))).get();
|
|
37960
|
+
const actualUpdatedAt = existing?.updatedAt ?? null;
|
|
37961
|
+
if (expectedUpdatedAt !== void 0 && expectedUpdatedAt !== actualUpdatedAt) {
|
|
37962
|
+
throw scheduleVersionConflict(expectedUpdatedAt, actualUpdatedAt);
|
|
37963
|
+
}
|
|
37964
|
+
const now = nextScheduleUpdatedAt(existing?.updatedAt);
|
|
37965
|
+
const scheduleId = existing?.id ?? crypto25.randomUUID();
|
|
37966
|
+
const values = {
|
|
37896
37967
|
cronExpr,
|
|
37897
37968
|
preset: preset ?? null,
|
|
37898
37969
|
timezone,
|
|
@@ -37900,32 +37971,48 @@ async function scheduleRoutes(app, opts) {
|
|
|
37900
37971
|
sourceId: sourceId ?? null,
|
|
37901
37972
|
enabled: enabledBool,
|
|
37902
37973
|
updatedAt: now
|
|
37903
|
-
}
|
|
37904
|
-
|
|
37905
|
-
|
|
37906
|
-
|
|
37974
|
+
};
|
|
37975
|
+
if (existing) {
|
|
37976
|
+
const changed = tx.update(schedules).set(values).where(
|
|
37977
|
+
expectedUpdatedAt === void 0 ? eq38(schedules.id, existing.id) : and31(eq38(schedules.id, existing.id), eq38(schedules.updatedAt, expectedUpdatedAt ?? existing.updatedAt))
|
|
37978
|
+
).run();
|
|
37979
|
+
if (changed.changes !== 1) {
|
|
37980
|
+
const actual = tx.select().from(schedules).where(eq38(schedules.id, existing.id)).get();
|
|
37981
|
+
throw scheduleVersionConflict(expectedUpdatedAt ?? existing.updatedAt, actual?.updatedAt ?? null);
|
|
37982
|
+
}
|
|
37983
|
+
} else {
|
|
37984
|
+
const insert = tx.insert(schedules).values({
|
|
37985
|
+
id: scheduleId,
|
|
37986
|
+
projectId: project.id,
|
|
37987
|
+
kind,
|
|
37988
|
+
...values,
|
|
37989
|
+
createdAt: now
|
|
37990
|
+
});
|
|
37991
|
+
const inserted = expectedUpdatedAt === null ? insert.onConflictDoNothing().run() : insert.run();
|
|
37992
|
+
if (expectedUpdatedAt === null && inserted.changes !== 1) {
|
|
37993
|
+
const actual = tx.select().from(schedules).where(and31(eq38(schedules.projectId, project.id), eq38(schedules.kind, kind))).get();
|
|
37994
|
+
throw scheduleVersionConflict(null, actual?.updatedAt ?? null);
|
|
37995
|
+
}
|
|
37996
|
+
}
|
|
37997
|
+
writeAuditLog(tx, {
|
|
37907
37998
|
projectId: project.id,
|
|
37908
|
-
|
|
37909
|
-
|
|
37910
|
-
|
|
37911
|
-
timezone,
|
|
37912
|
-
|
|
37913
|
-
|
|
37914
|
-
|
|
37915
|
-
|
|
37916
|
-
updatedAt: now
|
|
37917
|
-
}).run();
|
|
37918
|
-
}
|
|
37919
|
-
writeAuditLog(app.db, {
|
|
37920
|
-
projectId: project.id,
|
|
37921
|
-
actor: "api",
|
|
37922
|
-
action: existing ? "schedule.updated" : "schedule.created",
|
|
37923
|
-
entityType: "schedule",
|
|
37924
|
-
diff: { kind, cronExpr, preset, timezone, providers, sourceId }
|
|
37999
|
+
actor: "api",
|
|
38000
|
+
action: existing ? "schedule.updated" : "schedule.created",
|
|
38001
|
+
entityType: "schedule",
|
|
38002
|
+
diff: { kind, cronExpr, preset, timezone, providers, sourceId }
|
|
38003
|
+
});
|
|
38004
|
+
return {
|
|
38005
|
+
existed: existing !== void 0
|
|
38006
|
+
};
|
|
37925
38007
|
});
|
|
37926
38008
|
opts.onScheduleUpdated?.("upsert", project.id, kind);
|
|
37927
38009
|
const schedule = app.db.select().from(schedules).where(and31(eq38(schedules.projectId, project.id), eq38(schedules.kind, kind))).get();
|
|
37928
|
-
return reply.status(
|
|
38010
|
+
return reply.status(mutation.existed ? 200 : 201).send(formatSchedule(schedule));
|
|
38011
|
+
});
|
|
38012
|
+
app.get("/projects/:name/schedules", async (request, reply) => {
|
|
38013
|
+
const project = resolveProject(app.db, request.params.name);
|
|
38014
|
+
const rows = app.db.select().from(schedules).where(eq38(schedules.projectId, project.id)).orderBy(asc7(schedules.kind)).all();
|
|
38015
|
+
return reply.send(rows.map(formatSchedule));
|
|
37929
38016
|
});
|
|
37930
38017
|
app.get("/projects/:name/schedule", async (request, reply) => {
|
|
37931
38018
|
const project = resolveProject(app.db, request.params.name);
|
|
@@ -37939,18 +38026,31 @@ async function scheduleRoutes(app, opts) {
|
|
|
37939
38026
|
app.delete("/projects/:name/schedule", async (request, reply) => {
|
|
37940
38027
|
const project = resolveProject(app.db, request.params.name);
|
|
37941
38028
|
const kind = parseKindParam(request.query?.kind);
|
|
37942
|
-
const
|
|
37943
|
-
|
|
37944
|
-
|
|
37945
|
-
|
|
37946
|
-
|
|
37947
|
-
|
|
37948
|
-
|
|
37949
|
-
|
|
37950
|
-
|
|
37951
|
-
|
|
37952
|
-
|
|
37953
|
-
|
|
38029
|
+
const expectedUpdatedAt = parseExpectedUpdatedAtParam(request.query?.expectedUpdatedAt);
|
|
38030
|
+
app.db.transaction((tx) => {
|
|
38031
|
+
const schedule = tx.select().from(schedules).where(and31(eq38(schedules.projectId, project.id), eq38(schedules.kind, kind))).get();
|
|
38032
|
+
if (!schedule) {
|
|
38033
|
+
if (expectedUpdatedAt !== void 0) throw scheduleVersionConflict(expectedUpdatedAt, null);
|
|
38034
|
+
throw notFound("Schedule", `${request.params.name} (kind=${kind})`);
|
|
38035
|
+
}
|
|
38036
|
+
if (expectedUpdatedAt !== void 0 && schedule.updatedAt !== expectedUpdatedAt) {
|
|
38037
|
+
throw scheduleVersionConflict(expectedUpdatedAt, schedule.updatedAt);
|
|
38038
|
+
}
|
|
38039
|
+
const deleted = tx.delete(schedules).where(
|
|
38040
|
+
expectedUpdatedAt === void 0 ? eq38(schedules.id, schedule.id) : and31(eq38(schedules.id, schedule.id), eq38(schedules.updatedAt, expectedUpdatedAt))
|
|
38041
|
+
).run();
|
|
38042
|
+
if (deleted.changes !== 1) {
|
|
38043
|
+
const actual = tx.select().from(schedules).where(eq38(schedules.id, schedule.id)).get();
|
|
38044
|
+
throw scheduleVersionConflict(expectedUpdatedAt ?? schedule.updatedAt, actual?.updatedAt ?? null);
|
|
38045
|
+
}
|
|
38046
|
+
writeAuditLog(tx, {
|
|
38047
|
+
projectId: project.id,
|
|
38048
|
+
actor: "api",
|
|
38049
|
+
action: "schedule.deleted",
|
|
38050
|
+
entityType: "schedule",
|
|
38051
|
+
entityId: schedule.id,
|
|
38052
|
+
diff: { kind }
|
|
38053
|
+
});
|
|
37954
38054
|
});
|
|
37955
38055
|
opts.onScheduleUpdated?.("delete", project.id, kind);
|
|
37956
38056
|
return reply.status(204).send();
|
|
@@ -43474,7 +43574,7 @@ async function googleMarketingRoutes(app, opts) {
|
|
|
43474
43574
|
|
|
43475
43575
|
// ../api-routes/src/ads.ts
|
|
43476
43576
|
import crypto35 from "crypto";
|
|
43477
|
-
import { eq as eq43, and as and35, asc as
|
|
43577
|
+
import { eq as eq43, and as and35, asc as asc9, desc as desc19, gt as gt2, gte as gte10, lt as lt8, lte as lte9, ne as ne5, inArray as inArray17, or as or10, isNull as isNull5, isNotNull as isNotNull2, sql as sql17 } from "drizzle-orm";
|
|
43478
43578
|
|
|
43479
43579
|
// ../api-routes/src/ads-activation.ts
|
|
43480
43580
|
import crypto33 from "crypto";
|
|
@@ -44860,7 +44960,7 @@ async function executeApprovedAdsActivation(dependencies, request) {
|
|
|
44860
44960
|
|
|
44861
44961
|
// ../api-routes/src/ads-activation-routes.ts
|
|
44862
44962
|
import crypto34 from "crypto";
|
|
44863
|
-
import { and as and34, asc as
|
|
44963
|
+
import { and as and34, asc as asc8, eq as eq42, gt, isNotNull, isNull as isNull4, lte as lte8, or as or9, sql as sql16 } from "drizzle-orm";
|
|
44864
44964
|
var MAX_ACTIVATION_GRANT_LIFETIME_MS = 24 * 60 * 60 * 1e3;
|
|
44865
44965
|
var ACTIVATION_LEASE_MS = 5 * 6e4;
|
|
44866
44966
|
var ACTIVATION_REVOCATION_SETTLEMENT_MS = ACTIVATION_LEASE_MS;
|
|
@@ -44899,7 +44999,7 @@ function loadActivationOperation(db, operationId) {
|
|
|
44899
44999
|
if (row.kind !== AdsOperationKinds.campaign_tree_activate) {
|
|
44900
45000
|
throw internalError("Ads activation grant is bound to a non-activation receipt");
|
|
44901
45001
|
}
|
|
44902
|
-
const steps = db.select().from(adsOperationSteps).where(eq42(adsOperationSteps.operationId, operationId)).orderBy(
|
|
45002
|
+
const steps = db.select().from(adsOperationSteps).where(eq42(adsOperationSteps.operationId, operationId)).orderBy(asc8(adsOperationSteps.ordinal)).all().map(toStepDto);
|
|
44903
45003
|
return {
|
|
44904
45004
|
...row,
|
|
44905
45005
|
kind: AdsOperationKinds.campaign_tree_activate,
|
|
@@ -45455,9 +45555,9 @@ function selectWatchdogOperations(app, nowIso, batchSize, allowLiveRevocationLea
|
|
|
45455
45555
|
eq42(adsOperations.kind, AdsOperationKinds.campaign_tree_activate),
|
|
45456
45556
|
eligibleState
|
|
45457
45557
|
)).orderBy(
|
|
45458
|
-
|
|
45459
|
-
|
|
45460
|
-
|
|
45558
|
+
asc8(freshRevocationPriority),
|
|
45559
|
+
asc8(roundRobinCursor),
|
|
45560
|
+
asc8(adsOperations.updatedAt)
|
|
45461
45561
|
).limit(batchSize).all().map((row) => row.operation);
|
|
45462
45562
|
}
|
|
45463
45563
|
function selectRecoveryWatchdogOperations(app, nowIso, batchSize) {
|
|
@@ -46508,7 +46608,7 @@ function semanticallyMatchesMaterializedEntity(app, input) {
|
|
|
46508
46608
|
eq43(adsOperations.entityType, input.entityType),
|
|
46509
46609
|
eq43(adsOperations.entityId, input.entityId),
|
|
46510
46610
|
inArray17(adsOperations.kind, [createKind, updateKind])
|
|
46511
|
-
)).orderBy(
|
|
46611
|
+
)).orderBy(asc9(adsOperations.createdAt), asc9(adsOperations.id)).all();
|
|
46512
46612
|
if (rows.some((row) => row.state === AdsOperationStates.pending || row.state === AdsOperationStates.reconciling || row.state === AdsOperationStates.unknown || row.kind === updateKind && row.state === AdsOperationStates.succeeded)) {
|
|
46513
46613
|
return false;
|
|
46514
46614
|
}
|
|
@@ -47195,7 +47295,7 @@ async function sweepAdsOperationsOnce(app, opts, config) {
|
|
|
47195
47295
|
isNull5(adsOperations.errorCode),
|
|
47196
47296
|
ne5(adsOperations.errorCode, ADS_RECONCILIATION_QUARANTINED)
|
|
47197
47297
|
)
|
|
47198
|
-
)).orderBy(
|
|
47298
|
+
)).orderBy(asc9(adsOperations.updatedAt)).limit(config.batchSize).all();
|
|
47199
47299
|
for (const row of exhaustedRows) {
|
|
47200
47300
|
quarantineExhaustedReconciliation(app, row, now, config.policy, { actor: "system" });
|
|
47201
47301
|
}
|
|
@@ -47218,7 +47318,7 @@ async function sweepAdsOperationsOnce(app, opts, config) {
|
|
|
47218
47318
|
const rows = app.db.select().from(adsOperations).where(and35(
|
|
47219
47319
|
inArray17(adsOperations.projectId, eligibleProjectIds),
|
|
47220
47320
|
staleReconcileWhere
|
|
47221
|
-
)).orderBy(
|
|
47321
|
+
)).orderBy(asc9(adsOperations.updatedAt)).limit(config.batchSize).all();
|
|
47222
47322
|
for (const row of rows) {
|
|
47223
47323
|
const credential = credentialsByProjectId.get(row.projectId);
|
|
47224
47324
|
if (!credential) continue;
|
|
@@ -47546,7 +47646,7 @@ async function adsRoutes(app, opts) {
|
|
|
47546
47646
|
gt2(adsOperations.id, cursor.id)
|
|
47547
47647
|
)
|
|
47548
47648
|
) : void 0
|
|
47549
|
-
)).orderBy(
|
|
47649
|
+
)).orderBy(asc9(adsOperations.createdAt), asc9(adsOperations.id)).limit(parsed.data.limit + 1).all();
|
|
47550
47650
|
const hasMore = rows.length > parsed.data.limit;
|
|
47551
47651
|
const page2 = hasMore ? rows.slice(0, parsed.data.limit) : rows;
|
|
47552
47652
|
const response = {
|
|
@@ -48066,7 +48166,7 @@ async function adsRoutes(app, opts) {
|
|
|
48066
48166
|
if (entityId) conditions.push(eq43(adsInsightsDaily.entityId, entityId));
|
|
48067
48167
|
if (from) conditions.push(gte10(adsInsightsDaily.date, from));
|
|
48068
48168
|
if (to) conditions.push(lte9(adsInsightsDaily.date, to));
|
|
48069
|
-
const rows = app.db.select().from(adsInsightsDaily).where(and35(...conditions)).orderBy(
|
|
48169
|
+
const rows = app.db.select().from(adsInsightsDaily).where(and35(...conditions)).orderBy(asc9(adsInsightsDaily.date)).all();
|
|
48070
48170
|
const conn = app.db.select().from(adsConnections).where(eq43(adsConnections.projectId, project.id)).get();
|
|
48071
48171
|
const accountToday = adsAccountToday(conn?.timezone, (/* @__PURE__ */ new Date()).toISOString());
|
|
48072
48172
|
const dtoRows = rows.map((row) => ({
|
|
@@ -52268,7 +52368,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
52268
52368
|
|
|
52269
52369
|
// ../api-routes/src/backlinks.ts
|
|
52270
52370
|
import crypto40 from "crypto";
|
|
52271
|
-
import { and as and40, asc as
|
|
52371
|
+
import { and as and40, asc as asc10, desc as desc22, eq as eq47, sql as sql19 } from "drizzle-orm";
|
|
52272
52372
|
|
|
52273
52373
|
// ../integration-commoncrawl/src/constants.ts
|
|
52274
52374
|
import os2 from "os";
|
|
@@ -53026,7 +53126,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
53026
53126
|
async (request, reply) => {
|
|
53027
53127
|
const project = resolveProject(app.db, request.params.name);
|
|
53028
53128
|
const source = parseSourceParam(request.query.source);
|
|
53029
|
-
const rows = app.db.select().from(backlinkSummaries).where(and40(eq47(backlinkSummaries.projectId, project.id), eq47(backlinkSummaries.source, source))).orderBy(
|
|
53129
|
+
const rows = app.db.select().from(backlinkSummaries).where(and40(eq47(backlinkSummaries.projectId, project.id), eq47(backlinkSummaries.source, source))).orderBy(asc10(backlinkSummaries.queriedAt)).all();
|
|
53030
53130
|
const response = rows.map((r) => ({
|
|
53031
53131
|
release: r.release,
|
|
53032
53132
|
totalLinkingDomains: r.totalLinkingDomains,
|
|
@@ -70387,7 +70487,7 @@ function bindTrafficSyncSchedule(tx, projectId, sourceId, now, createIfMissing =
|
|
|
70387
70487
|
)).get();
|
|
70388
70488
|
if (schedule) {
|
|
70389
70489
|
if (schedule.sourceId === sourceId) return { changed: false, created: false };
|
|
70390
|
-
tx.update(schedules).set({ sourceId, updatedAt: now }).where(eq51(schedules.id, schedule.id)).run();
|
|
70490
|
+
tx.update(schedules).set({ sourceId, updatedAt: nextScheduleUpdatedAt(schedule.updatedAt, Date.parse(now)) }).where(eq51(schedules.id, schedule.id)).run();
|
|
70391
70491
|
return { changed: true, created: false };
|
|
70392
70492
|
}
|
|
70393
70493
|
if (!createIfMissing) return { changed: false, created: false };
|
|
@@ -74771,10 +74871,10 @@ var providersConfiguredCheck = {
|
|
|
74771
74871
|
const total = summary.length;
|
|
74772
74872
|
if (configured.length === 0) {
|
|
74773
74873
|
return {
|
|
74774
|
-
status: CheckStatuses.
|
|
74874
|
+
status: CheckStatuses.warn,
|
|
74775
74875
|
code: "providers.none-configured",
|
|
74776
|
-
summary: "No answer-engine
|
|
74777
|
-
remediation: "
|
|
74876
|
+
summary: "No answer-engine provider is configured. Page Health remains available; AI Visibility is disabled.",
|
|
74877
|
+
remediation: "To enable AI Visibility, set a provider environment variable and rerun `canonry bootstrap`, or run `canonry settings provider <name> --api-key <key>` while the server is running.",
|
|
74778
74878
|
details: { available: summary.map((entry) => entry.name) }
|
|
74779
74879
|
};
|
|
74780
74880
|
}
|
|
@@ -76715,7 +76815,7 @@ function dedupeStrings(input) {
|
|
|
76715
76815
|
|
|
76716
76816
|
// ../api-routes/src/technical-aeo.ts
|
|
76717
76817
|
import crypto47 from "crypto";
|
|
76718
|
-
import { and as and49, asc as
|
|
76818
|
+
import { and as and49, asc as asc11, count, desc as desc25, eq as eq60, inArray as inArray21, isNotNull as isNotNull3, isNull as isNull8, lt as lt11, or as or13, sql as sql24 } from "drizzle-orm";
|
|
76719
76819
|
import { alias } from "drizzle-orm/sqlite-core";
|
|
76720
76820
|
var FETCHED_SITE_CRAWL_STATES = /* @__PURE__ */ new Set([
|
|
76721
76821
|
...SiteCrawlFetchedStates,
|
|
@@ -77055,14 +77155,14 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
77055
77155
|
eq60(siteCrawlPages.runId, scope.runId),
|
|
77056
77156
|
eq60(siteCrawlPages.attemptId, scope.attemptId),
|
|
77057
77157
|
selector.nodeKey ? eq60(siteCrawlPages.nodeKey, selector.nodeKey) : eq60(siteCrawlPages.url, selector.url)
|
|
77058
|
-
)).orderBy(
|
|
77158
|
+
)).orderBy(asc11(siteCrawlPages.nodeKey)).limit(1).get() ?? null;
|
|
77059
77159
|
};
|
|
77060
77160
|
const rootPageInScope = (scope, rootUrl) => pageInScope(scope, { url: rootUrl }) ?? app.db.select().from(siteCrawlPages).where(and49(
|
|
77061
77161
|
eq60(siteCrawlPages.projectId, scope.projectId),
|
|
77062
77162
|
eq60(siteCrawlPages.runId, scope.runId),
|
|
77063
77163
|
eq60(siteCrawlPages.attemptId, scope.attemptId),
|
|
77064
77164
|
eq60(siteCrawlPages.depth, 0)
|
|
77065
|
-
)).orderBy(
|
|
77165
|
+
)).orderBy(asc11(siteCrawlPages.nodeKey)).limit(1).get() ?? null;
|
|
77066
77166
|
const isSurfaceableAuditRun = (projectId, runId) => Boolean(app.db.select({ id: runs.id }).from(runs).where(and49(
|
|
77067
77167
|
eq60(runs.id, runId),
|
|
77068
77168
|
eq60(runs.projectId, projectId),
|
|
@@ -77160,7 +77260,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
77160
77260
|
const total = totalRow?.value ?? 0;
|
|
77161
77261
|
const limit = parsePositiveInt(request.query.limit, 100, 500);
|
|
77162
77262
|
const offset = parsePositiveInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER);
|
|
77163
|
-
const orderBy = request.query.sort === "score-desc" ? desc25(siteAuditPages.overallScore) : request.query.sort === "url" ?
|
|
77263
|
+
const orderBy = request.query.sort === "score-desc" ? desc25(siteAuditPages.overallScore) : request.query.sort === "url" ? asc11(siteAuditPages.url) : asc11(siteAuditPages.overallScore);
|
|
77164
77264
|
const rows = app.db.select().from(siteAuditPages).where(where).orderBy(orderBy).limit(limit).offset(offset).all();
|
|
77165
77265
|
const pages = rows.map((row) => ({
|
|
77166
77266
|
url: row.url,
|
|
@@ -77357,7 +77457,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
77357
77457
|
eq60(siteCrawlPages.runId, siteCrawlGraphNodes.runId),
|
|
77358
77458
|
eq60(siteCrawlPages.attemptId, siteCrawlGraphNodes.attemptId),
|
|
77359
77459
|
eq60(siteCrawlPages.nodeKey, siteCrawlGraphNodes.nodeKey)
|
|
77360
|
-
)).where(and49(...graphScope, lt11(siteCrawlGraphNodes.sampleRank, maxNodes))).orderBy(
|
|
77460
|
+
)).where(and49(...graphScope, lt11(siteCrawlGraphNodes.sampleRank, maxNodes))).orderBy(asc11(siteCrawlGraphNodes.sampleRank)).all();
|
|
77361
77461
|
const nodes = nodeRows.map(({ indexabilityReasons, canonicalNodeKey, ...row }) => ({
|
|
77362
77462
|
...row,
|
|
77363
77463
|
healthState: deriveSiteHealthState({ ...row, indexabilityReasons, canonicalNodeKey })
|
|
@@ -77388,7 +77488,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
77388
77488
|
eq60(siteCrawlGraphEdges.attemptId, snapshot.attemptId),
|
|
77389
77489
|
lt11(siteCrawlGraphEdges.sampleRank, maxEdges),
|
|
77390
77490
|
graphLinkKindFilter
|
|
77391
|
-
)).orderBy(
|
|
77491
|
+
)).orderBy(asc11(siteCrawlGraphEdges.sampleRank)).all();
|
|
77392
77492
|
const totalNodes = persistedLayout.totalNodes;
|
|
77393
77493
|
const totalEdges = persistedLayout.totalEdges;
|
|
77394
77494
|
const totalTemplateEdges = persistedLayout.totalTemplateEdges;
|
|
@@ -77489,7 +77589,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
77489
77589
|
inArray21(siteCrawlEdges.sourceNodeKey, frontier),
|
|
77490
77590
|
inArray21(siteCrawlEdges.targetNodeKey, frontier)
|
|
77491
77591
|
)
|
|
77492
|
-
)).orderBy(
|
|
77592
|
+
)).orderBy(asc11(siteCrawlEdges.edgeKey)).limit(maxEdges + maxNodes + 1).all();
|
|
77493
77593
|
if (candidates.length > maxEdges + maxNodes) queryTruncated = true;
|
|
77494
77594
|
const next = /* @__PURE__ */ new Set();
|
|
77495
77595
|
for (const edge of candidates.slice(0, maxEdges + maxNodes)) {
|
|
@@ -77639,7 +77739,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
77639
77739
|
eq60(siteCrawlEdges.relation, "anchor"),
|
|
77640
77740
|
isNotNull3(siteCrawlEdges.targetNodeKey),
|
|
77641
77741
|
inArray21(siteCrawlEdges.sourceNodeKey, frontier)
|
|
77642
|
-
)).orderBy(
|
|
77742
|
+
)).orderBy(asc11(siteCrawlEdges.edgeKey)).limit(SITE_HEALTH_PATH_MAX_VISITED_NODES + 1).all();
|
|
77643
77743
|
if (candidates.length > SITE_HEALTH_PATH_MAX_VISITED_NODES) truncated = true;
|
|
77644
77744
|
const candidateTargetKeys = [...new Set(candidates.map((edge) => edge.targetNodeKey).filter((nodeKey) => nodeKey != null))];
|
|
77645
77745
|
const persistedTargetKeys = new Set(candidateTargetKeys.length === 0 ? [] : app.db.select({ nodeKey: siteCrawlPages.nodeKey }).from(siteCrawlPages).where(and49(
|
|
@@ -78119,7 +78219,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
78119
78219
|
const healthState = parseSiteHealthState(request.query.healthState);
|
|
78120
78220
|
const limit = parseBoundedLimit(request.query.limit, 100, 200);
|
|
78121
78221
|
const offset = decodeCursor(request.query.cursor);
|
|
78122
|
-
const orderBy = request.query.sort === "score-desc" ? [desc25(siteCrawlPages.auditScore),
|
|
78222
|
+
const orderBy = request.query.sort === "score-desc" ? [desc25(siteCrawlPages.auditScore), asc11(siteCrawlPages.nodeKey)] : request.query.sort === "score-asc" ? [asc11(siteCrawlPages.auditScore), asc11(siteCrawlPages.nodeKey)] : request.query.sort === "path" ? [asc11(siteCrawlPages.path), asc11(siteCrawlPages.nodeKey)] : [asc11(siteCrawlPages.url), asc11(siteCrawlPages.nodeKey)];
|
|
78123
78223
|
let healthStateFilter = null;
|
|
78124
78224
|
if (healthState) {
|
|
78125
78225
|
const legacyRow = app.db.select({ id: siteCrawlPages.id }).from(siteCrawlPages).where(and49(
|
|
@@ -78269,7 +78369,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
78269
78369
|
const total = app.db.select({ value: count() }).from(siteCrawlEdges).where(where).get()?.value ?? 0;
|
|
78270
78370
|
const limit = parseBoundedLimit(request.query.limit, 100, 200);
|
|
78271
78371
|
const offset = decodeCursor(request.query.cursor);
|
|
78272
|
-
const rows = app.db.select().from(siteCrawlEdges).where(where).orderBy(
|
|
78372
|
+
const rows = app.db.select().from(siteCrawlEdges).where(where).orderBy(asc11(siteCrawlEdges.edgeKey)).limit(limit).offset(offset).all();
|
|
78273
78373
|
const nextOffset = offset + rows.length;
|
|
78274
78374
|
return {
|
|
78275
78375
|
project: project.name,
|
|
@@ -78332,8 +78432,8 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
78332
78432
|
const inboundMatch = request.query.nodeKey && request.query.url ? or13(eq60(siteCrawlEdges.targetNodeKey, request.query.nodeKey), eq60(siteCrawlEdges.targetUrl, request.query.url)) : request.query.nodeKey ? eq60(siteCrawlEdges.targetNodeKey, request.query.nodeKey) : eq60(siteCrawlEdges.targetUrl, request.query.url);
|
|
78333
78433
|
const outboundMatch = request.query.nodeKey && request.query.url ? or13(eq60(siteCrawlEdges.sourceNodeKey, request.query.nodeKey), eq60(siteCrawlEdges.sourceUrl, request.query.url)) : request.query.nodeKey ? eq60(siteCrawlEdges.sourceNodeKey, request.query.nodeKey) : eq60(siteCrawlEdges.sourceUrl, request.query.url);
|
|
78334
78434
|
const limit = parseBoundedLimit(request.query.limit, 50, 100);
|
|
78335
|
-
const inboundRows = app.db.select().from(siteCrawlEdges).where(and49(...scope, inboundMatch)).orderBy(
|
|
78336
|
-
const outboundRows = app.db.select().from(siteCrawlEdges).where(and49(...scope, outboundMatch)).orderBy(
|
|
78435
|
+
const inboundRows = app.db.select().from(siteCrawlEdges).where(and49(...scope, inboundMatch)).orderBy(asc11(siteCrawlEdges.edgeKey)).limit(limit + 1).all();
|
|
78436
|
+
const outboundRows = app.db.select().from(siteCrawlEdges).where(and49(...scope, outboundMatch)).orderBy(asc11(siteCrawlEdges.edgeKey)).limit(limit + 1).all();
|
|
78337
78437
|
return {
|
|
78338
78438
|
project: project.name,
|
|
78339
78439
|
hasCrawlData: true,
|
|
@@ -78385,7 +78485,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
78385
78485
|
const total = app.db.select({ value: count() }).from(siteCrawlFindings).where(where).get()?.value ?? 0;
|
|
78386
78486
|
const limit = parseBoundedLimit(request.query.limit, 100, 200);
|
|
78387
78487
|
const offset = decodeCursor(request.query.cursor);
|
|
78388
|
-
const rows = app.db.select().from(siteCrawlFindings).where(where).orderBy(
|
|
78488
|
+
const rows = app.db.select().from(siteCrawlFindings).where(where).orderBy(asc11(siteCrawlFindings.findingKey)).limit(limit).offset(offset).all();
|
|
78389
78489
|
const nextOffset = offset + rows.length;
|
|
78390
78490
|
const deadLinks = rows.map((row) => ({
|
|
78391
78491
|
findingKey: row.findingKey,
|
|
@@ -78533,7 +78633,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
78533
78633
|
auditedWhere,
|
|
78534
78634
|
isNotNull3(siteCrawlPages.auditScore),
|
|
78535
78635
|
lt11(siteCrawlPages.auditScore, 70)
|
|
78536
|
-
)).orderBy(
|
|
78636
|
+
)).orderBy(asc11(siteCrawlPages.auditScore), asc11(siteCrawlPages.nodeKey)).limit(LIVE_PAGE_HEALTH_CANDIDATE_LIMIT).all();
|
|
78537
78637
|
const examples = candidates.flatMap((candidate) => {
|
|
78538
78638
|
if (candidate.auditScore == null) return [];
|
|
78539
78639
|
const checksNeedingAttention = countLivePageHealthChecks(candidate.auditFields);
|
|
@@ -78769,6 +78869,7 @@ async function apiRoutes(app, opts) {
|
|
|
78769
78869
|
onProjectDeleting: opts.onProjectDeleting,
|
|
78770
78870
|
onProjectDeleted: opts.onProjectDeleted,
|
|
78771
78871
|
onProjectUpserted: opts.onProjectUpserted,
|
|
78872
|
+
onProjectCreated: opts.onProjectCreated,
|
|
78772
78873
|
onAliasesChanged: opts.onAliasesChanged,
|
|
78773
78874
|
providerAdapters: opts.providerAdapters
|
|
78774
78875
|
});
|
|
@@ -78801,6 +78902,7 @@ async function apiRoutes(app, opts) {
|
|
|
78801
78902
|
await api.register(applyRoutes, {
|
|
78802
78903
|
onScheduleUpdated: opts.onScheduleUpdated,
|
|
78803
78904
|
onProjectUpserted: opts.onProjectUpserted,
|
|
78905
|
+
onProjectCreated: opts.onProjectCreated,
|
|
78804
78906
|
onAliasesChanged: opts.onAliasesChanged,
|
|
78805
78907
|
providerAdapters: opts.providerAdapters,
|
|
78806
78908
|
allowLoopbackWebhooks: opts.allowLoopbackWebhooks,
|
|
@@ -79750,7 +79852,7 @@ var IntelligenceService = class {
|
|
|
79750
79852
|
}
|
|
79751
79853
|
sinceTimestamp = parsed;
|
|
79752
79854
|
}
|
|
79753
|
-
const allRuns = this.db.select().from(runs).where(and51(...analyzableRunPredicates(project.id))).orderBy(
|
|
79855
|
+
const allRuns = this.db.select().from(runs).where(and51(...analyzableRunPredicates(project.id))).orderBy(asc12(runs.finishedAt)).all();
|
|
79754
79856
|
const measuredRunIds = this.runIdsWithSnapshots(allRuns.map((r) => r.id));
|
|
79755
79857
|
const measuredRuns = allRuns.filter((r) => measuredRunIds.has(r.id));
|
|
79756
79858
|
let startIdx = 0;
|