@ainyc/canonry 4.46.1 → 4.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agent-workspace/skills/aero/SKILL.md +11 -0
- package/assets/agent-workspace/skills/aero/references/orchestration.md +8 -0
- package/assets/agent-workspace/skills/aero/soul.md +1 -1
- package/assets/agent-workspace/skills/canonry/SKILL.md +2 -0
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +14 -1
- package/assets/assets/{index-BDMNXVHa.css → index-DOP3oQmw.css} +1 -1
- package/assets/assets/index-DVK0M62U.js +214 -0
- package/assets/assets/vendor-markdown-DN2199pt.js +14 -0
- package/assets/assets/vendor-radix-Bvy4KXTI.js +45 -0
- package/assets/assets/vendor-recharts-DPeiXMwW.js +36 -0
- package/assets/assets/vendor-tanstack-DPXTJtWt.js +1 -0
- package/assets/index.html +6 -2
- package/dist/{chunk-K2TOOQ4F.js → chunk-M4USKXJ4.js} +15 -5
- package/dist/chunk-MYDJ25GO.js +5744 -0
- package/dist/{chunk-MM3A2CJK.js → chunk-QIG3TKL4.js} +1628 -754
- package/dist/{chunk-IYUI74JP.js → chunk-YVP5CTSV.js} +930 -623
- package/dist/cli.js +45 -30
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-R3KDVKIB.js → intelligence-service-TY7IPRST.js} +2 -2
- package/dist/mcp.js +8 -7
- package/package.json +7 -6
- package/assets/assets/index-CJWNAoK4.js +0 -302
- package/dist/chunk-PRNO52YC.js +0 -2365
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
loadConfig,
|
|
6
6
|
loadConfigRaw,
|
|
7
7
|
saveConfigPatch
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MYDJ25GO.js";
|
|
9
9
|
import {
|
|
10
10
|
DEFAULT_RUN_HISTORY_LIMIT,
|
|
11
11
|
IntelligenceService,
|
|
@@ -80,10 +80,13 @@ import {
|
|
|
80
80
|
smoothedRunDelta,
|
|
81
81
|
trafficSources,
|
|
82
82
|
usageCounters
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-M4USKXJ4.js";
|
|
84
84
|
import {
|
|
85
85
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
86
86
|
AGENT_PROVIDER_IDS,
|
|
87
|
+
AI_ENGINE_DOMAINS,
|
|
88
|
+
AI_ENGINE_SELF_DOMAINS,
|
|
89
|
+
AI_PROVIDER_INFRA_DOMAINS,
|
|
87
90
|
AgentProviderIds,
|
|
88
91
|
AppError,
|
|
89
92
|
CcReleaseSyncStatuses,
|
|
@@ -110,24 +113,50 @@ import {
|
|
|
110
113
|
TrafficSourceAuthModes,
|
|
111
114
|
TrafficSourceStatuses,
|
|
112
115
|
TrafficSourceTypes,
|
|
116
|
+
VERTEX_AI_SEARCH_PROXY_DOMAIN,
|
|
113
117
|
VerificationStatuses,
|
|
114
118
|
absolutizeProjectUrl,
|
|
115
119
|
actionConfidenceLabel,
|
|
116
120
|
agentBusy,
|
|
117
121
|
agentMemoryDeleteRequestSchema,
|
|
118
122
|
agentMemoryUpsertRequestSchema,
|
|
123
|
+
agentProvidersResponseDtoSchema,
|
|
124
|
+
auditLogEntrySchema,
|
|
119
125
|
authInvalid,
|
|
120
126
|
authRequired,
|
|
127
|
+
backlinkHistoryEntrySchema,
|
|
128
|
+
backlinkListResponseSchema,
|
|
129
|
+
backlinkSummaryDtoSchema,
|
|
130
|
+
backlinksInstallResultDtoSchema,
|
|
131
|
+
backlinksInstallStatusDtoSchema,
|
|
132
|
+
bingConnectResponseDtoSchema,
|
|
133
|
+
bingCoverageSnapshotDtoSchema,
|
|
134
|
+
bingCoverageSummaryDtoSchema,
|
|
135
|
+
bingIndexingRequestResponseDtoSchema,
|
|
136
|
+
bingKeywordStatsDtoSchema,
|
|
137
|
+
bingSetSiteResponseDtoSchema,
|
|
138
|
+
bingSitesResponseDtoSchema,
|
|
139
|
+
bingStatusDtoSchema,
|
|
140
|
+
bingUrlInspectionDtoSchema,
|
|
121
141
|
brandKeyFromText,
|
|
122
142
|
brandLabelFromDomain,
|
|
123
143
|
buildRunErrorFromMessages,
|
|
124
144
|
categorizeSource,
|
|
125
145
|
categoryLabel,
|
|
146
|
+
ccAvailableReleaseSchema,
|
|
147
|
+
ccCachedReleaseSchema,
|
|
148
|
+
ccReleaseSyncDtoSchema,
|
|
149
|
+
cdpStatusDtoSchema,
|
|
126
150
|
citationStateSchema,
|
|
127
151
|
citationStateToCited,
|
|
152
|
+
citationVisibilityResponseSchema,
|
|
128
153
|
clusterByCosine,
|
|
129
154
|
competitorBatchRequestSchema,
|
|
155
|
+
competitorDtoSchema,
|
|
130
156
|
contentActionLabel,
|
|
157
|
+
contentGapsResponseDtoSchema,
|
|
158
|
+
contentSourcesResponseDtoSchema,
|
|
159
|
+
contentTargetsResponseDtoSchema,
|
|
131
160
|
dedupeReportActions,
|
|
132
161
|
dedupeReportOpportunities,
|
|
133
162
|
deliveryFailed,
|
|
@@ -135,8 +164,13 @@ import {
|
|
|
135
164
|
deltaTone,
|
|
136
165
|
determineAnswerMentioned,
|
|
137
166
|
discoveryBucketSchema,
|
|
167
|
+
discoveryPromotePreviewSchema,
|
|
138
168
|
discoveryPromoteRequestSchema,
|
|
169
|
+
discoveryPromoteResultSchema,
|
|
139
170
|
discoveryRunRequestSchema,
|
|
171
|
+
discoverySessionDetailDtoSchema,
|
|
172
|
+
discoverySessionDtoSchema,
|
|
173
|
+
doctorReportSchema,
|
|
140
174
|
effectiveBrandNames,
|
|
141
175
|
effectiveDomains,
|
|
142
176
|
emptyCitationVisibility,
|
|
@@ -148,12 +182,29 @@ import {
|
|
|
148
182
|
formatIsoDate,
|
|
149
183
|
formatNumber,
|
|
150
184
|
formatRatio,
|
|
185
|
+
ga4AiReferralHistoryEntrySchema,
|
|
186
|
+
ga4SessionHistoryEntrySchema,
|
|
187
|
+
ga4SocialReferralHistoryEntrySchema,
|
|
188
|
+
ga4StatusDtoSchema,
|
|
189
|
+
ga4SyncResponseDtoSchema,
|
|
151
190
|
getProviderLocationHandling,
|
|
191
|
+
googleConnectionDtoSchema,
|
|
192
|
+
gscCoverageSnapshotDtoSchema,
|
|
193
|
+
gscCoverageSummaryDtoSchema,
|
|
194
|
+
gscDeindexedRowSchema,
|
|
195
|
+
gscPerformanceDailyDtoSchema,
|
|
196
|
+
gscSearchDataDtoSchema,
|
|
197
|
+
gscSiteListResponseDtoSchema,
|
|
198
|
+
gscSitemapListResponseDtoSchema,
|
|
199
|
+
gscUrlInspectionDtoSchema,
|
|
152
200
|
hasLocationLabel,
|
|
201
|
+
indexingRequestResponseDtoSchema,
|
|
153
202
|
internalError,
|
|
154
203
|
isAgentProviderId,
|
|
155
204
|
isBrowserProvider,
|
|
205
|
+
keywordDtoSchema,
|
|
156
206
|
keywordGenerateRequestSchema,
|
|
207
|
+
latestProjectRunDtoSchema,
|
|
157
208
|
locationContextSchema,
|
|
158
209
|
mentionStateFromAnswerMentioned,
|
|
159
210
|
missingDependency,
|
|
@@ -162,12 +213,16 @@ import {
|
|
|
162
213
|
normalizeUrlPath,
|
|
163
214
|
notFound,
|
|
164
215
|
notImplemented,
|
|
216
|
+
notificationDtoSchema,
|
|
165
217
|
parseRunError,
|
|
166
218
|
parseWindow,
|
|
167
219
|
pickClusterRepresentative,
|
|
168
220
|
projectConfigSchema,
|
|
221
|
+
projectDtoSchema,
|
|
222
|
+
projectReportDtoSchema,
|
|
169
223
|
projectUpsertRequestSchema,
|
|
170
224
|
providerError,
|
|
225
|
+
queryDtoSchema,
|
|
171
226
|
queryGenerateRequestSchema,
|
|
172
227
|
registrableDomain,
|
|
173
228
|
reportActionCategoryLabel,
|
|
@@ -178,22 +233,47 @@ import {
|
|
|
178
233
|
resolveConfigSpecQueries,
|
|
179
234
|
resolveLocations,
|
|
180
235
|
resolveSnapshotRequestQueries,
|
|
236
|
+
runDetailDtoSchema,
|
|
237
|
+
runDtoSchema,
|
|
181
238
|
runInProgress,
|
|
182
239
|
runNotCancellable,
|
|
183
240
|
runTriggerRequestSchema,
|
|
184
241
|
schedulableRunKindSchema,
|
|
242
|
+
scheduleDtoSchema,
|
|
185
243
|
scheduleUpsertRequestSchema,
|
|
186
244
|
serializeRunError,
|
|
245
|
+
settingsDtoSchema,
|
|
246
|
+
snapshotDiffResponseSchema,
|
|
247
|
+
snapshotListResponseSchema,
|
|
248
|
+
snapshotReportSchema,
|
|
187
249
|
snapshotRequestSchema,
|
|
188
250
|
summarizeCheckResults,
|
|
251
|
+
trafficBackfillResponseSchema,
|
|
189
252
|
trafficConnectVercelRequestSchema,
|
|
190
253
|
trafficConnectWordpressRequestSchema,
|
|
254
|
+
trafficEventsResponseSchema,
|
|
255
|
+
trafficSourceDetailDtoSchema,
|
|
256
|
+
trafficSourceDtoSchema,
|
|
257
|
+
trafficSourceListResponseSchema,
|
|
258
|
+
trafficStatusResponseSchema,
|
|
259
|
+
trafficSyncResponseSchema,
|
|
191
260
|
unsupportedKind,
|
|
192
261
|
validationError,
|
|
193
262
|
visibilityStateFromAnswerMentioned,
|
|
194
263
|
windowCutoff,
|
|
195
|
-
|
|
196
|
-
|
|
264
|
+
wordpressAuditPageDtoSchema,
|
|
265
|
+
wordpressBulkMetaResultDtoSchema,
|
|
266
|
+
wordpressDiffDtoSchema,
|
|
267
|
+
wordpressEnvSchema,
|
|
268
|
+
wordpressManualAssistDtoSchema,
|
|
269
|
+
wordpressOnboardResultDtoSchema,
|
|
270
|
+
wordpressPageDetailDtoSchema,
|
|
271
|
+
wordpressPageSummaryDtoSchema,
|
|
272
|
+
wordpressSchemaBlockDtoSchema,
|
|
273
|
+
wordpressSchemaDeployResultDtoSchema,
|
|
274
|
+
wordpressSchemaStatusResultDtoSchema,
|
|
275
|
+
wordpressStatusDtoSchema
|
|
276
|
+
} from "./chunk-QIG3TKL4.js";
|
|
197
277
|
|
|
198
278
|
// src/telemetry.ts
|
|
199
279
|
import crypto from "crypto";
|
|
@@ -559,7 +639,10 @@ import { eq as eq3, sql as sql2 } from "drizzle-orm";
|
|
|
559
639
|
|
|
560
640
|
// ../api-routes/src/helpers.ts
|
|
561
641
|
import crypto3 from "crypto";
|
|
562
|
-
import { eq as eq2, sql } from "drizzle-orm";
|
|
642
|
+
import { eq as eq2, ne, sql } from "drizzle-orm";
|
|
643
|
+
function notProbeRun() {
|
|
644
|
+
return ne(runs.trigger, RunTriggers.probe);
|
|
645
|
+
}
|
|
563
646
|
function resolveProject(db, name) {
|
|
564
647
|
const project = db.select().from(projects).where(eq2(projects.name, name)).get();
|
|
565
648
|
if (!project) {
|
|
@@ -2262,7 +2345,7 @@ function normalizeCompetitorList2(domains) {
|
|
|
2262
2345
|
}
|
|
2263
2346
|
|
|
2264
2347
|
// ../api-routes/src/history.ts
|
|
2265
|
-
import { eq as eq9, desc as desc2, inArray as inArray2 } from "drizzle-orm";
|
|
2348
|
+
import { and as and4, eq as eq9, desc as desc2, inArray as inArray2 } from "drizzle-orm";
|
|
2266
2349
|
|
|
2267
2350
|
// ../api-routes/src/notification-redaction.ts
|
|
2268
2351
|
var REDACTED_URL = {
|
|
@@ -2319,7 +2402,7 @@ async function historyRoutes(app) {
|
|
|
2319
2402
|
const project = resolveProject(app.db, request.params.name);
|
|
2320
2403
|
const limit = parseInt(request.query.limit ?? "50", 10);
|
|
2321
2404
|
const offset = parseInt(request.query.offset ?? "0", 10);
|
|
2322
|
-
const projectRuns = app.db.select({ id: runs.id }).from(runs).where(eq9(runs.projectId, project.id)).all();
|
|
2405
|
+
const projectRuns = app.db.select({ id: runs.id }).from(runs).where(and4(eq9(runs.projectId, project.id), notProbeRun())).all();
|
|
2323
2406
|
if (projectRuns.length === 0) {
|
|
2324
2407
|
return reply.send({ snapshots: [], total: 0 });
|
|
2325
2408
|
}
|
|
@@ -2368,7 +2451,7 @@ async function historyRoutes(app) {
|
|
|
2368
2451
|
app.get("/projects/:name/timeline", async (request, reply) => {
|
|
2369
2452
|
const project = resolveProject(app.db, request.params.name);
|
|
2370
2453
|
const projectQueries = app.db.select().from(queries).where(eq9(queries.projectId, project.id)).all();
|
|
2371
|
-
const projectRuns = app.db.select().from(runs).where(eq9(runs.projectId, project.id)).orderBy(runs.createdAt).all();
|
|
2454
|
+
const projectRuns = app.db.select().from(runs).where(and4(eq9(runs.projectId, project.id), notProbeRun())).orderBy(runs.createdAt).all();
|
|
2372
2455
|
if (projectRuns.length === 0 || projectQueries.length === 0) {
|
|
2373
2456
|
return reply.send([]);
|
|
2374
2457
|
}
|
|
@@ -2553,13 +2636,13 @@ function formatAuditEntry(row) {
|
|
|
2553
2636
|
}
|
|
2554
2637
|
|
|
2555
2638
|
// ../api-routes/src/analytics.ts
|
|
2556
|
-
import { eq as eq10, desc as desc3, inArray as inArray3 } from "drizzle-orm";
|
|
2639
|
+
import { and as and5, eq as eq10, desc as desc3, inArray as inArray3 } from "drizzle-orm";
|
|
2557
2640
|
async function analyticsRoutes(app) {
|
|
2558
2641
|
app.get("/projects/:name/analytics/metrics", async (request, reply) => {
|
|
2559
2642
|
const project = resolveProject(app.db, request.params.name);
|
|
2560
2643
|
const window = parseWindow(request.query.window);
|
|
2561
2644
|
const cutoff = windowCutoff(window);
|
|
2562
|
-
const projectRuns = app.db.select().from(runs).where(eq10(runs.projectId, project.id)).orderBy(runs.createdAt).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
|
|
2645
|
+
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);
|
|
2563
2646
|
if (projectRuns.length === 0) {
|
|
2564
2647
|
return reply.send({
|
|
2565
2648
|
window,
|
|
@@ -2607,14 +2690,14 @@ async function analyticsRoutes(app) {
|
|
|
2607
2690
|
const project = resolveProject(app.db, request.params.name);
|
|
2608
2691
|
const window = parseWindow(request.query.window);
|
|
2609
2692
|
const cutoff = windowCutoff(window);
|
|
2610
|
-
const completedRuns = app.db.select().from(runs).where(eq10(runs.projectId, project.id)).orderBy(desc3(runs.createdAt), desc3(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial");
|
|
2693
|
+
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");
|
|
2611
2694
|
const latestGroup = groupRunsByCreatedAt(completedRuns)[0] ?? [];
|
|
2612
2695
|
const latestGroupRunIds = latestGroup.map((r) => r.id);
|
|
2613
2696
|
const latestRun = pickGroupRepresentative(latestGroup);
|
|
2614
2697
|
if (!latestRun) {
|
|
2615
2698
|
return reply.send({ cited: [], gap: [], uncited: [], mentionedQueries: [], mentionGap: [], notMentioned: [], runId: "", window });
|
|
2616
2699
|
}
|
|
2617
|
-
const windowRuns = app.db.select().from(runs).where(eq10(runs.projectId, project.id)).orderBy(runs.createdAt).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
|
|
2700
|
+
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);
|
|
2618
2701
|
const windowRunIds = windowRuns.map((r) => r.id);
|
|
2619
2702
|
const runIdToCreatedAt = new Map(windowRuns.map((r) => [r.id, r.createdAt]));
|
|
2620
2703
|
const consistencyMap = /* @__PURE__ */ new Map();
|
|
@@ -2730,7 +2813,7 @@ async function analyticsRoutes(app) {
|
|
|
2730
2813
|
const project = resolveProject(app.db, request.params.name);
|
|
2731
2814
|
const window = parseWindow(request.query.window);
|
|
2732
2815
|
const cutoff = windowCutoff(window);
|
|
2733
|
-
const windowRuns = app.db.select().from(runs).where(eq10(runs.projectId, project.id)).orderBy(desc3(runs.createdAt), desc3(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
|
|
2816
|
+
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);
|
|
2734
2817
|
if (windowRuns.length === 0) {
|
|
2735
2818
|
return reply.send({ overall: [], byQuery: {}, runId: "", window });
|
|
2736
2819
|
}
|
|
@@ -2764,16 +2847,10 @@ async function analyticsRoutes(app) {
|
|
|
2764
2847
|
return reply.send({ overall, byQuery, runId: latestRunId, window });
|
|
2765
2848
|
});
|
|
2766
2849
|
}
|
|
2767
|
-
var PROVIDER_INFRA_DOMAINS = /* @__PURE__ */ new Set([
|
|
2768
|
-
"vertexaisearch.cloud.google.com",
|
|
2769
|
-
"openai.com",
|
|
2770
|
-
"anthropic.com",
|
|
2771
|
-
"googleapis.com"
|
|
2772
|
-
]);
|
|
2773
2850
|
function isProviderInfraDomain(uri) {
|
|
2774
2851
|
try {
|
|
2775
2852
|
const host = new URL(uri).hostname.toLowerCase();
|
|
2776
|
-
for (const blocked of
|
|
2853
|
+
for (const blocked of AI_PROVIDER_INFRA_DOMAINS) {
|
|
2777
2854
|
if (host === blocked || host.endsWith(`.${blocked}`)) return true;
|
|
2778
2855
|
}
|
|
2779
2856
|
} catch {
|
|
@@ -2900,7 +2977,7 @@ function buildCategoryCounts(counts) {
|
|
|
2900
2977
|
}
|
|
2901
2978
|
|
|
2902
2979
|
// ../api-routes/src/intelligence.ts
|
|
2903
|
-
import { eq as eq11, desc as desc4, and as
|
|
2980
|
+
import { eq as eq11, desc as desc4, and as and6, inArray as inArray4 } from "drizzle-orm";
|
|
2904
2981
|
function emptyHealthSnapshot(projectId) {
|
|
2905
2982
|
return {
|
|
2906
2983
|
id: `no-data:${projectId}`,
|
|
@@ -2989,7 +3066,7 @@ async function intelligenceRoutes(app) {
|
|
|
2989
3066
|
if (request.query.runId) {
|
|
2990
3067
|
conditions.push(eq11(insights.runId, request.query.runId));
|
|
2991
3068
|
}
|
|
2992
|
-
const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] :
|
|
3069
|
+
const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] : and6(...conditions)).orderBy(desc4(insights.createdAt)).all();
|
|
2993
3070
|
const showDismissed = request.query.dismissed === "true";
|
|
2994
3071
|
const result = rows.filter((r) => showDismissed || !r.dismissed).map(mapInsightRow);
|
|
2995
3072
|
return reply.send(result);
|
|
@@ -3013,15 +3090,18 @@ async function intelligenceRoutes(app) {
|
|
|
3013
3090
|
});
|
|
3014
3091
|
app.get("/projects/:name/health/latest", async (request, reply) => {
|
|
3015
3092
|
const project = resolveProject(app.db, request.params.name);
|
|
3016
|
-
const projectVisRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(
|
|
3093
|
+
const projectVisRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(and6(
|
|
3017
3094
|
eq11(runs.projectId, project.id),
|
|
3018
3095
|
eq11(runs.kind, RunKinds["answer-visibility"]),
|
|
3019
|
-
inArray4(runs.status, [RunStatuses.completed, RunStatuses.partial])
|
|
3096
|
+
inArray4(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
3097
|
+
// Health-latest is the dashboard headline; probe runs must not
|
|
3098
|
+
// displace the most recent real visibility sweep.
|
|
3099
|
+
notProbeRun()
|
|
3020
3100
|
)).orderBy(desc4(runs.createdAt), desc4(runs.id)).all();
|
|
3021
3101
|
const latestGroup = groupRunsByCreatedAt(projectVisRuns)[0] ?? [];
|
|
3022
3102
|
const latestGroupRunIds = latestGroup.map((r) => r.id);
|
|
3023
3103
|
if (latestGroupRunIds.length > 0) {
|
|
3024
|
-
const groupRows = app.db.select().from(healthSnapshots).where(
|
|
3104
|
+
const groupRows = app.db.select().from(healthSnapshots).where(and6(
|
|
3025
3105
|
eq11(healthSnapshots.projectId, project.id),
|
|
3026
3106
|
inArray4(healthSnapshots.runId, latestGroupRunIds)
|
|
3027
3107
|
)).all();
|
|
@@ -3045,7 +3125,7 @@ async function intelligenceRoutes(app) {
|
|
|
3045
3125
|
}
|
|
3046
3126
|
|
|
3047
3127
|
// ../api-routes/src/report.ts
|
|
3048
|
-
import { and as
|
|
3128
|
+
import { and as and8, desc as desc6, eq as eq13, gte, inArray as inArray6, lt, lte, ne as ne2, or as or3, sql as sql5 } from "drizzle-orm";
|
|
3049
3129
|
|
|
3050
3130
|
// ../api-routes/src/report-renderer.ts
|
|
3051
3131
|
var COLORS = {
|
|
@@ -5285,7 +5365,7 @@ function renderReportHtml(report, opts = {}) {
|
|
|
5285
5365
|
}
|
|
5286
5366
|
|
|
5287
5367
|
// ../api-routes/src/content-data.ts
|
|
5288
|
-
import { and as
|
|
5368
|
+
import { and as and7, eq as eq12, desc as desc5, inArray as inArray5 } from "drizzle-orm";
|
|
5289
5369
|
var RECENT_RUNS_WINDOW = 5;
|
|
5290
5370
|
function loadOrchestratorInput(db, project, locationFilter = void 0) {
|
|
5291
5371
|
const projectId = project.id;
|
|
@@ -5409,13 +5489,16 @@ function listCompetitorDomains(db, projectId) {
|
|
|
5409
5489
|
}
|
|
5410
5490
|
function listRecentAnswerVisibilityRunIds(db, projectId, limit, locationFilter) {
|
|
5411
5491
|
const rows = db.select({ id: runs.id, location: runs.location }).from(runs).where(
|
|
5412
|
-
|
|
5492
|
+
and7(
|
|
5413
5493
|
eq12(runs.projectId, projectId),
|
|
5414
5494
|
eq12(runs.kind, RunKinds["answer-visibility"]),
|
|
5415
5495
|
// Queued/running/failed/cancelled runs may have partial or no
|
|
5416
5496
|
// snapshots; including them risks pointing latestRunId at a run with
|
|
5417
5497
|
// no usable evidence.
|
|
5418
|
-
inArray5(runs.status, [RunStatuses.completed, RunStatuses.partial])
|
|
5498
|
+
inArray5(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
5499
|
+
// Probe runs are operator/agent test runs; they must not poison the
|
|
5500
|
+
// recent-runs window the content engine uses to recommend actions.
|
|
5501
|
+
notProbeRun()
|
|
5419
5502
|
)
|
|
5420
5503
|
).orderBy(desc5(runs.createdAt)).all();
|
|
5421
5504
|
const filtered = locationFilter === void 0 ? rows : rows.filter((r) => (r.location ?? null) === locationFilter);
|
|
@@ -5776,7 +5859,7 @@ function buildGscSection(db, projectId, projectBrandNames, canonicalDomain, trac
|
|
|
5776
5859
|
}
|
|
5777
5860
|
function buildGaSection(db, projectId) {
|
|
5778
5861
|
const windowSummary = db.select().from(gaTrafficWindowSummaries).where(
|
|
5779
|
-
|
|
5862
|
+
and8(
|
|
5780
5863
|
eq13(gaTrafficWindowSummaries.projectId, projectId),
|
|
5781
5864
|
eq13(gaTrafficWindowSummaries.windowKey, "30d")
|
|
5782
5865
|
)
|
|
@@ -5954,9 +6037,9 @@ function nonSubresourceReferralPathCondition() {
|
|
|
5954
6037
|
}
|
|
5955
6038
|
function buildServerActivity(db, projectId) {
|
|
5956
6039
|
const sourceRows = db.select({ id: trafficSources.id }).from(trafficSources).where(
|
|
5957
|
-
|
|
6040
|
+
and8(
|
|
5958
6041
|
eq13(trafficSources.projectId, projectId),
|
|
5959
|
-
|
|
6042
|
+
ne2(trafficSources.status, TrafficSourceStatuses.archived)
|
|
5960
6043
|
)
|
|
5961
6044
|
).all();
|
|
5962
6045
|
if (sourceRows.length === 0) return null;
|
|
@@ -5970,7 +6053,7 @@ function buildServerActivity(db, projectId) {
|
|
|
5970
6053
|
const trendStart = new Date(trendStartMs).toISOString();
|
|
5971
6054
|
const sumVerifiedCrawlers = (windowStartIso, windowEndIso, exclusiveEnd = false) => Number(
|
|
5972
6055
|
db.select({ total: sql5`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
|
|
5973
|
-
|
|
6056
|
+
and8(
|
|
5974
6057
|
eq13(crawlerEventsHourly.projectId, projectId),
|
|
5975
6058
|
eq13(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
|
|
5976
6059
|
gte(crawlerEventsHourly.tsHour, windowStartIso),
|
|
@@ -5980,9 +6063,9 @@ function buildServerActivity(db, projectId) {
|
|
|
5980
6063
|
);
|
|
5981
6064
|
const sumUnverifiedCrawlers = (windowStartIso, windowEndIso, exclusiveEnd = false) => Number(
|
|
5982
6065
|
db.select({ total: sql5`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
|
|
5983
|
-
|
|
6066
|
+
and8(
|
|
5984
6067
|
eq13(crawlerEventsHourly.projectId, projectId),
|
|
5985
|
-
|
|
6068
|
+
ne2(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
|
|
5986
6069
|
gte(crawlerEventsHourly.tsHour, windowStartIso),
|
|
5987
6070
|
exclusiveEnd ? lt(crawlerEventsHourly.tsHour, windowEndIso) : lte(crawlerEventsHourly.tsHour, windowEndIso)
|
|
5988
6071
|
)
|
|
@@ -5990,7 +6073,7 @@ function buildServerActivity(db, projectId) {
|
|
|
5990
6073
|
);
|
|
5991
6074
|
const sumReferrals = (windowStartIso, windowEndIso, exclusiveEnd = false) => Number(
|
|
5992
6075
|
db.select({ total: sql5`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
|
|
5993
|
-
|
|
6076
|
+
and8(
|
|
5994
6077
|
eq13(aiReferralEventsHourly.projectId, projectId),
|
|
5995
6078
|
nonSubresourceReferralPathCondition(),
|
|
5996
6079
|
gte(aiReferralEventsHourly.tsHour, windowStartIso),
|
|
@@ -6009,7 +6092,7 @@ function buildServerActivity(db, projectId) {
|
|
|
6009
6092
|
verificationStatus: crawlerEventsHourly.verificationStatus,
|
|
6010
6093
|
hits: sql5`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
|
|
6011
6094
|
}).from(crawlerEventsHourly).where(
|
|
6012
|
-
|
|
6095
|
+
and8(
|
|
6013
6096
|
eq13(crawlerEventsHourly.projectId, projectId),
|
|
6014
6097
|
gte(crawlerEventsHourly.tsHour, headlineStart),
|
|
6015
6098
|
lte(crawlerEventsHourly.tsHour, headlineEnd)
|
|
@@ -6019,7 +6102,7 @@ function buildServerActivity(db, projectId) {
|
|
|
6019
6102
|
operator: crawlerEventsHourly.operator,
|
|
6020
6103
|
hits: sql5`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
|
|
6021
6104
|
}).from(crawlerEventsHourly).where(
|
|
6022
|
-
|
|
6105
|
+
and8(
|
|
6023
6106
|
eq13(crawlerEventsHourly.projectId, projectId),
|
|
6024
6107
|
eq13(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
|
|
6025
6108
|
gte(crawlerEventsHourly.tsHour, priorStart),
|
|
@@ -6030,7 +6113,7 @@ function buildServerActivity(db, projectId) {
|
|
|
6030
6113
|
operator: aiReferralEventsHourly.operator,
|
|
6031
6114
|
hits: sql5`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)`
|
|
6032
6115
|
}).from(aiReferralEventsHourly).where(
|
|
6033
|
-
|
|
6116
|
+
and8(
|
|
6034
6117
|
eq13(aiReferralEventsHourly.projectId, projectId),
|
|
6035
6118
|
nonSubresourceReferralPathCondition(),
|
|
6036
6119
|
gte(aiReferralEventsHourly.tsHour, headlineStart),
|
|
@@ -6071,7 +6154,7 @@ function buildServerActivity(db, projectId) {
|
|
|
6071
6154
|
hits: sql5`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`,
|
|
6072
6155
|
operators: sql5`COUNT(DISTINCT ${crawlerEventsHourly.operator})`
|
|
6073
6156
|
}).from(crawlerEventsHourly).where(
|
|
6074
|
-
|
|
6157
|
+
and8(
|
|
6075
6158
|
eq13(crawlerEventsHourly.projectId, projectId),
|
|
6076
6159
|
eq13(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
|
|
6077
6160
|
gte(crawlerEventsHourly.tsHour, headlineStart),
|
|
@@ -6088,7 +6171,7 @@ function buildServerActivity(db, projectId) {
|
|
|
6088
6171
|
arrivals: sql5`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)`,
|
|
6089
6172
|
landingPaths: sql5`COUNT(DISTINCT ${aiReferralEventsHourly.landingPathNormalized})`
|
|
6090
6173
|
}).from(aiReferralEventsHourly).where(
|
|
6091
|
-
|
|
6174
|
+
and8(
|
|
6092
6175
|
eq13(aiReferralEventsHourly.projectId, projectId),
|
|
6093
6176
|
nonSubresourceReferralPathCondition(),
|
|
6094
6177
|
gte(aiReferralEventsHourly.tsHour, headlineStart),
|
|
@@ -6105,7 +6188,7 @@ function buildServerActivity(db, projectId) {
|
|
|
6105
6188
|
arrivals: sql5`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)`,
|
|
6106
6189
|
products: sql5`COUNT(DISTINCT ${aiReferralEventsHourly.product})`
|
|
6107
6190
|
}).from(aiReferralEventsHourly).where(
|
|
6108
|
-
|
|
6191
|
+
and8(
|
|
6109
6192
|
eq13(aiReferralEventsHourly.projectId, projectId),
|
|
6110
6193
|
nonSubresourceReferralPathCondition(),
|
|
6111
6194
|
gte(aiReferralEventsHourly.tsHour, headlineStart),
|
|
@@ -6121,7 +6204,7 @@ function buildServerActivity(db, projectId) {
|
|
|
6121
6204
|
date: sql5`SUBSTR(${crawlerEventsHourly.tsHour}, 1, 10)`,
|
|
6122
6205
|
hits: sql5`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
|
|
6123
6206
|
}).from(crawlerEventsHourly).where(
|
|
6124
|
-
|
|
6207
|
+
and8(
|
|
6125
6208
|
eq13(crawlerEventsHourly.projectId, projectId),
|
|
6126
6209
|
eq13(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
|
|
6127
6210
|
gte(crawlerEventsHourly.tsHour, trendStart),
|
|
@@ -6132,7 +6215,7 @@ function buildServerActivity(db, projectId) {
|
|
|
6132
6215
|
date: sql5`SUBSTR(${aiReferralEventsHourly.tsHour}, 1, 10)`,
|
|
6133
6216
|
hits: sql5`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)`
|
|
6134
6217
|
}).from(aiReferralEventsHourly).where(
|
|
6135
|
-
|
|
6218
|
+
and8(
|
|
6136
6219
|
eq13(aiReferralEventsHourly.projectId, projectId),
|
|
6137
6220
|
nonSubresourceReferralPathCondition(),
|
|
6138
6221
|
gte(aiReferralEventsHourly.tsHour, trendStart),
|
|
@@ -6207,7 +6290,7 @@ function buildIndexingHealth(db, projectId) {
|
|
|
6207
6290
|
return null;
|
|
6208
6291
|
}
|
|
6209
6292
|
function buildCitationsTrend(db, projectId, queryLookup, locationFilter) {
|
|
6210
|
-
const visibilityRuns = db.select().from(runs).where(
|
|
6293
|
+
const visibilityRuns = db.select().from(runs).where(and8(eq13(runs.projectId, projectId), eq13(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).all().filter((r) => locationFilter === void 0 || (r.location ?? null) === locationFilter);
|
|
6211
6294
|
const totalQueries = queryLookup.byId.size;
|
|
6212
6295
|
const points = [];
|
|
6213
6296
|
for (const run of visibilityRuns) {
|
|
@@ -6253,14 +6336,15 @@ function buildCitationsTrend(db, projectId, queryLookup, locationFilter) {
|
|
|
6253
6336
|
}
|
|
6254
6337
|
function buildInsightList(db, projectId, locationFilter) {
|
|
6255
6338
|
const recentRunIds = db.select({ id: runs.id, location: runs.location }).from(runs).where(
|
|
6256
|
-
|
|
6339
|
+
and8(
|
|
6257
6340
|
eq13(runs.projectId, projectId),
|
|
6258
6341
|
eq13(runs.kind, RunKinds["answer-visibility"]),
|
|
6259
|
-
or3(eq13(runs.status, RunStatuses.completed), eq13(runs.status, RunStatuses.partial))
|
|
6342
|
+
or3(eq13(runs.status, RunStatuses.completed), eq13(runs.status, RunStatuses.partial)),
|
|
6343
|
+
notProbeRun()
|
|
6260
6344
|
)
|
|
6261
6345
|
).orderBy(desc6(runs.createdAt)).all().filter((r) => locationFilter === void 0 || (r.location ?? null) === locationFilter).slice(0, INSIGHT_LOOKBACK_RUNS).map((r) => r.id);
|
|
6262
6346
|
if (recentRunIds.length === 0) return [];
|
|
6263
|
-
const rows = db.select().from(insights).where(
|
|
6347
|
+
const rows = db.select().from(insights).where(and8(eq13(insights.projectId, projectId), inArray6(insights.runId, recentRunIds))).orderBy(desc6(insights.createdAt)).all();
|
|
6264
6348
|
const severityRank = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
6265
6349
|
const flat = rows.filter((r) => !r.dismissed).map((r) => {
|
|
6266
6350
|
const recommendation = parseJsonColumn(r.recommendation, null);
|
|
@@ -6805,7 +6889,7 @@ function buildWhatsChanged(input) {
|
|
|
6805
6889
|
function buildProjectReport(db, projectName) {
|
|
6806
6890
|
const project = resolveProject(db, projectName);
|
|
6807
6891
|
const queryLookup = loadQueryLookup(db, project.id);
|
|
6808
|
-
const allRuns = db.select().from(runs).where(eq13(runs.projectId, project.id)).orderBy(desc6(runs.createdAt), desc6(runs.id)).all();
|
|
6892
|
+
const allRuns = db.select().from(runs).where(and8(eq13(runs.projectId, project.id), notProbeRun())).orderBy(desc6(runs.createdAt), desc6(runs.id)).all();
|
|
6809
6893
|
const visibilityRuns = allRuns.filter((r) => r.kind === RunKinds["answer-visibility"]);
|
|
6810
6894
|
const completedVisRunGroups = groupRunsByCreatedAt(
|
|
6811
6895
|
visibilityRuns.filter((r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial)
|
|
@@ -7033,7 +7117,7 @@ async function reportRoutes(app) {
|
|
|
7033
7117
|
}
|
|
7034
7118
|
|
|
7035
7119
|
// ../api-routes/src/citations.ts
|
|
7036
|
-
import { eq as eq14, inArray as inArray7 } from "drizzle-orm";
|
|
7120
|
+
import { and as and9, eq as eq14, inArray as inArray7 } from "drizzle-orm";
|
|
7037
7121
|
async function citationRoutes(app) {
|
|
7038
7122
|
app.get("/projects/:name/citations/visibility", async (request, reply) => {
|
|
7039
7123
|
const project = resolveProject(app.db, request.params.name);
|
|
@@ -7042,7 +7126,7 @@ async function citationRoutes(app) {
|
|
|
7042
7126
|
if (projectQueries.length === 0) {
|
|
7043
7127
|
return reply.send(emptyCitationVisibility("no-queries"));
|
|
7044
7128
|
}
|
|
7045
|
-
const projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(eq14(runs.projectId, project.id)).all();
|
|
7129
|
+
const projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(and9(eq14(runs.projectId, project.id), notProbeRun())).all();
|
|
7046
7130
|
if (projectRuns.length === 0) {
|
|
7047
7131
|
return reply.send(emptyCitationVisibility("no-runs-yet"));
|
|
7048
7132
|
}
|
|
@@ -7198,7 +7282,7 @@ function normalizeDomain2(domain) {
|
|
|
7198
7282
|
}
|
|
7199
7283
|
|
|
7200
7284
|
// ../api-routes/src/composites.ts
|
|
7201
|
-
import { eq as eq15, and as
|
|
7285
|
+
import { eq as eq15, and as and10, desc as desc7, sql as sql6, like, or as or4, inArray as inArray8 } from "drizzle-orm";
|
|
7202
7286
|
var TOP_INSIGHT_LIMIT = 5;
|
|
7203
7287
|
var SEARCH_HIT_HARD_LIMIT = 50;
|
|
7204
7288
|
var SEARCH_SNIPPET_RADIUS = 80;
|
|
@@ -7216,7 +7300,7 @@ async function compositeRoutes(app) {
|
|
|
7216
7300
|
const project = resolveProject(app.db, request.params.name);
|
|
7217
7301
|
const filterLocation = (request.query.location ?? "").trim() || null;
|
|
7218
7302
|
const sinceIso = parseSinceFilter(request.query.since);
|
|
7219
|
-
const allRunsRaw = app.db.select().from(runs).where(eq15(runs.projectId, project.id)).orderBy(desc7(runs.createdAt), desc7(runs.id)).all();
|
|
7303
|
+
const allRunsRaw = app.db.select().from(runs).where(and10(eq15(runs.projectId, project.id), notProbeRun())).orderBy(desc7(runs.createdAt), desc7(runs.id)).all();
|
|
7220
7304
|
const allRuns = allRunsRaw.filter((r) => runMatchesFilters(r, filterLocation, sinceIso));
|
|
7221
7305
|
const totalRuns = allRuns.length;
|
|
7222
7306
|
const visibilityRuns = allRuns.filter((r) => r.kind === RunKinds["answer-visibility"]);
|
|
@@ -7345,7 +7429,7 @@ async function compositeRoutes(app) {
|
|
|
7345
7429
|
rawResponse: querySnapshots.rawResponse,
|
|
7346
7430
|
createdAt: querySnapshots.createdAt
|
|
7347
7431
|
}).from(querySnapshots).innerJoin(queries, eq15(querySnapshots.queryId, queries.id)).where(
|
|
7348
|
-
|
|
7432
|
+
and10(
|
|
7349
7433
|
eq15(queries.projectId, project.id),
|
|
7350
7434
|
or4(
|
|
7351
7435
|
sql6`${querySnapshots.answerText} LIKE ${pattern} ESCAPE '\\'`,
|
|
@@ -7356,7 +7440,7 @@ async function compositeRoutes(app) {
|
|
|
7356
7440
|
)
|
|
7357
7441
|
).orderBy(desc7(querySnapshots.createdAt)).limit(limit + 1).all());
|
|
7358
7442
|
const insightMatches = app.db.select().from(insights).where(
|
|
7359
|
-
|
|
7443
|
+
and10(
|
|
7360
7444
|
eq15(insights.projectId, project.id),
|
|
7361
7445
|
or4(
|
|
7362
7446
|
like(insights.title, pattern),
|
|
@@ -7529,7 +7613,7 @@ function buildSuggestedQueriesFromGsc(app, projectId, trackedQueries) {
|
|
|
7529
7613
|
// NULLIF guards the degenerate impressions=0 case (SQLite returns NULL,
|
|
7530
7614
|
// which the JS coerces to 0 — caught by the impression floor anyway).
|
|
7531
7615
|
avgPosition: sql6`COALESCE(SUM(${gscSearchData.position} * ${gscSearchData.impressions}) * 1.0 / NULLIF(SUM(${gscSearchData.impressions}), 0), 0)`
|
|
7532
|
-
}).from(gscSearchData).where(
|
|
7616
|
+
}).from(gscSearchData).where(and10(
|
|
7533
7617
|
eq15(gscSearchData.projectId, projectId),
|
|
7534
7618
|
sql6`${gscSearchData.date} >= ${cutoff}`,
|
|
7535
7619
|
sql6`${gscSearchData.impressions} > 0`
|
|
@@ -7718,6 +7802,7 @@ function formatProject2(row) {
|
|
|
7718
7802
|
language: row.language,
|
|
7719
7803
|
tags: parseJsonColumn(row.tags, []),
|
|
7720
7804
|
labels: parseJsonColumn(row.labels, {}),
|
|
7805
|
+
providers: parseJsonColumn(row.providers, []),
|
|
7721
7806
|
locations: parseJsonColumn(row.locations, []),
|
|
7722
7807
|
defaultLocation: row.defaultLocation,
|
|
7723
7808
|
autoExtractBacklinks: row.autoExtractBacklinks === 1,
|
|
@@ -7864,6 +7949,141 @@ function parseLimitParam(raw) {
|
|
|
7864
7949
|
return parsed;
|
|
7865
7950
|
}
|
|
7866
7951
|
|
|
7952
|
+
// ../api-routes/src/openapi-schemas.ts
|
|
7953
|
+
import { z } from "zod";
|
|
7954
|
+
var SCHEMA_TABLE = {
|
|
7955
|
+
AgentProvidersResponseDto: agentProvidersResponseDtoSchema,
|
|
7956
|
+
AuditLogEntry: auditLogEntrySchema,
|
|
7957
|
+
BacklinkHistoryEntry: backlinkHistoryEntrySchema,
|
|
7958
|
+
BacklinkListResponse: backlinkListResponseSchema,
|
|
7959
|
+
BacklinkSummaryDto: backlinkSummaryDtoSchema,
|
|
7960
|
+
BacklinksInstallResultDto: backlinksInstallResultDtoSchema,
|
|
7961
|
+
BacklinksInstallStatusDto: backlinksInstallStatusDtoSchema,
|
|
7962
|
+
BingConnectResponseDto: bingConnectResponseDtoSchema,
|
|
7963
|
+
BingCoverageSnapshotDto: bingCoverageSnapshotDtoSchema,
|
|
7964
|
+
BingCoverageSummaryDto: bingCoverageSummaryDtoSchema,
|
|
7965
|
+
BingIndexingRequestResponseDto: bingIndexingRequestResponseDtoSchema,
|
|
7966
|
+
BingKeywordStatsDto: bingKeywordStatsDtoSchema,
|
|
7967
|
+
BingSetSiteResponseDto: bingSetSiteResponseDtoSchema,
|
|
7968
|
+
BingSitesResponseDto: bingSitesResponseDtoSchema,
|
|
7969
|
+
BingStatusDto: bingStatusDtoSchema,
|
|
7970
|
+
BingUrlInspectionDto: bingUrlInspectionDtoSchema,
|
|
7971
|
+
CcAvailableRelease: ccAvailableReleaseSchema,
|
|
7972
|
+
CcCachedRelease: ccCachedReleaseSchema,
|
|
7973
|
+
CcReleaseSyncDto: ccReleaseSyncDtoSchema,
|
|
7974
|
+
CdpStatusDto: cdpStatusDtoSchema,
|
|
7975
|
+
CitationVisibilityResponse: citationVisibilityResponseSchema,
|
|
7976
|
+
CompetitorDto: competitorDtoSchema,
|
|
7977
|
+
ContentGapsResponseDto: contentGapsResponseDtoSchema,
|
|
7978
|
+
ContentSourcesResponseDto: contentSourcesResponseDtoSchema,
|
|
7979
|
+
ContentTargetsResponseDto: contentTargetsResponseDtoSchema,
|
|
7980
|
+
DiscoveryPromotePreview: discoveryPromotePreviewSchema,
|
|
7981
|
+
DiscoveryPromoteResult: discoveryPromoteResultSchema,
|
|
7982
|
+
DiscoverySessionDetailDto: discoverySessionDetailDtoSchema,
|
|
7983
|
+
DiscoverySessionDto: discoverySessionDtoSchema,
|
|
7984
|
+
DoctorReportDto: doctorReportSchema,
|
|
7985
|
+
GA4AiReferralHistoryEntry: ga4AiReferralHistoryEntrySchema,
|
|
7986
|
+
GA4SessionHistoryEntry: ga4SessionHistoryEntrySchema,
|
|
7987
|
+
GA4SocialReferralHistoryEntry: ga4SocialReferralHistoryEntrySchema,
|
|
7988
|
+
GA4StatusDto: ga4StatusDtoSchema,
|
|
7989
|
+
GA4SyncResponseDto: ga4SyncResponseDtoSchema,
|
|
7990
|
+
GoogleConnectionDto: googleConnectionDtoSchema,
|
|
7991
|
+
GscCoverageSnapshotDto: gscCoverageSnapshotDtoSchema,
|
|
7992
|
+
GscCoverageSummaryDto: gscCoverageSummaryDtoSchema,
|
|
7993
|
+
GscDeindexedRowDto: gscDeindexedRowSchema,
|
|
7994
|
+
GscPerformanceDailyDto: gscPerformanceDailyDtoSchema,
|
|
7995
|
+
GscSearchDataDto: gscSearchDataDtoSchema,
|
|
7996
|
+
GscSiteListResponseDto: gscSiteListResponseDtoSchema,
|
|
7997
|
+
GscSitemapListResponseDto: gscSitemapListResponseDtoSchema,
|
|
7998
|
+
GscUrlInspectionDto: gscUrlInspectionDtoSchema,
|
|
7999
|
+
IndexingRequestResponseDto: indexingRequestResponseDtoSchema,
|
|
8000
|
+
KeywordDto: keywordDtoSchema,
|
|
8001
|
+
LatestProjectRunDto: latestProjectRunDtoSchema,
|
|
8002
|
+
LocationContext: locationContextSchema,
|
|
8003
|
+
NotificationDto: notificationDtoSchema,
|
|
8004
|
+
ProjectDto: projectDtoSchema,
|
|
8005
|
+
ProjectReportDto: projectReportDtoSchema,
|
|
8006
|
+
QueryDto: queryDtoSchema,
|
|
8007
|
+
RunDetailDto: runDetailDtoSchema,
|
|
8008
|
+
RunDto: runDtoSchema,
|
|
8009
|
+
ScheduleDto: scheduleDtoSchema,
|
|
8010
|
+
SettingsDto: settingsDtoSchema,
|
|
8011
|
+
SnapshotDiffResponse: snapshotDiffResponseSchema,
|
|
8012
|
+
SnapshotListResponse: snapshotListResponseSchema,
|
|
8013
|
+
SnapshotReportDto: snapshotReportSchema,
|
|
8014
|
+
TrafficBackfillResponse: trafficBackfillResponseSchema,
|
|
8015
|
+
TrafficEventsResponse: trafficEventsResponseSchema,
|
|
8016
|
+
TrafficSourceDetailDto: trafficSourceDetailDtoSchema,
|
|
8017
|
+
TrafficSourceDto: trafficSourceDtoSchema,
|
|
8018
|
+
TrafficSourceListResponse: trafficSourceListResponseSchema,
|
|
8019
|
+
TrafficStatusResponse: trafficStatusResponseSchema,
|
|
8020
|
+
TrafficSyncResponse: trafficSyncResponseSchema,
|
|
8021
|
+
WordpressAuditPageDto: wordpressAuditPageDtoSchema,
|
|
8022
|
+
WordpressBulkMetaResultDto: wordpressBulkMetaResultDtoSchema,
|
|
8023
|
+
WordpressDiffDto: wordpressDiffDtoSchema,
|
|
8024
|
+
WordpressManualAssistDto: wordpressManualAssistDtoSchema,
|
|
8025
|
+
WordpressOnboardResultDto: wordpressOnboardResultDtoSchema,
|
|
8026
|
+
WordpressPageDetailDto: wordpressPageDetailDtoSchema,
|
|
8027
|
+
WordpressPageSummaryDto: wordpressPageSummaryDtoSchema,
|
|
8028
|
+
WordpressSchemaBlockDto: wordpressSchemaBlockDtoSchema,
|
|
8029
|
+
WordpressSchemaDeployResultDto: wordpressSchemaDeployResultDtoSchema,
|
|
8030
|
+
WordpressSchemaStatusResultDto: wordpressSchemaStatusResultDtoSchema,
|
|
8031
|
+
WordpressStatusDto: wordpressStatusDtoSchema,
|
|
8032
|
+
// Shared envelope used by every 4xx/5xx response. Defined locally because
|
|
8033
|
+
// the API never returns this from a typed handler — it's emitted by the
|
|
8034
|
+
// global error handler. Codegen consumers reference it through the
|
|
8035
|
+
// ErrorEnvelope ref so error shape is part of the public contract.
|
|
8036
|
+
ErrorEnvelope: z.object({
|
|
8037
|
+
error: z.object({
|
|
8038
|
+
code: z.string(),
|
|
8039
|
+
message: z.string(),
|
|
8040
|
+
details: z.unknown().optional()
|
|
8041
|
+
})
|
|
8042
|
+
})
|
|
8043
|
+
};
|
|
8044
|
+
function buildComponentSchemas() {
|
|
8045
|
+
const out = {};
|
|
8046
|
+
for (const [name, schema] of Object.entries(SCHEMA_TABLE)) {
|
|
8047
|
+
out[name] = z.toJSONSchema(schema, { target: "openapi-3.0" });
|
|
8048
|
+
}
|
|
8049
|
+
return out;
|
|
8050
|
+
}
|
|
8051
|
+
function jsonResponse(description, schemaName) {
|
|
8052
|
+
return {
|
|
8053
|
+
description,
|
|
8054
|
+
content: {
|
|
8055
|
+
"application/json": {
|
|
8056
|
+
schema: { $ref: `#/components/schemas/${schemaName}` }
|
|
8057
|
+
}
|
|
8058
|
+
}
|
|
8059
|
+
};
|
|
8060
|
+
}
|
|
8061
|
+
function jsonArrayResponse(description, schemaName) {
|
|
8062
|
+
return {
|
|
8063
|
+
description,
|
|
8064
|
+
content: {
|
|
8065
|
+
"application/json": {
|
|
8066
|
+
schema: {
|
|
8067
|
+
type: "array",
|
|
8068
|
+
items: { $ref: `#/components/schemas/${schemaName}` }
|
|
8069
|
+
}
|
|
8070
|
+
}
|
|
8071
|
+
}
|
|
8072
|
+
};
|
|
8073
|
+
}
|
|
8074
|
+
function rawJsonResponse(description, schema) {
|
|
8075
|
+
return {
|
|
8076
|
+
description,
|
|
8077
|
+
content: {
|
|
8078
|
+
"application/json": { schema }
|
|
8079
|
+
}
|
|
8080
|
+
};
|
|
8081
|
+
}
|
|
8082
|
+
var looseObjectSchema = { type: "object", additionalProperties: true };
|
|
8083
|
+
function errorResponse(description) {
|
|
8084
|
+
return jsonResponse(description, "ErrorEnvelope");
|
|
8085
|
+
}
|
|
8086
|
+
|
|
7867
8087
|
// ../api-routes/src/openapi.ts
|
|
7868
8088
|
var stringSchema = { type: "string" };
|
|
7869
8089
|
var booleanSchema = { type: "boolean" };
|
|
@@ -7996,7 +8216,7 @@ var routeCatalog = [
|
|
|
7996
8216
|
tags: ["meta"],
|
|
7997
8217
|
auth: false,
|
|
7998
8218
|
responses: {
|
|
7999
|
-
200:
|
|
8219
|
+
200: rawJsonResponse("OpenAPI document.", looseObjectSchema)
|
|
8000
8220
|
}
|
|
8001
8221
|
},
|
|
8002
8222
|
{
|
|
@@ -8031,8 +8251,8 @@ var routeCatalog = [
|
|
|
8031
8251
|
}
|
|
8032
8252
|
},
|
|
8033
8253
|
responses: {
|
|
8034
|
-
200:
|
|
8035
|
-
201:
|
|
8254
|
+
200: jsonResponse("Project updated.", "ProjectDto"),
|
|
8255
|
+
201: jsonResponse("Project created.", "ProjectDto")
|
|
8036
8256
|
}
|
|
8037
8257
|
},
|
|
8038
8258
|
{
|
|
@@ -8041,7 +8261,7 @@ var routeCatalog = [
|
|
|
8041
8261
|
summary: "List projects",
|
|
8042
8262
|
tags: ["projects"],
|
|
8043
8263
|
responses: {
|
|
8044
|
-
200:
|
|
8264
|
+
200: jsonArrayResponse("Projects returned.", "ProjectDto")
|
|
8045
8265
|
}
|
|
8046
8266
|
},
|
|
8047
8267
|
{
|
|
@@ -8051,8 +8271,8 @@ var routeCatalog = [
|
|
|
8051
8271
|
tags: ["projects"],
|
|
8052
8272
|
parameters: [nameParameter],
|
|
8053
8273
|
responses: {
|
|
8054
|
-
200:
|
|
8055
|
-
404:
|
|
8274
|
+
200: jsonResponse("Project returned.", "ProjectDto"),
|
|
8275
|
+
404: errorResponse("Project not found.")
|
|
8056
8276
|
}
|
|
8057
8277
|
},
|
|
8058
8278
|
{
|
|
@@ -8063,7 +8283,7 @@ var routeCatalog = [
|
|
|
8063
8283
|
parameters: [nameParameter],
|
|
8064
8284
|
responses: {
|
|
8065
8285
|
204: { description: "Project deleted." },
|
|
8066
|
-
404:
|
|
8286
|
+
404: errorResponse("Project not found.")
|
|
8067
8287
|
}
|
|
8068
8288
|
},
|
|
8069
8289
|
{
|
|
@@ -8074,8 +8294,9 @@ var routeCatalog = [
|
|
|
8074
8294
|
tags: ["projects"],
|
|
8075
8295
|
parameters: [nameParameter],
|
|
8076
8296
|
responses: {
|
|
8077
|
-
|
|
8078
|
-
|
|
8297
|
+
// TODO: Define `ProjectDeletePreviewDto` Zod schema in contracts and reference here.
|
|
8298
|
+
200: rawJsonResponse("Preview of cascade impact.", looseObjectSchema),
|
|
8299
|
+
404: errorResponse("Project not found.")
|
|
8079
8300
|
}
|
|
8080
8301
|
},
|
|
8081
8302
|
{
|
|
@@ -8093,9 +8314,9 @@ var routeCatalog = [
|
|
|
8093
8314
|
}
|
|
8094
8315
|
},
|
|
8095
8316
|
responses: {
|
|
8096
|
-
201:
|
|
8097
|
-
400:
|
|
8098
|
-
404:
|
|
8317
|
+
201: jsonResponse("Location created.", "LocationContext"),
|
|
8318
|
+
400: errorResponse("Invalid location."),
|
|
8319
|
+
404: errorResponse("Project not found.")
|
|
8099
8320
|
}
|
|
8100
8321
|
},
|
|
8101
8322
|
{
|
|
@@ -8105,8 +8326,9 @@ var routeCatalog = [
|
|
|
8105
8326
|
tags: ["projects"],
|
|
8106
8327
|
parameters: [nameParameter],
|
|
8107
8328
|
responses: {
|
|
8108
|
-
|
|
8109
|
-
|
|
8329
|
+
// TODO: Define `ProjectLocationsResponse` Zod schema (`{ locations: LocationContext[]; defaultLocation: string | null }`) in contracts.
|
|
8330
|
+
200: rawJsonResponse("Locations returned.", looseObjectSchema),
|
|
8331
|
+
404: errorResponse("Project not found.")
|
|
8110
8332
|
}
|
|
8111
8333
|
},
|
|
8112
8334
|
{
|
|
@@ -8117,8 +8339,8 @@ var routeCatalog = [
|
|
|
8117
8339
|
parameters: [nameParameter, locationLabelParameter],
|
|
8118
8340
|
responses: {
|
|
8119
8341
|
204: { description: "Location removed." },
|
|
8120
|
-
400:
|
|
8121
|
-
404:
|
|
8342
|
+
400: errorResponse("Invalid location."),
|
|
8343
|
+
404: errorResponse("Project or location not found.")
|
|
8122
8344
|
}
|
|
8123
8345
|
},
|
|
8124
8346
|
{
|
|
@@ -8142,9 +8364,9 @@ var routeCatalog = [
|
|
|
8142
8364
|
}
|
|
8143
8365
|
},
|
|
8144
8366
|
responses: {
|
|
8145
|
-
200:
|
|
8146
|
-
400:
|
|
8147
|
-
404:
|
|
8367
|
+
200: jsonResponse("Default location updated.", "ProjectDto"),
|
|
8368
|
+
400: errorResponse("Invalid location."),
|
|
8369
|
+
404: errorResponse("Project not found.")
|
|
8148
8370
|
}
|
|
8149
8371
|
},
|
|
8150
8372
|
{
|
|
@@ -8154,8 +8376,9 @@ var routeCatalog = [
|
|
|
8154
8376
|
tags: ["projects"],
|
|
8155
8377
|
parameters: [nameParameter],
|
|
8156
8378
|
responses: {
|
|
8157
|
-
|
|
8158
|
-
|
|
8379
|
+
// TODO: Define an `ExportedProjectConfig` Zod schema in contracts (mirrors canonry.yaml shape).
|
|
8380
|
+
200: rawJsonResponse("Project configuration returned.", looseObjectSchema),
|
|
8381
|
+
404: errorResponse("Project not found.")
|
|
8159
8382
|
}
|
|
8160
8383
|
},
|
|
8161
8384
|
{
|
|
@@ -8165,7 +8388,7 @@ var routeCatalog = [
|
|
|
8165
8388
|
tags: ["queries"],
|
|
8166
8389
|
parameters: [nameParameter],
|
|
8167
8390
|
responses: {
|
|
8168
|
-
200:
|
|
8391
|
+
200: jsonArrayResponse("Queries returned.", "QueryDto")
|
|
8169
8392
|
}
|
|
8170
8393
|
},
|
|
8171
8394
|
{
|
|
@@ -8189,7 +8412,7 @@ var routeCatalog = [
|
|
|
8189
8412
|
}
|
|
8190
8413
|
},
|
|
8191
8414
|
responses: {
|
|
8192
|
-
200:
|
|
8415
|
+
200: jsonArrayResponse("Queries replaced.", "QueryDto")
|
|
8193
8416
|
}
|
|
8194
8417
|
},
|
|
8195
8418
|
{
|
|
@@ -8213,8 +8436,8 @@ var routeCatalog = [
|
|
|
8213
8436
|
}
|
|
8214
8437
|
},
|
|
8215
8438
|
responses: {
|
|
8216
|
-
200:
|
|
8217
|
-
400:
|
|
8439
|
+
200: jsonArrayResponse("Remaining queries returned.", "QueryDto"),
|
|
8440
|
+
400: errorResponse("Invalid query delete request.")
|
|
8218
8441
|
}
|
|
8219
8442
|
},
|
|
8220
8443
|
{
|
|
@@ -8238,7 +8461,7 @@ var routeCatalog = [
|
|
|
8238
8461
|
}
|
|
8239
8462
|
},
|
|
8240
8463
|
responses: {
|
|
8241
|
-
200:
|
|
8464
|
+
200: jsonArrayResponse("Queries appended.", "QueryDto")
|
|
8242
8465
|
}
|
|
8243
8466
|
},
|
|
8244
8467
|
{
|
|
@@ -8263,8 +8486,9 @@ var routeCatalog = [
|
|
|
8263
8486
|
}
|
|
8264
8487
|
},
|
|
8265
8488
|
responses: {
|
|
8266
|
-
|
|
8267
|
-
|
|
8489
|
+
// TODO: Add `QueriesReplacePreviewDto` Zod schema in contracts.
|
|
8490
|
+
200: rawJsonResponse("Replace preview returned.", looseObjectSchema),
|
|
8491
|
+
404: errorResponse("Project not found.")
|
|
8268
8492
|
}
|
|
8269
8493
|
},
|
|
8270
8494
|
{
|
|
@@ -8289,8 +8513,8 @@ var routeCatalog = [
|
|
|
8289
8513
|
}
|
|
8290
8514
|
},
|
|
8291
8515
|
responses: {
|
|
8292
|
-
200: {
|
|
8293
|
-
501:
|
|
8516
|
+
200: rawJsonResponse("Query suggestions returned.", { type: "object", properties: { suggestions: { type: "array", items: { type: "string" } } } }),
|
|
8517
|
+
501: errorResponse("Query generation is not available.")
|
|
8294
8518
|
}
|
|
8295
8519
|
},
|
|
8296
8520
|
{
|
|
@@ -8300,7 +8524,7 @@ var routeCatalog = [
|
|
|
8300
8524
|
tags: ["queries"],
|
|
8301
8525
|
parameters: [nameParameter],
|
|
8302
8526
|
responses: {
|
|
8303
|
-
200:
|
|
8527
|
+
200: jsonArrayResponse("Legacy keyword-shaped queries returned.", "KeywordDto")
|
|
8304
8528
|
}
|
|
8305
8529
|
},
|
|
8306
8530
|
{
|
|
@@ -8324,7 +8548,7 @@ var routeCatalog = [
|
|
|
8324
8548
|
}
|
|
8325
8549
|
},
|
|
8326
8550
|
responses: {
|
|
8327
|
-
200:
|
|
8551
|
+
200: jsonArrayResponse("Legacy keyword-shaped queries replaced.", "KeywordDto")
|
|
8328
8552
|
}
|
|
8329
8553
|
},
|
|
8330
8554
|
{
|
|
@@ -8348,8 +8572,8 @@ var routeCatalog = [
|
|
|
8348
8572
|
}
|
|
8349
8573
|
},
|
|
8350
8574
|
responses: {
|
|
8351
|
-
200:
|
|
8352
|
-
400:
|
|
8575
|
+
200: jsonArrayResponse("Remaining legacy keyword-shaped queries returned.", "KeywordDto"),
|
|
8576
|
+
400: errorResponse("Invalid legacy keyword delete request.")
|
|
8353
8577
|
}
|
|
8354
8578
|
},
|
|
8355
8579
|
{
|
|
@@ -8373,7 +8597,7 @@ var routeCatalog = [
|
|
|
8373
8597
|
}
|
|
8374
8598
|
},
|
|
8375
8599
|
responses: {
|
|
8376
|
-
200:
|
|
8600
|
+
200: jsonArrayResponse("Legacy keyword-shaped queries appended.", "KeywordDto")
|
|
8377
8601
|
}
|
|
8378
8602
|
},
|
|
8379
8603
|
{
|
|
@@ -8398,8 +8622,9 @@ var routeCatalog = [
|
|
|
8398
8622
|
}
|
|
8399
8623
|
},
|
|
8400
8624
|
responses: {
|
|
8401
|
-
|
|
8402
|
-
|
|
8625
|
+
// TODO: Add `KeywordGenerateResponse` Zod schema (`{ suggestions: string[] }`) in contracts.
|
|
8626
|
+
200: rawJsonResponse("Legacy keyword suggestions returned.", looseObjectSchema),
|
|
8627
|
+
501: errorResponse("Legacy keyword generation is not available.")
|
|
8403
8628
|
}
|
|
8404
8629
|
},
|
|
8405
8630
|
{
|
|
@@ -8409,7 +8634,7 @@ var routeCatalog = [
|
|
|
8409
8634
|
tags: ["competitors"],
|
|
8410
8635
|
parameters: [nameParameter],
|
|
8411
8636
|
responses: {
|
|
8412
|
-
200:
|
|
8637
|
+
200: jsonArrayResponse("Competitors returned.", "CompetitorDto")
|
|
8413
8638
|
}
|
|
8414
8639
|
},
|
|
8415
8640
|
{
|
|
@@ -8433,7 +8658,7 @@ var routeCatalog = [
|
|
|
8433
8658
|
}
|
|
8434
8659
|
},
|
|
8435
8660
|
responses: {
|
|
8436
|
-
200:
|
|
8661
|
+
200: jsonArrayResponse("Competitors replaced.", "CompetitorDto")
|
|
8437
8662
|
}
|
|
8438
8663
|
},
|
|
8439
8664
|
{
|
|
@@ -8457,8 +8682,8 @@ var routeCatalog = [
|
|
|
8457
8682
|
}
|
|
8458
8683
|
},
|
|
8459
8684
|
responses: {
|
|
8460
|
-
200:
|
|
8461
|
-
400:
|
|
8685
|
+
200: jsonArrayResponse("Competitors appended.", "CompetitorDto"),
|
|
8686
|
+
400: errorResponse("Invalid competitor append request.")
|
|
8462
8687
|
}
|
|
8463
8688
|
},
|
|
8464
8689
|
{
|
|
@@ -8482,8 +8707,8 @@ var routeCatalog = [
|
|
|
8482
8707
|
}
|
|
8483
8708
|
},
|
|
8484
8709
|
responses: {
|
|
8485
|
-
200:
|
|
8486
|
-
400:
|
|
8710
|
+
200: jsonArrayResponse("Remaining competitors returned.", "CompetitorDto"),
|
|
8711
|
+
400: errorResponse("Invalid competitor delete request.")
|
|
8487
8712
|
}
|
|
8488
8713
|
},
|
|
8489
8714
|
{
|
|
@@ -8511,8 +8736,8 @@ var routeCatalog = [
|
|
|
8511
8736
|
}
|
|
8512
8737
|
},
|
|
8513
8738
|
responses: {
|
|
8514
|
-
201:
|
|
8515
|
-
409:
|
|
8739
|
+
201: jsonResponse("Run queued.", "RunDto"),
|
|
8740
|
+
409: errorResponse("Run already in progress.")
|
|
8516
8741
|
}
|
|
8517
8742
|
},
|
|
8518
8743
|
{
|
|
@@ -8522,7 +8747,7 @@ var routeCatalog = [
|
|
|
8522
8747
|
tags: ["runs"],
|
|
8523
8748
|
parameters: [nameParameter, limitQueryParameter],
|
|
8524
8749
|
responses: {
|
|
8525
|
-
200:
|
|
8750
|
+
200: jsonArrayResponse("Runs returned.", "RunDto")
|
|
8526
8751
|
}
|
|
8527
8752
|
},
|
|
8528
8753
|
{
|
|
@@ -8532,7 +8757,7 @@ var routeCatalog = [
|
|
|
8532
8757
|
tags: ["runs"],
|
|
8533
8758
|
parameters: [nameParameter],
|
|
8534
8759
|
responses: {
|
|
8535
|
-
200:
|
|
8760
|
+
200: jsonResponse("Latest run returned.", "LatestProjectRunDto")
|
|
8536
8761
|
}
|
|
8537
8762
|
},
|
|
8538
8763
|
{
|
|
@@ -8541,7 +8766,7 @@ var routeCatalog = [
|
|
|
8541
8766
|
summary: "List all runs",
|
|
8542
8767
|
tags: ["runs"],
|
|
8543
8768
|
responses: {
|
|
8544
|
-
200:
|
|
8769
|
+
200: jsonArrayResponse("Runs returned.", "RunDto")
|
|
8545
8770
|
}
|
|
8546
8771
|
},
|
|
8547
8772
|
{
|
|
@@ -8563,7 +8788,8 @@ var routeCatalog = [
|
|
|
8563
8788
|
}
|
|
8564
8789
|
},
|
|
8565
8790
|
responses: {
|
|
8566
|
-
|
|
8791
|
+
// TODO: Add `TriggerAllRunsResponse` Zod schema in contracts.
|
|
8792
|
+
207: rawJsonResponse("Run results returned.", looseObjectSchema)
|
|
8567
8793
|
}
|
|
8568
8794
|
},
|
|
8569
8795
|
{
|
|
@@ -8573,8 +8799,8 @@ var routeCatalog = [
|
|
|
8573
8799
|
tags: ["runs"],
|
|
8574
8800
|
parameters: [runIdParameter],
|
|
8575
8801
|
responses: {
|
|
8576
|
-
200:
|
|
8577
|
-
404:
|
|
8802
|
+
200: jsonResponse("Run returned.", "RunDetailDto"),
|
|
8803
|
+
404: errorResponse("Run not found.")
|
|
8578
8804
|
}
|
|
8579
8805
|
},
|
|
8580
8806
|
{
|
|
@@ -8584,9 +8810,9 @@ var routeCatalog = [
|
|
|
8584
8810
|
tags: ["runs"],
|
|
8585
8811
|
parameters: [runIdParameter],
|
|
8586
8812
|
responses: {
|
|
8587
|
-
200:
|
|
8588
|
-
404:
|
|
8589
|
-
409:
|
|
8813
|
+
200: jsonResponse("Run cancelled.", "RunDto"),
|
|
8814
|
+
404: errorResponse("Run not found."),
|
|
8815
|
+
409: errorResponse("Run is not cancellable.")
|
|
8590
8816
|
}
|
|
8591
8817
|
},
|
|
8592
8818
|
{
|
|
@@ -8604,8 +8830,9 @@ var routeCatalog = [
|
|
|
8604
8830
|
}
|
|
8605
8831
|
},
|
|
8606
8832
|
responses: {
|
|
8607
|
-
|
|
8608
|
-
|
|
8833
|
+
// TODO: Add `ApplyResultDto` Zod schema in contracts (single-doc apply result).
|
|
8834
|
+
200: jsonResponse("Config applied.", "ProjectDto"),
|
|
8835
|
+
400: errorResponse("Invalid config.")
|
|
8609
8836
|
}
|
|
8610
8837
|
},
|
|
8611
8838
|
{
|
|
@@ -8615,7 +8842,7 @@ var routeCatalog = [
|
|
|
8615
8842
|
tags: ["history"],
|
|
8616
8843
|
parameters: [nameParameter],
|
|
8617
8844
|
responses: {
|
|
8618
|
-
200:
|
|
8845
|
+
200: jsonArrayResponse("Audit history returned.", "AuditLogEntry")
|
|
8619
8846
|
}
|
|
8620
8847
|
},
|
|
8621
8848
|
{
|
|
@@ -8624,7 +8851,7 @@ var routeCatalog = [
|
|
|
8624
8851
|
summary: "Get global audit history",
|
|
8625
8852
|
tags: ["history"],
|
|
8626
8853
|
responses: {
|
|
8627
|
-
200:
|
|
8854
|
+
200: jsonArrayResponse("Audit history returned.", "AuditLogEntry")
|
|
8628
8855
|
}
|
|
8629
8856
|
},
|
|
8630
8857
|
{
|
|
@@ -8639,7 +8866,7 @@ var routeCatalog = [
|
|
|
8639
8866
|
locationQueryParameter
|
|
8640
8867
|
],
|
|
8641
8868
|
responses: {
|
|
8642
|
-
200:
|
|
8869
|
+
200: jsonResponse("Snapshots returned.", "SnapshotListResponse")
|
|
8643
8870
|
}
|
|
8644
8871
|
},
|
|
8645
8872
|
{
|
|
@@ -8649,7 +8876,8 @@ var routeCatalog = [
|
|
|
8649
8876
|
tags: ["history"],
|
|
8650
8877
|
parameters: [nameParameter, locationQueryParameter],
|
|
8651
8878
|
responses: {
|
|
8652
|
-
|
|
8879
|
+
// TODO: Add `ProjectTimelineDto` Zod schema in contracts.
|
|
8880
|
+
200: rawJsonResponse("Timeline returned.", looseObjectSchema)
|
|
8653
8881
|
}
|
|
8654
8882
|
},
|
|
8655
8883
|
{
|
|
@@ -8659,8 +8887,9 @@ var routeCatalog = [
|
|
|
8659
8887
|
tags: ["analytics"],
|
|
8660
8888
|
parameters: [nameParameter, analyticsWindowParameter],
|
|
8661
8889
|
responses: {
|
|
8662
|
-
|
|
8663
|
-
|
|
8890
|
+
// TODO: Add `BrandMetricsDto` Zod schema in contracts.
|
|
8891
|
+
200: rawJsonResponse("Citation metrics returned.", looseObjectSchema),
|
|
8892
|
+
404: errorResponse("Project not found.")
|
|
8664
8893
|
}
|
|
8665
8894
|
},
|
|
8666
8895
|
{
|
|
@@ -8670,8 +8899,9 @@ var routeCatalog = [
|
|
|
8670
8899
|
tags: ["analytics"],
|
|
8671
8900
|
parameters: [nameParameter, analyticsWindowParameter],
|
|
8672
8901
|
responses: {
|
|
8673
|
-
|
|
8674
|
-
|
|
8902
|
+
// TODO: Add `GapAnalysisDto` Zod schema in contracts.
|
|
8903
|
+
200: rawJsonResponse("Gap analysis returned.", looseObjectSchema),
|
|
8904
|
+
404: errorResponse("Project not found.")
|
|
8675
8905
|
}
|
|
8676
8906
|
},
|
|
8677
8907
|
{
|
|
@@ -8681,8 +8911,9 @@ var routeCatalog = [
|
|
|
8681
8911
|
tags: ["analytics"],
|
|
8682
8912
|
parameters: [nameParameter, analyticsWindowParameter],
|
|
8683
8913
|
responses: {
|
|
8684
|
-
|
|
8685
|
-
|
|
8914
|
+
// TODO: Add `SourceBreakdownDto` Zod schema in contracts.
|
|
8915
|
+
200: rawJsonResponse("Source breakdown returned.", looseObjectSchema),
|
|
8916
|
+
404: errorResponse("Project not found.")
|
|
8686
8917
|
}
|
|
8687
8918
|
},
|
|
8688
8919
|
{
|
|
@@ -8708,8 +8939,8 @@ var routeCatalog = [
|
|
|
8708
8939
|
}
|
|
8709
8940
|
],
|
|
8710
8941
|
responses: {
|
|
8711
|
-
200:
|
|
8712
|
-
400:
|
|
8942
|
+
200: jsonResponse("Diff returned.", "SnapshotDiffResponse"),
|
|
8943
|
+
400: errorResponse("Missing run IDs.")
|
|
8713
8944
|
}
|
|
8714
8945
|
},
|
|
8715
8946
|
{
|
|
@@ -8718,7 +8949,7 @@ var routeCatalog = [
|
|
|
8718
8949
|
summary: "Get provider settings summary",
|
|
8719
8950
|
tags: ["settings"],
|
|
8720
8951
|
responses: {
|
|
8721
|
-
200:
|
|
8952
|
+
200: jsonResponse("Settings returned.", "SettingsDto")
|
|
8722
8953
|
}
|
|
8723
8954
|
},
|
|
8724
8955
|
{
|
|
@@ -8744,9 +8975,10 @@ var routeCatalog = [
|
|
|
8744
8975
|
}
|
|
8745
8976
|
},
|
|
8746
8977
|
responses: {
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8978
|
+
// TODO: Add `ProviderSettingsDto` Zod schema in contracts.
|
|
8979
|
+
200: rawJsonResponse("Provider updated.", looseObjectSchema),
|
|
8980
|
+
400: errorResponse("Invalid provider settings."),
|
|
8981
|
+
501: errorResponse("Provider updates are not supported.")
|
|
8750
8982
|
}
|
|
8751
8983
|
},
|
|
8752
8984
|
{
|
|
@@ -8770,9 +9002,10 @@ var routeCatalog = [
|
|
|
8770
9002
|
}
|
|
8771
9003
|
},
|
|
8772
9004
|
responses: {
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
9005
|
+
// TODO: Add `GoogleSettingsDto` Zod schema in contracts.
|
|
9006
|
+
200: rawJsonResponse("Google settings updated.", looseObjectSchema),
|
|
9007
|
+
400: errorResponse("Invalid Google settings."),
|
|
9008
|
+
501: errorResponse("Google settings updates are not supported.")
|
|
8776
9009
|
}
|
|
8777
9010
|
},
|
|
8778
9011
|
{
|
|
@@ -8798,9 +9031,9 @@ var routeCatalog = [
|
|
|
8798
9031
|
}
|
|
8799
9032
|
},
|
|
8800
9033
|
responses: {
|
|
8801
|
-
200:
|
|
8802
|
-
400:
|
|
8803
|
-
501:
|
|
9034
|
+
200: jsonResponse("Snapshot report returned.", "SnapshotReportDto"),
|
|
9035
|
+
400: errorResponse("Invalid snapshot input."),
|
|
9036
|
+
501: errorResponse("Snapshot reporting is not supported.")
|
|
8804
9037
|
}
|
|
8805
9038
|
},
|
|
8806
9039
|
{
|
|
@@ -8823,9 +9056,10 @@ var routeCatalog = [
|
|
|
8823
9056
|
}
|
|
8824
9057
|
},
|
|
8825
9058
|
responses: {
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
9059
|
+
// TODO: Add `BingSettingsDto` Zod schema in contracts.
|
|
9060
|
+
200: rawJsonResponse("Bing settings updated.", looseObjectSchema),
|
|
9061
|
+
400: errorResponse("Invalid Bing settings."),
|
|
9062
|
+
501: errorResponse("Bing settings updates are not supported.")
|
|
8829
9063
|
}
|
|
8830
9064
|
},
|
|
8831
9065
|
{
|
|
@@ -8849,9 +9083,10 @@ var routeCatalog = [
|
|
|
8849
9083
|
}
|
|
8850
9084
|
},
|
|
8851
9085
|
responses: {
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
9086
|
+
// TODO: Add `CdpEndpointConfigDto` Zod schema in contracts.
|
|
9087
|
+
200: rawJsonResponse("CDP endpoint updated.", looseObjectSchema),
|
|
9088
|
+
400: errorResponse("Invalid CDP settings."),
|
|
9089
|
+
501: errorResponse("CDP updates are not supported.")
|
|
8855
9090
|
}
|
|
8856
9091
|
},
|
|
8857
9092
|
{
|
|
@@ -8880,9 +9115,9 @@ var routeCatalog = [
|
|
|
8880
9115
|
}
|
|
8881
9116
|
},
|
|
8882
9117
|
responses: {
|
|
8883
|
-
200:
|
|
8884
|
-
201:
|
|
8885
|
-
400:
|
|
9118
|
+
200: jsonResponse("Schedule updated.", "ScheduleDto"),
|
|
9119
|
+
201: jsonResponse("Schedule created.", "ScheduleDto"),
|
|
9120
|
+
400: errorResponse("Invalid payload (e.g. sourceId missing for kind=traffic-sync, or providers set for kind=traffic-sync).")
|
|
8886
9121
|
}
|
|
8887
9122
|
},
|
|
8888
9123
|
{
|
|
@@ -8892,8 +9127,8 @@ var routeCatalog = [
|
|
|
8892
9127
|
tags: ["schedules"],
|
|
8893
9128
|
parameters: [nameParameter, scheduleKindQueryParameter],
|
|
8894
9129
|
responses: {
|
|
8895
|
-
200:
|
|
8896
|
-
404:
|
|
9130
|
+
200: jsonResponse("Schedule returned.", "ScheduleDto"),
|
|
9131
|
+
404: errorResponse("Schedule not found.")
|
|
8897
9132
|
}
|
|
8898
9133
|
},
|
|
8899
9134
|
{
|
|
@@ -8904,7 +9139,7 @@ var routeCatalog = [
|
|
|
8904
9139
|
parameters: [nameParameter, scheduleKindQueryParameter],
|
|
8905
9140
|
responses: {
|
|
8906
9141
|
204: { description: "Schedule deleted." },
|
|
8907
|
-
404:
|
|
9142
|
+
404: errorResponse("Schedule not found.")
|
|
8908
9143
|
}
|
|
8909
9144
|
},
|
|
8910
9145
|
{
|
|
@@ -8913,7 +9148,7 @@ var routeCatalog = [
|
|
|
8913
9148
|
summary: "List notification event types",
|
|
8914
9149
|
tags: ["notifications"],
|
|
8915
9150
|
responses: {
|
|
8916
|
-
200:
|
|
9151
|
+
200: rawJsonResponse("Events returned.", { type: "array", items: stringSchema })
|
|
8917
9152
|
}
|
|
8918
9153
|
},
|
|
8919
9154
|
{
|
|
@@ -8939,7 +9174,7 @@ var routeCatalog = [
|
|
|
8939
9174
|
}
|
|
8940
9175
|
},
|
|
8941
9176
|
responses: {
|
|
8942
|
-
201:
|
|
9177
|
+
201: jsonResponse("Notification created.", "NotificationDto")
|
|
8943
9178
|
}
|
|
8944
9179
|
},
|
|
8945
9180
|
{
|
|
@@ -8949,7 +9184,7 @@ var routeCatalog = [
|
|
|
8949
9184
|
tags: ["notifications"],
|
|
8950
9185
|
parameters: [nameParameter],
|
|
8951
9186
|
responses: {
|
|
8952
|
-
200:
|
|
9187
|
+
200: jsonArrayResponse("Notifications returned.", "NotificationDto")
|
|
8953
9188
|
}
|
|
8954
9189
|
},
|
|
8955
9190
|
{
|
|
@@ -8960,7 +9195,7 @@ var routeCatalog = [
|
|
|
8960
9195
|
parameters: [nameParameter, notificationIdParameter],
|
|
8961
9196
|
responses: {
|
|
8962
9197
|
204: { description: "Notification deleted." },
|
|
8963
|
-
404:
|
|
9198
|
+
404: errorResponse("Notification not found.")
|
|
8964
9199
|
}
|
|
8965
9200
|
},
|
|
8966
9201
|
{
|
|
@@ -8970,10 +9205,11 @@ var routeCatalog = [
|
|
|
8970
9205
|
tags: ["notifications"],
|
|
8971
9206
|
parameters: [nameParameter, notificationIdParameter],
|
|
8972
9207
|
responses: {
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
9208
|
+
// TODO: Add `NotificationTestResult` Zod schema in contracts.
|
|
9209
|
+
200: rawJsonResponse("Test notification sent.", looseObjectSchema),
|
|
9210
|
+
400: errorResponse("Stored notification config is invalid."),
|
|
9211
|
+
404: errorResponse("Notification not found."),
|
|
9212
|
+
502: errorResponse("Notification delivery failed.")
|
|
8977
9213
|
}
|
|
8978
9214
|
},
|
|
8979
9215
|
{
|
|
@@ -8982,8 +9218,9 @@ var routeCatalog = [
|
|
|
8982
9218
|
summary: "Get telemetry status",
|
|
8983
9219
|
tags: ["telemetry"],
|
|
8984
9220
|
responses: {
|
|
8985
|
-
|
|
8986
|
-
|
|
9221
|
+
// TODO: Add `TelemetryStatusDto` Zod schema in contracts.
|
|
9222
|
+
200: rawJsonResponse("Telemetry status returned.", looseObjectSchema),
|
|
9223
|
+
501: errorResponse("Telemetry status is not available.")
|
|
8987
9224
|
}
|
|
8988
9225
|
},
|
|
8989
9226
|
{
|
|
@@ -9006,9 +9243,10 @@ var routeCatalog = [
|
|
|
9006
9243
|
}
|
|
9007
9244
|
},
|
|
9008
9245
|
responses: {
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9246
|
+
// TODO: Add `TelemetryStatusDto` Zod schema in contracts.
|
|
9247
|
+
200: rawJsonResponse("Telemetry updated.", looseObjectSchema),
|
|
9248
|
+
400: errorResponse("Invalid telemetry request."),
|
|
9249
|
+
501: errorResponse("Telemetry configuration is not available.")
|
|
9012
9250
|
}
|
|
9013
9251
|
},
|
|
9014
9252
|
{
|
|
@@ -9018,8 +9256,9 @@ var routeCatalog = [
|
|
|
9018
9256
|
tags: ["cdp"],
|
|
9019
9257
|
parameters: [snapshotIdParameter],
|
|
9020
9258
|
responses: {
|
|
9021
|
-
|
|
9022
|
-
|
|
9259
|
+
// Returns image bytes, not JSON. Codegen consumers should treat this as a binary stream.
|
|
9260
|
+
200: { description: "Screenshot returned.", content: { "image/png": { schema: { type: "string", format: "binary" } } } },
|
|
9261
|
+
404: errorResponse("Screenshot not found.")
|
|
9023
9262
|
}
|
|
9024
9263
|
},
|
|
9025
9264
|
{
|
|
@@ -9028,8 +9267,8 @@ var routeCatalog = [
|
|
|
9028
9267
|
summary: "Get CDP connection status",
|
|
9029
9268
|
tags: ["cdp"],
|
|
9030
9269
|
responses: {
|
|
9031
|
-
200:
|
|
9032
|
-
501:
|
|
9270
|
+
200: jsonResponse("CDP status returned.", "CdpStatusDto"),
|
|
9271
|
+
501: errorResponse("CDP is not configured.")
|
|
9033
9272
|
}
|
|
9034
9273
|
},
|
|
9035
9274
|
{
|
|
@@ -9053,9 +9292,10 @@ var routeCatalog = [
|
|
|
9053
9292
|
}
|
|
9054
9293
|
},
|
|
9055
9294
|
responses: {
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9295
|
+
// TODO: Add `CdpScreenshotResultDto` Zod schema in contracts.
|
|
9296
|
+
200: rawJsonResponse("CDP screenshot results returned.", looseObjectSchema),
|
|
9297
|
+
400: errorResponse("Invalid CDP screenshot request."),
|
|
9298
|
+
501: errorResponse("CDP screenshot support is not available.")
|
|
9059
9299
|
}
|
|
9060
9300
|
},
|
|
9061
9301
|
{
|
|
@@ -9065,8 +9305,9 @@ var routeCatalog = [
|
|
|
9065
9305
|
tags: ["cdp", "runs"],
|
|
9066
9306
|
parameters: [nameParameter, projectRunIdParameter],
|
|
9067
9307
|
responses: {
|
|
9068
|
-
|
|
9069
|
-
|
|
9308
|
+
// TODO: Add `BrowserDiffDto` Zod schema in contracts.
|
|
9309
|
+
200: rawJsonResponse("Browser diff returned.", looseObjectSchema),
|
|
9310
|
+
404: errorResponse("Project or run not found.")
|
|
9070
9311
|
}
|
|
9071
9312
|
},
|
|
9072
9313
|
{
|
|
@@ -9081,9 +9322,9 @@ var routeCatalog = [
|
|
|
9081
9322
|
{ name: "error", in: "query", description: "OAuth error code.", schema: stringSchema }
|
|
9082
9323
|
],
|
|
9083
9324
|
responses: {
|
|
9084
|
-
200:
|
|
9085
|
-
400:
|
|
9086
|
-
500:
|
|
9325
|
+
200: rawJsonResponse("OAuth callback handled.", { type: "object", properties: { status: { type: "string" } } }),
|
|
9326
|
+
400: errorResponse("Invalid callback request."),
|
|
9327
|
+
500: errorResponse("OAuth configuration is incomplete.")
|
|
9087
9328
|
}
|
|
9088
9329
|
},
|
|
9089
9330
|
{
|
|
@@ -9099,9 +9340,9 @@ var routeCatalog = [
|
|
|
9099
9340
|
{ name: "error", in: "query", description: "OAuth error code.", schema: stringSchema }
|
|
9100
9341
|
],
|
|
9101
9342
|
responses: {
|
|
9102
|
-
200:
|
|
9103
|
-
400:
|
|
9104
|
-
500:
|
|
9343
|
+
200: rawJsonResponse("OAuth callback handled.", { type: "object", properties: { status: { type: "string" } } }),
|
|
9344
|
+
400: errorResponse("Invalid callback request."),
|
|
9345
|
+
500: errorResponse("OAuth configuration is incomplete.")
|
|
9105
9346
|
}
|
|
9106
9347
|
},
|
|
9107
9348
|
{
|
|
@@ -9111,8 +9352,8 @@ var routeCatalog = [
|
|
|
9111
9352
|
tags: ["google"],
|
|
9112
9353
|
parameters: [nameParameter],
|
|
9113
9354
|
responses: {
|
|
9114
|
-
200:
|
|
9115
|
-
404:
|
|
9355
|
+
200: jsonArrayResponse("Google connections returned.", "GoogleConnectionDto"),
|
|
9356
|
+
404: errorResponse("Project not found.")
|
|
9116
9357
|
}
|
|
9117
9358
|
},
|
|
9118
9359
|
{
|
|
@@ -9138,8 +9379,8 @@ var routeCatalog = [
|
|
|
9138
9379
|
}
|
|
9139
9380
|
},
|
|
9140
9381
|
responses: {
|
|
9141
|
-
200:
|
|
9142
|
-
400:
|
|
9382
|
+
200: rawJsonResponse("Google auth URL returned.", { type: "object", properties: { url: { type: "string" } } }),
|
|
9383
|
+
400: errorResponse("Invalid Google connection request.")
|
|
9143
9384
|
}
|
|
9144
9385
|
},
|
|
9145
9386
|
{
|
|
@@ -9150,7 +9391,7 @@ var routeCatalog = [
|
|
|
9150
9391
|
parameters: [nameParameter, googleTypeParameter],
|
|
9151
9392
|
responses: {
|
|
9152
9393
|
204: { description: "Google connection deleted." },
|
|
9153
|
-
404:
|
|
9394
|
+
404: errorResponse("Project or connection not found.")
|
|
9154
9395
|
}
|
|
9155
9396
|
},
|
|
9156
9397
|
{
|
|
@@ -9160,9 +9401,9 @@ var routeCatalog = [
|
|
|
9160
9401
|
tags: ["google"],
|
|
9161
9402
|
parameters: [nameParameter],
|
|
9162
9403
|
responses: {
|
|
9163
|
-
200:
|
|
9164
|
-
400:
|
|
9165
|
-
404:
|
|
9404
|
+
200: jsonResponse("Google properties returned.", "GscSiteListResponseDto"),
|
|
9405
|
+
400: errorResponse("Google OAuth is not configured."),
|
|
9406
|
+
404: errorResponse("Project not found.")
|
|
9166
9407
|
}
|
|
9167
9408
|
},
|
|
9168
9409
|
{
|
|
@@ -9186,9 +9427,9 @@ var routeCatalog = [
|
|
|
9186
9427
|
}
|
|
9187
9428
|
},
|
|
9188
9429
|
responses: {
|
|
9189
|
-
200:
|
|
9190
|
-
400:
|
|
9191
|
-
404:
|
|
9430
|
+
200: jsonResponse("Google property updated.", "GoogleConnectionDto"),
|
|
9431
|
+
400: errorResponse("Invalid property request."),
|
|
9432
|
+
404: errorResponse("Project or connection not found.")
|
|
9192
9433
|
}
|
|
9193
9434
|
},
|
|
9194
9435
|
{
|
|
@@ -9212,9 +9453,9 @@ var routeCatalog = [
|
|
|
9212
9453
|
}
|
|
9213
9454
|
},
|
|
9214
9455
|
responses: {
|
|
9215
|
-
200:
|
|
9216
|
-
400:
|
|
9217
|
-
404:
|
|
9456
|
+
200: jsonResponse("Google sitemap updated.", "GoogleConnectionDto"),
|
|
9457
|
+
400: errorResponse("Invalid sitemap request."),
|
|
9458
|
+
404: errorResponse("Project or connection not found.")
|
|
9218
9459
|
}
|
|
9219
9460
|
},
|
|
9220
9461
|
{
|
|
@@ -9237,9 +9478,9 @@ var routeCatalog = [
|
|
|
9237
9478
|
}
|
|
9238
9479
|
},
|
|
9239
9480
|
responses: {
|
|
9240
|
-
200:
|
|
9241
|
-
400:
|
|
9242
|
-
404:
|
|
9481
|
+
200: jsonResponse("GSC sync run returned.", "RunDto"),
|
|
9482
|
+
400: errorResponse("Invalid GSC sync request."),
|
|
9483
|
+
404: errorResponse("Project or connection not found.")
|
|
9243
9484
|
}
|
|
9244
9485
|
},
|
|
9245
9486
|
{
|
|
@@ -9258,8 +9499,11 @@ var routeCatalog = [
|
|
|
9258
9499
|
analyticsWindowParameter
|
|
9259
9500
|
],
|
|
9260
9501
|
responses: {
|
|
9261
|
-
|
|
9262
|
-
|
|
9502
|
+
// Handler returns an array of GscSearchDataDto rows (web's
|
|
9503
|
+
// ApiGscPerformanceRow[] confirms). Was incorrectly spec'd as a
|
|
9504
|
+
// single object, which silently truncated client types to one row.
|
|
9505
|
+
200: jsonArrayResponse("GSC performance rows returned.", "GscSearchDataDto"),
|
|
9506
|
+
404: errorResponse("Project not found.")
|
|
9263
9507
|
}
|
|
9264
9508
|
},
|
|
9265
9509
|
{
|
|
@@ -9274,8 +9518,8 @@ var routeCatalog = [
|
|
|
9274
9518
|
analyticsWindowParameter
|
|
9275
9519
|
],
|
|
9276
9520
|
responses: {
|
|
9277
|
-
200:
|
|
9278
|
-
404:
|
|
9521
|
+
200: jsonResponse("Daily aggregate (date \u2192 clicks/impressions/ctr) plus window totals.", "GscPerformanceDailyDto"),
|
|
9522
|
+
404: errorResponse("Project not found.")
|
|
9279
9523
|
}
|
|
9280
9524
|
},
|
|
9281
9525
|
{
|
|
@@ -9299,9 +9543,9 @@ var routeCatalog = [
|
|
|
9299
9543
|
}
|
|
9300
9544
|
},
|
|
9301
9545
|
responses: {
|
|
9302
|
-
200:
|
|
9303
|
-
400:
|
|
9304
|
-
404:
|
|
9546
|
+
200: jsonResponse("GSC inspection result returned.", "GscUrlInspectionDto"),
|
|
9547
|
+
400: errorResponse("Invalid inspection request."),
|
|
9548
|
+
404: errorResponse("Project or connection not found.")
|
|
9305
9549
|
}
|
|
9306
9550
|
},
|
|
9307
9551
|
{
|
|
@@ -9311,8 +9555,8 @@ var routeCatalog = [
|
|
|
9311
9555
|
tags: ["google"],
|
|
9312
9556
|
parameters: [nameParameter, { name: "url", in: "query", description: "Filter by URL.", schema: stringSchema }, limitQueryParameter],
|
|
9313
9557
|
responses: {
|
|
9314
|
-
200:
|
|
9315
|
-
404:
|
|
9558
|
+
200: jsonArrayResponse("GSC inspections returned.", "GscUrlInspectionDto"),
|
|
9559
|
+
404: errorResponse("Project not found.")
|
|
9316
9560
|
}
|
|
9317
9561
|
},
|
|
9318
9562
|
{
|
|
@@ -9322,8 +9566,8 @@ var routeCatalog = [
|
|
|
9322
9566
|
tags: ["google"],
|
|
9323
9567
|
parameters: [nameParameter],
|
|
9324
9568
|
responses: {
|
|
9325
|
-
200:
|
|
9326
|
-
404:
|
|
9569
|
+
200: jsonArrayResponse("Deindexed pages returned.", "GscDeindexedRowDto"),
|
|
9570
|
+
404: errorResponse("Project not found.")
|
|
9327
9571
|
}
|
|
9328
9572
|
},
|
|
9329
9573
|
{
|
|
@@ -9333,8 +9577,8 @@ var routeCatalog = [
|
|
|
9333
9577
|
tags: ["google"],
|
|
9334
9578
|
parameters: [nameParameter],
|
|
9335
9579
|
responses: {
|
|
9336
|
-
200:
|
|
9337
|
-
404:
|
|
9580
|
+
200: jsonResponse("GSC coverage returned.", "GscCoverageSummaryDto"),
|
|
9581
|
+
404: errorResponse("Project not found.")
|
|
9338
9582
|
}
|
|
9339
9583
|
},
|
|
9340
9584
|
{
|
|
@@ -9344,8 +9588,8 @@ var routeCatalog = [
|
|
|
9344
9588
|
tags: ["google"],
|
|
9345
9589
|
parameters: [nameParameter, limitQueryParameter],
|
|
9346
9590
|
responses: {
|
|
9347
|
-
200:
|
|
9348
|
-
404:
|
|
9591
|
+
200: jsonArrayResponse("GSC coverage history returned.", "GscCoverageSnapshotDto"),
|
|
9592
|
+
404: errorResponse("Project not found.")
|
|
9349
9593
|
}
|
|
9350
9594
|
},
|
|
9351
9595
|
{
|
|
@@ -9355,9 +9599,9 @@ var routeCatalog = [
|
|
|
9355
9599
|
tags: ["google"],
|
|
9356
9600
|
parameters: [nameParameter],
|
|
9357
9601
|
responses: {
|
|
9358
|
-
200:
|
|
9359
|
-
400:
|
|
9360
|
-
404:
|
|
9602
|
+
200: jsonResponse("GSC sitemaps returned.", "GscSitemapListResponseDto"),
|
|
9603
|
+
400: errorResponse("Invalid sitemap request."),
|
|
9604
|
+
404: errorResponse("Project or connection not found.")
|
|
9361
9605
|
}
|
|
9362
9606
|
},
|
|
9363
9607
|
{
|
|
@@ -9367,9 +9611,10 @@ var routeCatalog = [
|
|
|
9367
9611
|
tags: ["google"],
|
|
9368
9612
|
parameters: [nameParameter],
|
|
9369
9613
|
responses: {
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9614
|
+
// TODO: Add `DiscoverSitemapsResponse` Zod schema in contracts.
|
|
9615
|
+
200: rawJsonResponse("Discovered sitemaps and queued run returned.", looseObjectSchema),
|
|
9616
|
+
400: errorResponse("Invalid sitemap discovery request."),
|
|
9617
|
+
404: errorResponse("Project or connection not found.")
|
|
9373
9618
|
}
|
|
9374
9619
|
},
|
|
9375
9620
|
{
|
|
@@ -9391,9 +9636,9 @@ var routeCatalog = [
|
|
|
9391
9636
|
}
|
|
9392
9637
|
},
|
|
9393
9638
|
responses: {
|
|
9394
|
-
200:
|
|
9395
|
-
400:
|
|
9396
|
-
404:
|
|
9639
|
+
200: jsonResponse("Sitemap inspection run returned.", "RunDto"),
|
|
9640
|
+
400: errorResponse("Invalid sitemap inspection request."),
|
|
9641
|
+
404: errorResponse("Project or connection not found.")
|
|
9397
9642
|
}
|
|
9398
9643
|
},
|
|
9399
9644
|
{
|
|
@@ -9417,9 +9662,9 @@ var routeCatalog = [
|
|
|
9417
9662
|
}
|
|
9418
9663
|
},
|
|
9419
9664
|
responses: {
|
|
9420
|
-
200:
|
|
9421
|
-
400:
|
|
9422
|
-
404:
|
|
9665
|
+
200: jsonResponse("Indexing request results returned.", "IndexingRequestResponseDto"),
|
|
9666
|
+
400: errorResponse("Invalid indexing request."),
|
|
9667
|
+
404: errorResponse("Project or connection not found.")
|
|
9423
9668
|
}
|
|
9424
9669
|
},
|
|
9425
9670
|
{
|
|
@@ -9443,9 +9688,9 @@ var routeCatalog = [
|
|
|
9443
9688
|
}
|
|
9444
9689
|
},
|
|
9445
9690
|
responses: {
|
|
9446
|
-
200:
|
|
9447
|
-
400:
|
|
9448
|
-
404:
|
|
9691
|
+
200: jsonResponse("Bing connection returned.", "BingConnectResponseDto"),
|
|
9692
|
+
400: errorResponse("Invalid Bing connection request."),
|
|
9693
|
+
404: errorResponse("Project not found.")
|
|
9449
9694
|
}
|
|
9450
9695
|
},
|
|
9451
9696
|
{
|
|
@@ -9456,7 +9701,7 @@ var routeCatalog = [
|
|
|
9456
9701
|
parameters: [nameParameter],
|
|
9457
9702
|
responses: {
|
|
9458
9703
|
204: { description: "Bing connection deleted." },
|
|
9459
|
-
404:
|
|
9704
|
+
404: errorResponse("Project or connection not found.")
|
|
9460
9705
|
}
|
|
9461
9706
|
},
|
|
9462
9707
|
{
|
|
@@ -9466,8 +9711,8 @@ var routeCatalog = [
|
|
|
9466
9711
|
tags: ["bing"],
|
|
9467
9712
|
parameters: [nameParameter],
|
|
9468
9713
|
responses: {
|
|
9469
|
-
200:
|
|
9470
|
-
404:
|
|
9714
|
+
200: jsonResponse("Bing status returned.", "BingStatusDto"),
|
|
9715
|
+
404: errorResponse("Project not found.")
|
|
9471
9716
|
}
|
|
9472
9717
|
},
|
|
9473
9718
|
{
|
|
@@ -9477,9 +9722,9 @@ var routeCatalog = [
|
|
|
9477
9722
|
tags: ["bing"],
|
|
9478
9723
|
parameters: [nameParameter],
|
|
9479
9724
|
responses: {
|
|
9480
|
-
200:
|
|
9481
|
-
400:
|
|
9482
|
-
404:
|
|
9725
|
+
200: jsonResponse("Bing sites returned.", "BingSitesResponseDto"),
|
|
9726
|
+
400: errorResponse("Bing is not configured for this project."),
|
|
9727
|
+
404: errorResponse("Project not found.")
|
|
9483
9728
|
}
|
|
9484
9729
|
},
|
|
9485
9730
|
{
|
|
@@ -9503,9 +9748,9 @@ var routeCatalog = [
|
|
|
9503
9748
|
}
|
|
9504
9749
|
},
|
|
9505
9750
|
responses: {
|
|
9506
|
-
200:
|
|
9507
|
-
400:
|
|
9508
|
-
404:
|
|
9751
|
+
200: jsonResponse("Active Bing site updated.", "BingSetSiteResponseDto"),
|
|
9752
|
+
400: errorResponse("Invalid Bing site request."),
|
|
9753
|
+
404: errorResponse("Project or connection not found.")
|
|
9509
9754
|
}
|
|
9510
9755
|
},
|
|
9511
9756
|
{
|
|
@@ -9515,9 +9760,13 @@ var routeCatalog = [
|
|
|
9515
9760
|
tags: ["bing"],
|
|
9516
9761
|
parameters: [nameParameter],
|
|
9517
9762
|
responses: {
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9763
|
+
// Was incorrectly mapped to `BingCoverageSnapshotDto` (the daily
|
|
9764
|
+
// history snapshot — 4 fields). The /coverage handler actually
|
|
9765
|
+
// returns the nested summary shape with indexed/notIndexed/unknown
|
|
9766
|
+
// arrays. `BingCoverageSummaryDto` is the right ref.
|
|
9767
|
+
200: jsonResponse("Bing coverage returned.", "BingCoverageSummaryDto"),
|
|
9768
|
+
400: errorResponse("Bing is not configured for this project."),
|
|
9769
|
+
404: errorResponse("Project not found.")
|
|
9521
9770
|
}
|
|
9522
9771
|
},
|
|
9523
9772
|
{
|
|
@@ -9527,9 +9776,9 @@ var routeCatalog = [
|
|
|
9527
9776
|
tags: ["bing"],
|
|
9528
9777
|
parameters: [nameParameter, limitQueryParameter],
|
|
9529
9778
|
responses: {
|
|
9530
|
-
200:
|
|
9531
|
-
400:
|
|
9532
|
-
404:
|
|
9779
|
+
200: jsonArrayResponse("Bing coverage history returned.", "BingCoverageSnapshotDto"),
|
|
9780
|
+
400: errorResponse("Bing is not configured for this project."),
|
|
9781
|
+
404: errorResponse("Project not found.")
|
|
9533
9782
|
}
|
|
9534
9783
|
},
|
|
9535
9784
|
{
|
|
@@ -9539,9 +9788,9 @@ var routeCatalog = [
|
|
|
9539
9788
|
tags: ["bing"],
|
|
9540
9789
|
parameters: [nameParameter, { name: "url", in: "query", description: "Filter by URL.", schema: stringSchema }, limitQueryParameter],
|
|
9541
9790
|
responses: {
|
|
9542
|
-
200:
|
|
9543
|
-
400:
|
|
9544
|
-
404:
|
|
9791
|
+
200: jsonArrayResponse("Bing inspections returned.", "BingUrlInspectionDto"),
|
|
9792
|
+
400: errorResponse("Bing is not configured for this project."),
|
|
9793
|
+
404: errorResponse("Project not found.")
|
|
9545
9794
|
}
|
|
9546
9795
|
},
|
|
9547
9796
|
{
|
|
@@ -9565,9 +9814,9 @@ var routeCatalog = [
|
|
|
9565
9814
|
}
|
|
9566
9815
|
},
|
|
9567
9816
|
responses: {
|
|
9568
|
-
200:
|
|
9569
|
-
400:
|
|
9570
|
-
404:
|
|
9817
|
+
200: jsonResponse("Bing inspection result returned.", "BingUrlInspectionDto"),
|
|
9818
|
+
400: errorResponse("Invalid inspection request."),
|
|
9819
|
+
404: errorResponse("Project or connection not found.")
|
|
9571
9820
|
}
|
|
9572
9821
|
},
|
|
9573
9822
|
{
|
|
@@ -9590,9 +9839,9 @@ var routeCatalog = [
|
|
|
9590
9839
|
}
|
|
9591
9840
|
},
|
|
9592
9841
|
responses: {
|
|
9593
|
-
200:
|
|
9594
|
-
400:
|
|
9595
|
-
404:
|
|
9842
|
+
200: jsonResponse("Sitemap inspection run queued.", "RunDto"),
|
|
9843
|
+
400: errorResponse("Bing is not configured for this project."),
|
|
9844
|
+
404: errorResponse("Project not found.")
|
|
9596
9845
|
}
|
|
9597
9846
|
},
|
|
9598
9847
|
{
|
|
@@ -9616,9 +9865,9 @@ var routeCatalog = [
|
|
|
9616
9865
|
}
|
|
9617
9866
|
},
|
|
9618
9867
|
responses: {
|
|
9619
|
-
200:
|
|
9620
|
-
400:
|
|
9621
|
-
404:
|
|
9868
|
+
200: jsonResponse("Bing indexing request results returned.", "BingIndexingRequestResponseDto"),
|
|
9869
|
+
400: errorResponse("Invalid indexing request."),
|
|
9870
|
+
404: errorResponse("Project or connection not found.")
|
|
9622
9871
|
}
|
|
9623
9872
|
},
|
|
9624
9873
|
{
|
|
@@ -9628,9 +9877,9 @@ var routeCatalog = [
|
|
|
9628
9877
|
tags: ["bing"],
|
|
9629
9878
|
parameters: [nameParameter, limitQueryParameter],
|
|
9630
9879
|
responses: {
|
|
9631
|
-
200:
|
|
9632
|
-
400:
|
|
9633
|
-
404:
|
|
9880
|
+
200: jsonArrayResponse("Bing performance returned.", "BingKeywordStatsDto"),
|
|
9881
|
+
400: errorResponse("Bing is not configured for this project."),
|
|
9882
|
+
404: errorResponse("Project not found.")
|
|
9634
9883
|
}
|
|
9635
9884
|
},
|
|
9636
9885
|
{
|
|
@@ -9658,9 +9907,9 @@ var routeCatalog = [
|
|
|
9658
9907
|
}
|
|
9659
9908
|
},
|
|
9660
9909
|
responses: {
|
|
9661
|
-
200:
|
|
9662
|
-
400:
|
|
9663
|
-
404:
|
|
9910
|
+
200: jsonResponse("WordPress connection status returned.", "WordpressStatusDto"),
|
|
9911
|
+
400: errorResponse("Invalid WordPress connection request."),
|
|
9912
|
+
404: errorResponse("Project not found.")
|
|
9664
9913
|
}
|
|
9665
9914
|
},
|
|
9666
9915
|
{
|
|
@@ -9671,7 +9920,7 @@ var routeCatalog = [
|
|
|
9671
9920
|
parameters: [nameParameter],
|
|
9672
9921
|
responses: {
|
|
9673
9922
|
204: { description: "WordPress connection deleted." },
|
|
9674
|
-
404:
|
|
9923
|
+
404: errorResponse("Project or connection not found.")
|
|
9675
9924
|
}
|
|
9676
9925
|
},
|
|
9677
9926
|
{
|
|
@@ -9681,8 +9930,8 @@ var routeCatalog = [
|
|
|
9681
9930
|
tags: ["wordpress"],
|
|
9682
9931
|
parameters: [nameParameter],
|
|
9683
9932
|
responses: {
|
|
9684
|
-
200:
|
|
9685
|
-
404:
|
|
9933
|
+
200: jsonResponse("WordPress status returned.", "WordpressStatusDto"),
|
|
9934
|
+
404: errorResponse("Project not found.")
|
|
9686
9935
|
}
|
|
9687
9936
|
},
|
|
9688
9937
|
{
|
|
@@ -9692,9 +9941,9 @@ var routeCatalog = [
|
|
|
9692
9941
|
tags: ["wordpress"],
|
|
9693
9942
|
parameters: [nameParameter, wordpressEnvQueryParameter],
|
|
9694
9943
|
responses: {
|
|
9695
|
-
200:
|
|
9696
|
-
400:
|
|
9697
|
-
404:
|
|
9944
|
+
200: jsonArrayResponse("WordPress pages returned.", "WordpressPageSummaryDto"),
|
|
9945
|
+
400: errorResponse("Invalid environment or missing connection."),
|
|
9946
|
+
404: errorResponse("Project not found.")
|
|
9698
9947
|
}
|
|
9699
9948
|
},
|
|
9700
9949
|
{
|
|
@@ -9704,9 +9953,9 @@ var routeCatalog = [
|
|
|
9704
9953
|
tags: ["wordpress"],
|
|
9705
9954
|
parameters: [nameParameter, wordpressSlugQueryParameter, wordpressEnvQueryParameter],
|
|
9706
9955
|
responses: {
|
|
9707
|
-
200:
|
|
9708
|
-
400:
|
|
9709
|
-
404:
|
|
9956
|
+
200: jsonResponse("WordPress page returned.", "WordpressPageDetailDto"),
|
|
9957
|
+
400: errorResponse("Invalid slug or environment."),
|
|
9958
|
+
404: errorResponse("Project, connection, or page not found.")
|
|
9710
9959
|
}
|
|
9711
9960
|
},
|
|
9712
9961
|
{
|
|
@@ -9734,9 +9983,9 @@ var routeCatalog = [
|
|
|
9734
9983
|
}
|
|
9735
9984
|
},
|
|
9736
9985
|
responses: {
|
|
9737
|
-
200:
|
|
9738
|
-
400:
|
|
9739
|
-
404:
|
|
9986
|
+
200: jsonResponse("WordPress page created.", "WordpressPageDetailDto"),
|
|
9987
|
+
400: errorResponse("Invalid page creation request."),
|
|
9988
|
+
404: errorResponse("Project or connection not found.")
|
|
9740
9989
|
}
|
|
9741
9990
|
},
|
|
9742
9991
|
{
|
|
@@ -9765,9 +10014,9 @@ var routeCatalog = [
|
|
|
9765
10014
|
}
|
|
9766
10015
|
},
|
|
9767
10016
|
responses: {
|
|
9768
|
-
200:
|
|
9769
|
-
400:
|
|
9770
|
-
404:
|
|
10017
|
+
200: jsonResponse("WordPress page updated.", "WordpressPageDetailDto"),
|
|
10018
|
+
400: errorResponse("Invalid page update request."),
|
|
10019
|
+
404: errorResponse("Project, connection, or page not found.")
|
|
9771
10020
|
}
|
|
9772
10021
|
},
|
|
9773
10022
|
{
|
|
@@ -9795,9 +10044,10 @@ var routeCatalog = [
|
|
|
9795
10044
|
}
|
|
9796
10045
|
},
|
|
9797
10046
|
responses: {
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
10047
|
+
// TODO: Add `WordpressSeoStateDto` to the schema table (already in contracts).
|
|
10048
|
+
200: rawJsonResponse("WordPress SEO meta updated.", looseObjectSchema),
|
|
10049
|
+
400: errorResponse("SEO meta is unsupported or the request is invalid."),
|
|
10050
|
+
404: errorResponse("Project, connection, or page not found.")
|
|
9801
10051
|
}
|
|
9802
10052
|
},
|
|
9803
10053
|
{
|
|
@@ -9834,9 +10084,9 @@ var routeCatalog = [
|
|
|
9834
10084
|
}
|
|
9835
10085
|
},
|
|
9836
10086
|
responses: {
|
|
9837
|
-
200:
|
|
9838
|
-
400:
|
|
9839
|
-
404:
|
|
10087
|
+
200: jsonResponse("Bulk SEO meta update results returned.", "WordpressBulkMetaResultDto"),
|
|
10088
|
+
400: errorResponse("Invalid entries or environment."),
|
|
10089
|
+
404: errorResponse("Project or connection not found.")
|
|
9840
10090
|
}
|
|
9841
10091
|
},
|
|
9842
10092
|
{
|
|
@@ -9846,9 +10096,9 @@ var routeCatalog = [
|
|
|
9846
10096
|
tags: ["wordpress"],
|
|
9847
10097
|
parameters: [nameParameter, wordpressSlugQueryParameter, wordpressEnvQueryParameter],
|
|
9848
10098
|
responses: {
|
|
9849
|
-
200:
|
|
9850
|
-
400:
|
|
9851
|
-
404:
|
|
10099
|
+
200: jsonArrayResponse("WordPress schema blocks returned.", "WordpressSchemaBlockDto"),
|
|
10100
|
+
400: errorResponse("Invalid slug or environment."),
|
|
10101
|
+
404: errorResponse("Project, connection, or page not found.")
|
|
9852
10102
|
}
|
|
9853
10103
|
},
|
|
9854
10104
|
{
|
|
@@ -9875,9 +10125,9 @@ var routeCatalog = [
|
|
|
9875
10125
|
}
|
|
9876
10126
|
},
|
|
9877
10127
|
responses: {
|
|
9878
|
-
200:
|
|
9879
|
-
400:
|
|
9880
|
-
404:
|
|
10128
|
+
200: jsonResponse("Manual schema instructions returned.", "WordpressManualAssistDto"),
|
|
10129
|
+
400: errorResponse("Invalid schema request."),
|
|
10130
|
+
404: errorResponse("Project, connection, or page not found.")
|
|
9881
10131
|
}
|
|
9882
10132
|
},
|
|
9883
10133
|
{
|
|
@@ -9905,9 +10155,9 @@ var routeCatalog = [
|
|
|
9905
10155
|
}
|
|
9906
10156
|
},
|
|
9907
10157
|
responses: {
|
|
9908
|
-
200:
|
|
9909
|
-
400:
|
|
9910
|
-
404:
|
|
10158
|
+
200: jsonResponse("Schema deployment results returned.", "WordpressSchemaDeployResultDto"),
|
|
10159
|
+
400: errorResponse("Invalid profile or environment."),
|
|
10160
|
+
404: errorResponse("Project or connection not found.")
|
|
9911
10161
|
}
|
|
9912
10162
|
},
|
|
9913
10163
|
{
|
|
@@ -9917,9 +10167,9 @@ var routeCatalog = [
|
|
|
9917
10167
|
tags: ["wordpress"],
|
|
9918
10168
|
parameters: [nameParameter, wordpressEnvQueryParameter],
|
|
9919
10169
|
responses: {
|
|
9920
|
-
200:
|
|
9921
|
-
400:
|
|
9922
|
-
404:
|
|
10170
|
+
200: jsonResponse("Schema status per page returned.", "WordpressSchemaStatusResultDto"),
|
|
10171
|
+
400: errorResponse("Invalid environment."),
|
|
10172
|
+
404: errorResponse("Project or connection not found.")
|
|
9923
10173
|
}
|
|
9924
10174
|
},
|
|
9925
10175
|
{
|
|
@@ -9929,9 +10179,10 @@ var routeCatalog = [
|
|
|
9929
10179
|
tags: ["wordpress"],
|
|
9930
10180
|
parameters: [nameParameter, wordpressEnvQueryParameter],
|
|
9931
10181
|
responses: {
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
10182
|
+
// Returns raw text/plain content of llms.txt.
|
|
10183
|
+
200: { description: "llms.txt returned.", content: { "text/plain": { schema: { type: "string" } } } },
|
|
10184
|
+
400: errorResponse("Invalid environment or missing connection."),
|
|
10185
|
+
404: errorResponse("Project not found.")
|
|
9935
10186
|
}
|
|
9936
10187
|
},
|
|
9937
10188
|
{
|
|
@@ -9956,9 +10207,9 @@ var routeCatalog = [
|
|
|
9956
10207
|
}
|
|
9957
10208
|
},
|
|
9958
10209
|
responses: {
|
|
9959
|
-
200:
|
|
9960
|
-
400:
|
|
9961
|
-
404:
|
|
10210
|
+
200: jsonResponse("Manual llms.txt instructions returned.", "WordpressManualAssistDto"),
|
|
10211
|
+
400: errorResponse("Invalid llms.txt request."),
|
|
10212
|
+
404: errorResponse("Project or connection not found.")
|
|
9962
10213
|
}
|
|
9963
10214
|
},
|
|
9964
10215
|
{
|
|
@@ -9968,9 +10219,9 @@ var routeCatalog = [
|
|
|
9968
10219
|
tags: ["wordpress"],
|
|
9969
10220
|
parameters: [nameParameter, wordpressEnvQueryParameter],
|
|
9970
10221
|
responses: {
|
|
9971
|
-
200:
|
|
9972
|
-
400:
|
|
9973
|
-
404:
|
|
10222
|
+
200: jsonArrayResponse("WordPress audit returned.", "WordpressAuditPageDto"),
|
|
10223
|
+
400: errorResponse("Invalid environment or missing connection."),
|
|
10224
|
+
404: errorResponse("Project not found.")
|
|
9974
10225
|
}
|
|
9975
10226
|
},
|
|
9976
10227
|
{
|
|
@@ -9980,9 +10231,9 @@ var routeCatalog = [
|
|
|
9980
10231
|
tags: ["wordpress"],
|
|
9981
10232
|
parameters: [nameParameter, wordpressSlugQueryParameter],
|
|
9982
10233
|
responses: {
|
|
9983
|
-
200:
|
|
9984
|
-
400:
|
|
9985
|
-
404:
|
|
10234
|
+
200: jsonResponse("WordPress diff returned.", "WordpressDiffDto"),
|
|
10235
|
+
400: errorResponse("Invalid slug or missing staging configuration."),
|
|
10236
|
+
404: errorResponse("Project, connection, or page not found.")
|
|
9986
10237
|
}
|
|
9987
10238
|
},
|
|
9988
10239
|
{
|
|
@@ -9992,9 +10243,10 @@ var routeCatalog = [
|
|
|
9992
10243
|
tags: ["wordpress"],
|
|
9993
10244
|
parameters: [nameParameter],
|
|
9994
10245
|
responses: {
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
10246
|
+
// TODO: Add `WordpressSiteStatusDto` to the schema table (already in contracts).
|
|
10247
|
+
200: rawJsonResponse("WordPress staging status returned.", looseObjectSchema),
|
|
10248
|
+
400: errorResponse("WordPress is not configured for this project."),
|
|
10249
|
+
404: errorResponse("Project not found.")
|
|
9998
10250
|
}
|
|
9999
10251
|
},
|
|
10000
10252
|
{
|
|
@@ -10004,9 +10256,9 @@ var routeCatalog = [
|
|
|
10004
10256
|
tags: ["wordpress"],
|
|
10005
10257
|
parameters: [nameParameter],
|
|
10006
10258
|
responses: {
|
|
10007
|
-
200:
|
|
10008
|
-
400:
|
|
10009
|
-
404:
|
|
10259
|
+
200: jsonResponse("Manual staging push instructions returned.", "WordpressManualAssistDto"),
|
|
10260
|
+
400: errorResponse("Missing staging configuration."),
|
|
10261
|
+
404: errorResponse("Project or connection not found.")
|
|
10010
10262
|
}
|
|
10011
10263
|
},
|
|
10012
10264
|
{
|
|
@@ -10037,9 +10289,9 @@ var routeCatalog = [
|
|
|
10037
10289
|
}
|
|
10038
10290
|
},
|
|
10039
10291
|
responses: {
|
|
10040
|
-
200:
|
|
10041
|
-
400:
|
|
10042
|
-
404:
|
|
10292
|
+
200: jsonResponse("Onboarding result with step-by-step status.", "WordpressOnboardResultDto"),
|
|
10293
|
+
400: errorResponse("Invalid onboarding request."),
|
|
10294
|
+
404: errorResponse("Project not found.")
|
|
10043
10295
|
}
|
|
10044
10296
|
},
|
|
10045
10297
|
// GA4 routes
|
|
@@ -10065,9 +10317,10 @@ var routeCatalog = [
|
|
|
10065
10317
|
}
|
|
10066
10318
|
},
|
|
10067
10319
|
responses: {
|
|
10068
|
-
|
|
10069
|
-
|
|
10070
|
-
|
|
10320
|
+
// TODO: Add `GaConnectResponse` Zod schema in contracts.
|
|
10321
|
+
200: rawJsonResponse("GA4 connection established.", looseObjectSchema),
|
|
10322
|
+
400: errorResponse("Invalid GA4 connection request."),
|
|
10323
|
+
404: errorResponse("Project not found.")
|
|
10071
10324
|
}
|
|
10072
10325
|
},
|
|
10073
10326
|
{
|
|
@@ -10078,7 +10331,7 @@ var routeCatalog = [
|
|
|
10078
10331
|
parameters: [nameParameter],
|
|
10079
10332
|
responses: {
|
|
10080
10333
|
204: { description: "GA4 connection deleted." },
|
|
10081
|
-
404:
|
|
10334
|
+
404: errorResponse("Project or connection not found.")
|
|
10082
10335
|
}
|
|
10083
10336
|
},
|
|
10084
10337
|
{
|
|
@@ -10088,8 +10341,8 @@ var routeCatalog = [
|
|
|
10088
10341
|
tags: ["ga4"],
|
|
10089
10342
|
parameters: [nameParameter],
|
|
10090
10343
|
responses: {
|
|
10091
|
-
200:
|
|
10092
|
-
404:
|
|
10344
|
+
200: jsonResponse("GA4 status returned.", "GA4StatusDto"),
|
|
10345
|
+
404: errorResponse("Project not found.")
|
|
10093
10346
|
}
|
|
10094
10347
|
},
|
|
10095
10348
|
{
|
|
@@ -10112,9 +10365,9 @@ var routeCatalog = [
|
|
|
10112
10365
|
}
|
|
10113
10366
|
},
|
|
10114
10367
|
responses: {
|
|
10115
|
-
200:
|
|
10116
|
-
400:
|
|
10117
|
-
404:
|
|
10368
|
+
200: jsonResponse("GA4 sync completed.", "GA4SyncResponseDto"),
|
|
10369
|
+
400: errorResponse("GA4 is not connected."),
|
|
10370
|
+
404: errorResponse("Project not found.")
|
|
10118
10371
|
}
|
|
10119
10372
|
},
|
|
10120
10373
|
{
|
|
@@ -10124,9 +10377,10 @@ var routeCatalog = [
|
|
|
10124
10377
|
tags: ["ga4"],
|
|
10125
10378
|
parameters: [nameParameter, limitQueryParameter, analyticsWindowParameter],
|
|
10126
10379
|
responses: {
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10380
|
+
// TODO: Add `GaTrafficResponse` Zod schema in contracts.
|
|
10381
|
+
200: rawJsonResponse("GA4 traffic data returned.", looseObjectSchema),
|
|
10382
|
+
400: errorResponse("GA4 is not connected."),
|
|
10383
|
+
404: errorResponse("Project not found.")
|
|
10130
10384
|
}
|
|
10131
10385
|
},
|
|
10132
10386
|
{
|
|
@@ -10136,9 +10390,9 @@ var routeCatalog = [
|
|
|
10136
10390
|
tags: ["ga4"],
|
|
10137
10391
|
parameters: [nameParameter, analyticsWindowParameter],
|
|
10138
10392
|
responses: {
|
|
10139
|
-
200:
|
|
10140
|
-
400:
|
|
10141
|
-
404:
|
|
10393
|
+
200: jsonArrayResponse("AI referral history returned.", "GA4AiReferralHistoryEntry"),
|
|
10394
|
+
400: errorResponse("GA4 is not connected."),
|
|
10395
|
+
404: errorResponse("Project not found.")
|
|
10142
10396
|
}
|
|
10143
10397
|
},
|
|
10144
10398
|
{
|
|
@@ -10148,9 +10402,9 @@ var routeCatalog = [
|
|
|
10148
10402
|
tags: ["ga4"],
|
|
10149
10403
|
parameters: [nameParameter, analyticsWindowParameter],
|
|
10150
10404
|
responses: {
|
|
10151
|
-
200:
|
|
10152
|
-
400:
|
|
10153
|
-
404:
|
|
10405
|
+
200: jsonArrayResponse("Social referral history returned.", "GA4SocialReferralHistoryEntry"),
|
|
10406
|
+
400: errorResponse("GA4 is not connected."),
|
|
10407
|
+
404: errorResponse("Project not found.")
|
|
10154
10408
|
}
|
|
10155
10409
|
},
|
|
10156
10410
|
{
|
|
@@ -10160,9 +10414,10 @@ var routeCatalog = [
|
|
|
10160
10414
|
tags: ["ga4"],
|
|
10161
10415
|
parameters: [nameParameter],
|
|
10162
10416
|
responses: {
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10417
|
+
// TODO: Add `GaSocialReferralTrendResponse` Zod schema in contracts.
|
|
10418
|
+
200: rawJsonResponse("Social referral trend returned.", looseObjectSchema),
|
|
10419
|
+
400: errorResponse("GA4 is not connected."),
|
|
10420
|
+
404: errorResponse("Project not found.")
|
|
10166
10421
|
}
|
|
10167
10422
|
},
|
|
10168
10423
|
{
|
|
@@ -10172,9 +10427,10 @@ var routeCatalog = [
|
|
|
10172
10427
|
tags: ["ga4"],
|
|
10173
10428
|
parameters: [nameParameter],
|
|
10174
10429
|
responses: {
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
|
|
10430
|
+
// TODO: Add `GaAttributionTrendResponse` Zod schema in contracts.
|
|
10431
|
+
200: rawJsonResponse("Attribution trend returned.", looseObjectSchema),
|
|
10432
|
+
400: errorResponse("GA4 is not connected."),
|
|
10433
|
+
404: errorResponse("Project not found.")
|
|
10178
10434
|
}
|
|
10179
10435
|
},
|
|
10180
10436
|
{
|
|
@@ -10184,9 +10440,9 @@ var routeCatalog = [
|
|
|
10184
10440
|
tags: ["ga4"],
|
|
10185
10441
|
parameters: [nameParameter, analyticsWindowParameter],
|
|
10186
10442
|
responses: {
|
|
10187
|
-
200:
|
|
10188
|
-
400:
|
|
10189
|
-
404:
|
|
10443
|
+
200: jsonArrayResponse("Session history returned.", "GA4SessionHistoryEntry"),
|
|
10444
|
+
400: errorResponse("GA4 is not connected."),
|
|
10445
|
+
404: errorResponse("Project not found.")
|
|
10190
10446
|
}
|
|
10191
10447
|
},
|
|
10192
10448
|
{
|
|
@@ -10196,9 +10452,10 @@ var routeCatalog = [
|
|
|
10196
10452
|
tags: ["ga4"],
|
|
10197
10453
|
parameters: [nameParameter],
|
|
10198
10454
|
responses: {
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10455
|
+
// TODO: Add `GaCoverageResponse` Zod schema in contracts.
|
|
10456
|
+
200: rawJsonResponse("GA4 coverage data returned.", looseObjectSchema),
|
|
10457
|
+
400: errorResponse("GA4 is not connected."),
|
|
10458
|
+
404: errorResponse("Project not found.")
|
|
10202
10459
|
}
|
|
10203
10460
|
},
|
|
10204
10461
|
// Intelligence
|
|
@@ -10213,8 +10470,9 @@ var routeCatalog = [
|
|
|
10213
10470
|
{ name: "runId", in: "query", description: "Filter by run ID.", schema: stringSchema }
|
|
10214
10471
|
],
|
|
10215
10472
|
responses: {
|
|
10216
|
-
|
|
10217
|
-
|
|
10473
|
+
// TODO: Add `InsightDto` Zod schema in contracts.
|
|
10474
|
+
200: rawJsonResponse("Insights returned.", { type: "array", items: looseObjectSchema }),
|
|
10475
|
+
404: errorResponse("Project not found.")
|
|
10218
10476
|
}
|
|
10219
10477
|
},
|
|
10220
10478
|
{
|
|
@@ -10227,8 +10485,9 @@ var routeCatalog = [
|
|
|
10227
10485
|
{ name: "id", in: "path", required: true, description: "Insight ID.", schema: stringSchema }
|
|
10228
10486
|
],
|
|
10229
10487
|
responses: {
|
|
10230
|
-
|
|
10231
|
-
|
|
10488
|
+
// TODO: Add `InsightDto` Zod schema in contracts.
|
|
10489
|
+
200: rawJsonResponse("Insight returned.", looseObjectSchema),
|
|
10490
|
+
404: errorResponse("Insight not found.")
|
|
10232
10491
|
}
|
|
10233
10492
|
},
|
|
10234
10493
|
{
|
|
@@ -10241,8 +10500,9 @@ var routeCatalog = [
|
|
|
10241
10500
|
{ name: "id", in: "path", required: true, description: "Insight ID.", schema: stringSchema }
|
|
10242
10501
|
],
|
|
10243
10502
|
responses: {
|
|
10244
|
-
|
|
10245
|
-
|
|
10503
|
+
// TODO: Add `InsightDto` Zod schema in contracts.
|
|
10504
|
+
200: rawJsonResponse("Insight dismissed.", looseObjectSchema),
|
|
10505
|
+
404: errorResponse("Insight not found.")
|
|
10246
10506
|
}
|
|
10247
10507
|
},
|
|
10248
10508
|
{
|
|
@@ -10253,8 +10513,8 @@ var routeCatalog = [
|
|
|
10253
10513
|
description: "Bundles every section the canonry-report HTML output needs (executive summary, client summary, agency diagnostics, action plan, citation scorecard, competitor landscape \u2014 citation + mention landscapes, AI citation sources, GSC, GA4, social/AI referrals, indexing health, citations trend, insights, and recommended next steps) into a single canonical JSON payload. Backs `canonry report <project>` and MCP report reads.",
|
|
10254
10514
|
parameters: [nameParameter],
|
|
10255
10515
|
responses: {
|
|
10256
|
-
200:
|
|
10257
|
-
404:
|
|
10516
|
+
200: jsonResponse("Report returned.", "ProjectReportDto"),
|
|
10517
|
+
404: errorResponse("Project not found.")
|
|
10258
10518
|
}
|
|
10259
10519
|
},
|
|
10260
10520
|
{
|
|
@@ -10265,8 +10525,8 @@ var routeCatalog = [
|
|
|
10265
10525
|
description: "Server-rendered self-contained HTML version of the project report. Same data as `/projects/{name}/report` (JSON), rendered through the canonry HTML report renderer in agency or client mode. Returns `text/html` with `Content-Disposition: attachment` so browsers download it as `canonry-report-<project>-<audience>-YYYY-MM-DD.html`. Open in a browser and Print \u2192 Save as PDF for a PDF copy.",
|
|
10266
10526
|
parameters: [nameParameter, reportAudienceQueryParameter],
|
|
10267
10527
|
responses: {
|
|
10268
|
-
200: { description: "HTML report returned." },
|
|
10269
|
-
404:
|
|
10528
|
+
200: { description: "HTML report returned.", content: { "text/html": { schema: { type: "string" } } } },
|
|
10529
|
+
404: errorResponse("Project not found.")
|
|
10270
10530
|
}
|
|
10271
10531
|
},
|
|
10272
10532
|
{
|
|
@@ -10277,8 +10537,9 @@ var routeCatalog = [
|
|
|
10277
10537
|
tags: ["intelligence"],
|
|
10278
10538
|
parameters: [nameParameter],
|
|
10279
10539
|
responses: {
|
|
10280
|
-
|
|
10281
|
-
|
|
10540
|
+
// TODO: Add `HealthSnapshotDto` Zod schema in contracts.
|
|
10541
|
+
200: rawJsonResponse("Health snapshot or no-data sentinel returned.", looseObjectSchema),
|
|
10542
|
+
404: errorResponse("Project not found.")
|
|
10282
10543
|
}
|
|
10283
10544
|
},
|
|
10284
10545
|
{
|
|
@@ -10291,8 +10552,9 @@ var routeCatalog = [
|
|
|
10291
10552
|
{ name: "limit", in: "query", description: "Max results.", schema: stringSchema }
|
|
10292
10553
|
],
|
|
10293
10554
|
responses: {
|
|
10294
|
-
|
|
10295
|
-
|
|
10555
|
+
// TODO: Add `HealthSnapshotDto` Zod schema in contracts.
|
|
10556
|
+
200: rawJsonResponse("Health history returned.", { type: "array", items: looseObjectSchema }),
|
|
10557
|
+
404: errorResponse("Project not found.")
|
|
10296
10558
|
}
|
|
10297
10559
|
},
|
|
10298
10560
|
{
|
|
@@ -10303,8 +10565,8 @@ var routeCatalog = [
|
|
|
10303
10565
|
tags: ["intelligence"],
|
|
10304
10566
|
parameters: [nameParameter],
|
|
10305
10567
|
responses: {
|
|
10306
|
-
200:
|
|
10307
|
-
404:
|
|
10568
|
+
200: jsonResponse("Citation visibility report or no-data sentinel returned.", "CitationVisibilityResponse"),
|
|
10569
|
+
404: errorResponse("Project not found.")
|
|
10308
10570
|
}
|
|
10309
10571
|
},
|
|
10310
10572
|
// Content opportunity engine
|
|
@@ -10320,9 +10582,9 @@ var routeCatalog = [
|
|
|
10320
10582
|
{ name: "include-in-progress", in: "query", description: "Include rows with in-flight tracked actions.", schema: stringSchema }
|
|
10321
10583
|
],
|
|
10322
10584
|
responses: {
|
|
10323
|
-
200:
|
|
10324
|
-
400:
|
|
10325
|
-
404:
|
|
10585
|
+
200: jsonResponse("Targets returned.", "ContentTargetsResponseDto"),
|
|
10586
|
+
400: errorResponse("Invalid limit."),
|
|
10587
|
+
404: errorResponse("Project not found.")
|
|
10326
10588
|
}
|
|
10327
10589
|
},
|
|
10328
10590
|
{
|
|
@@ -10333,8 +10595,8 @@ var routeCatalog = [
|
|
|
10333
10595
|
tags: ["content"],
|
|
10334
10596
|
parameters: [nameParameter],
|
|
10335
10597
|
responses: {
|
|
10336
|
-
200:
|
|
10337
|
-
404:
|
|
10598
|
+
200: jsonResponse("Sources returned.", "ContentSourcesResponseDto"),
|
|
10599
|
+
404: errorResponse("Project not found.")
|
|
10338
10600
|
}
|
|
10339
10601
|
},
|
|
10340
10602
|
{
|
|
@@ -10345,8 +10607,8 @@ var routeCatalog = [
|
|
|
10345
10607
|
tags: ["content"],
|
|
10346
10608
|
parameters: [nameParameter],
|
|
10347
10609
|
responses: {
|
|
10348
|
-
200:
|
|
10349
|
-
404:
|
|
10610
|
+
200: jsonResponse("Gaps returned.", "ContentGapsResponseDto"),
|
|
10611
|
+
404: errorResponse("Project not found.")
|
|
10350
10612
|
}
|
|
10351
10613
|
},
|
|
10352
10614
|
{
|
|
@@ -10357,8 +10619,9 @@ var routeCatalog = [
|
|
|
10357
10619
|
tags: ["intelligence"],
|
|
10358
10620
|
parameters: [nameParameter],
|
|
10359
10621
|
responses: {
|
|
10360
|
-
|
|
10361
|
-
|
|
10622
|
+
// TODO: Add `ProjectOverviewDto` Zod schema in contracts.
|
|
10623
|
+
200: rawJsonResponse("Overview returned.", looseObjectSchema),
|
|
10624
|
+
404: errorResponse("Project not found.")
|
|
10362
10625
|
}
|
|
10363
10626
|
},
|
|
10364
10627
|
{
|
|
@@ -10373,9 +10636,10 @@ var routeCatalog = [
|
|
|
10373
10636
|
{ name: "limit", in: "query", description: "Max combined hits (1-50, default 25).", schema: stringSchema }
|
|
10374
10637
|
],
|
|
10375
10638
|
responses: {
|
|
10376
|
-
|
|
10377
|
-
|
|
10378
|
-
|
|
10639
|
+
// TODO: Add `ProjectSearchResponseDto` Zod schema in contracts (projectSearchResponseSchema exists).
|
|
10640
|
+
200: rawJsonResponse("Search hits returned.", looseObjectSchema),
|
|
10641
|
+
400: errorResponse("Query string missing or too short."),
|
|
10642
|
+
404: errorResponse("Project not found.")
|
|
10379
10643
|
}
|
|
10380
10644
|
},
|
|
10381
10645
|
{
|
|
@@ -10393,7 +10657,7 @@ var routeCatalog = [
|
|
|
10393
10657
|
}
|
|
10394
10658
|
],
|
|
10395
10659
|
responses: {
|
|
10396
|
-
200:
|
|
10660
|
+
200: jsonResponse("Doctor report returned.", "DoctorReportDto")
|
|
10397
10661
|
}
|
|
10398
10662
|
},
|
|
10399
10663
|
{
|
|
@@ -10412,8 +10676,8 @@ var routeCatalog = [
|
|
|
10412
10676
|
}
|
|
10413
10677
|
],
|
|
10414
10678
|
responses: {
|
|
10415
|
-
200:
|
|
10416
|
-
404:
|
|
10679
|
+
200: jsonResponse("Doctor report returned.", "DoctorReportDto"),
|
|
10680
|
+
404: errorResponse("Project not found.")
|
|
10417
10681
|
}
|
|
10418
10682
|
},
|
|
10419
10683
|
{
|
|
@@ -10423,8 +10687,8 @@ var routeCatalog = [
|
|
|
10423
10687
|
description: "Reports whether @duckdb/node-api is installed in the local plugin dir. Returns MISSING_DEPENDENCY (422) on deployments that cannot host the plugin (e.g. the cloud API).",
|
|
10424
10688
|
tags: ["backlinks"],
|
|
10425
10689
|
responses: {
|
|
10426
|
-
200:
|
|
10427
|
-
422:
|
|
10690
|
+
200: jsonResponse("Install status returned.", "BacklinksInstallStatusDto"),
|
|
10691
|
+
422: errorResponse("Backlinks feature is not available on this deployment.")
|
|
10428
10692
|
}
|
|
10429
10693
|
},
|
|
10430
10694
|
{
|
|
@@ -10434,8 +10698,8 @@ var routeCatalog = [
|
|
|
10434
10698
|
description: "Idempotently installs DuckDB into the canonry plugin dir. Returns MISSING_DEPENDENCY (422) when the host cannot perform the install.",
|
|
10435
10699
|
tags: ["backlinks"],
|
|
10436
10700
|
responses: {
|
|
10437
|
-
200:
|
|
10438
|
-
422:
|
|
10701
|
+
200: jsonResponse("Installed (or already present).", "BacklinksInstallResultDto"),
|
|
10702
|
+
422: errorResponse("Backlinks feature is not available on this deployment.")
|
|
10439
10703
|
}
|
|
10440
10704
|
},
|
|
10441
10705
|
{
|
|
@@ -10458,10 +10722,10 @@ var routeCatalog = [
|
|
|
10458
10722
|
}
|
|
10459
10723
|
},
|
|
10460
10724
|
responses: {
|
|
10461
|
-
200:
|
|
10462
|
-
201:
|
|
10463
|
-
400:
|
|
10464
|
-
422:
|
|
10725
|
+
200: jsonResponse("Existing in-flight sync returned.", "CcReleaseSyncDto"),
|
|
10726
|
+
201: jsonResponse("Sync queued.", "CcReleaseSyncDto"),
|
|
10727
|
+
400: errorResponse("Invalid release id."),
|
|
10728
|
+
422: errorResponse("Backlinks feature is not available on this deployment.")
|
|
10465
10729
|
}
|
|
10466
10730
|
},
|
|
10467
10731
|
{
|
|
@@ -10471,7 +10735,7 @@ var routeCatalog = [
|
|
|
10471
10735
|
description: "Returns syncs ordered by updatedAt DESC \u2014 re-queued rows surface ahead of untouched newer rows.",
|
|
10472
10736
|
tags: ["backlinks"],
|
|
10473
10737
|
responses: {
|
|
10474
|
-
200:
|
|
10738
|
+
200: jsonArrayResponse("Sync history returned.", "CcReleaseSyncDto")
|
|
10475
10739
|
}
|
|
10476
10740
|
},
|
|
10477
10741
|
{
|
|
@@ -10480,7 +10744,10 @@ var routeCatalog = [
|
|
|
10480
10744
|
summary: "Get the most recently-updated Common Crawl release sync",
|
|
10481
10745
|
tags: ["backlinks"],
|
|
10482
10746
|
responses: {
|
|
10483
|
-
|
|
10747
|
+
// Returns CcReleaseSyncDto | null
|
|
10748
|
+
200: rawJsonResponse("Latest sync returned, or null when no sync exists.", {
|
|
10749
|
+
oneOf: [{ $ref: "#/components/schemas/CcReleaseSyncDto" }, { type: "null" }]
|
|
10750
|
+
})
|
|
10484
10751
|
}
|
|
10485
10752
|
},
|
|
10486
10753
|
{
|
|
@@ -10489,7 +10756,7 @@ var routeCatalog = [
|
|
|
10489
10756
|
summary: "List cached Common Crawl releases on the local filesystem",
|
|
10490
10757
|
tags: ["backlinks"],
|
|
10491
10758
|
responses: {
|
|
10492
|
-
200:
|
|
10759
|
+
200: jsonArrayResponse("Cached release metadata returned.", "CcCachedRelease")
|
|
10493
10760
|
}
|
|
10494
10761
|
},
|
|
10495
10762
|
{
|
|
@@ -10499,8 +10766,10 @@ var routeCatalog = [
|
|
|
10499
10766
|
description: "Probes Common Crawl by HEAD-checking quarterly release slugs and returns the newest one published. The local server caches the result for ~5 minutes so repeated calls do not hammer Common Crawl.",
|
|
10500
10767
|
tags: ["backlinks"],
|
|
10501
10768
|
responses: {
|
|
10502
|
-
200:
|
|
10503
|
-
|
|
10769
|
+
200: rawJsonResponse("Latest available release, or null when no candidate slug responded.", {
|
|
10770
|
+
oneOf: [{ $ref: "#/components/schemas/CcAvailableRelease" }, { type: "null" }]
|
|
10771
|
+
}),
|
|
10772
|
+
422: errorResponse("Backlinks feature is not available on this deployment.")
|
|
10504
10773
|
}
|
|
10505
10774
|
},
|
|
10506
10775
|
{
|
|
@@ -10518,9 +10787,10 @@ var routeCatalog = [
|
|
|
10518
10787
|
}
|
|
10519
10788
|
],
|
|
10520
10789
|
responses: {
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10790
|
+
// TODO: Add `BacklinksCachePruneResultDto` Zod schema in contracts.
|
|
10791
|
+
200: rawJsonResponse("Cache pruned.", looseObjectSchema),
|
|
10792
|
+
400: errorResponse("Invalid release id."),
|
|
10793
|
+
422: errorResponse("Backlinks feature is not available on this deployment.")
|
|
10524
10794
|
}
|
|
10525
10795
|
},
|
|
10526
10796
|
{
|
|
@@ -10544,10 +10814,10 @@ var routeCatalog = [
|
|
|
10544
10814
|
}
|
|
10545
10815
|
},
|
|
10546
10816
|
responses: {
|
|
10547
|
-
201:
|
|
10548
|
-
400:
|
|
10549
|
-
404:
|
|
10550
|
-
422:
|
|
10817
|
+
201: jsonResponse("Extract run queued.", "RunDto"),
|
|
10818
|
+
400: errorResponse("Invalid release id."),
|
|
10819
|
+
404: errorResponse("Project not found."),
|
|
10820
|
+
422: errorResponse("Backlinks feature is not available on this deployment.")
|
|
10551
10821
|
}
|
|
10552
10822
|
},
|
|
10553
10823
|
{
|
|
@@ -10560,8 +10830,10 @@ var routeCatalog = [
|
|
|
10560
10830
|
{ name: "release", in: "query", description: "Release id filter.", schema: stringSchema }
|
|
10561
10831
|
],
|
|
10562
10832
|
responses: {
|
|
10563
|
-
200:
|
|
10564
|
-
|
|
10833
|
+
200: rawJsonResponse("Summary returned, or null when no backlinks exist.", {
|
|
10834
|
+
oneOf: [{ $ref: "#/components/schemas/BacklinkSummaryDto" }, { type: "null" }]
|
|
10835
|
+
}),
|
|
10836
|
+
404: errorResponse("Project not found.")
|
|
10565
10837
|
}
|
|
10566
10838
|
},
|
|
10567
10839
|
{
|
|
@@ -10576,8 +10848,8 @@ var routeCatalog = [
|
|
|
10576
10848
|
{ name: "offset", in: "query", description: "Pagination offset.", schema: stringSchema }
|
|
10577
10849
|
],
|
|
10578
10850
|
responses: {
|
|
10579
|
-
200:
|
|
10580
|
-
404:
|
|
10851
|
+
200: jsonResponse("Domain list returned.", "BacklinkListResponse"),
|
|
10852
|
+
404: errorResponse("Project not found.")
|
|
10581
10853
|
}
|
|
10582
10854
|
},
|
|
10583
10855
|
{
|
|
@@ -10587,8 +10859,8 @@ var routeCatalog = [
|
|
|
10587
10859
|
tags: ["backlinks"],
|
|
10588
10860
|
parameters: [nameParameter],
|
|
10589
10861
|
responses: {
|
|
10590
|
-
200:
|
|
10591
|
-
404:
|
|
10862
|
+
200: jsonArrayResponse("History returned oldest-first by queriedAt.", "BacklinkHistoryEntry"),
|
|
10863
|
+
404: errorResponse("Project not found.")
|
|
10592
10864
|
}
|
|
10593
10865
|
},
|
|
10594
10866
|
{
|
|
@@ -10617,9 +10889,9 @@ var routeCatalog = [
|
|
|
10617
10889
|
}
|
|
10618
10890
|
},
|
|
10619
10891
|
responses: {
|
|
10620
|
-
200:
|
|
10621
|
-
400:
|
|
10622
|
-
404:
|
|
10892
|
+
200: jsonResponse("Traffic source DTO returned.", "TrafficSourceDto"),
|
|
10893
|
+
400: errorResponse("Invalid Cloud Run connection request."),
|
|
10894
|
+
404: errorResponse("Project not found.")
|
|
10623
10895
|
}
|
|
10624
10896
|
},
|
|
10625
10897
|
{
|
|
@@ -10647,10 +10919,10 @@ var routeCatalog = [
|
|
|
10647
10919
|
}
|
|
10648
10920
|
},
|
|
10649
10921
|
responses: {
|
|
10650
|
-
200:
|
|
10651
|
-
400:
|
|
10652
|
-
404:
|
|
10653
|
-
502:
|
|
10922
|
+
200: jsonResponse("Traffic source DTO returned.", "TrafficSourceDto"),
|
|
10923
|
+
400: errorResponse("Invalid WordPress connection request."),
|
|
10924
|
+
404: errorResponse("Project not found."),
|
|
10925
|
+
502: errorResponse("WordPress plugin endpoint probe failed (bad credentials, unreachable host, etc.).")
|
|
10654
10926
|
}
|
|
10655
10927
|
},
|
|
10656
10928
|
{
|
|
@@ -10679,10 +10951,10 @@ var routeCatalog = [
|
|
|
10679
10951
|
}
|
|
10680
10952
|
},
|
|
10681
10953
|
responses: {
|
|
10682
|
-
200:
|
|
10683
|
-
400:
|
|
10684
|
-
404:
|
|
10685
|
-
502:
|
|
10954
|
+
200: jsonResponse("Traffic source DTO returned.", "TrafficSourceDto"),
|
|
10955
|
+
400: errorResponse("Invalid Vercel connection request."),
|
|
10956
|
+
404: errorResponse("Project not found."),
|
|
10957
|
+
502: errorResponse("Vercel request-logs endpoint probe failed (bad token, wrong project / team id, unreachable host, etc.).")
|
|
10686
10958
|
}
|
|
10687
10959
|
},
|
|
10688
10960
|
{
|
|
@@ -10709,10 +10981,10 @@ var routeCatalog = [
|
|
|
10709
10981
|
}
|
|
10710
10982
|
},
|
|
10711
10983
|
responses: {
|
|
10712
|
-
200:
|
|
10713
|
-
400:
|
|
10714
|
-
404:
|
|
10715
|
-
502:
|
|
10984
|
+
200: jsonResponse("Sync summary returned.", "TrafficSyncResponse"),
|
|
10985
|
+
400: errorResponse("Invalid sync request or missing credentials."),
|
|
10986
|
+
404: errorResponse("Project or traffic source not found."),
|
|
10987
|
+
502: errorResponse("Upstream Cloud Run pull or auth-token resolution failed.")
|
|
10716
10988
|
}
|
|
10717
10989
|
},
|
|
10718
10990
|
{
|
|
@@ -10739,9 +11011,9 @@ var routeCatalog = [
|
|
|
10739
11011
|
}
|
|
10740
11012
|
},
|
|
10741
11013
|
responses: {
|
|
10742
|
-
200:
|
|
10743
|
-
400:
|
|
10744
|
-
404:
|
|
11014
|
+
200: jsonResponse("Backfill submitted; poll the returned runId for completion.", "TrafficBackfillResponse"),
|
|
11015
|
+
400: errorResponse("Invalid backfill request or missing credentials."),
|
|
11016
|
+
404: errorResponse("Project or traffic source not found.")
|
|
10745
11017
|
}
|
|
10746
11018
|
},
|
|
10747
11019
|
{
|
|
@@ -10751,8 +11023,8 @@ var routeCatalog = [
|
|
|
10751
11023
|
tags: ["traffic"],
|
|
10752
11024
|
parameters: [nameParameter],
|
|
10753
11025
|
responses: {
|
|
10754
|
-
200:
|
|
10755
|
-
404:
|
|
11026
|
+
200: jsonResponse("Source list returned.", "TrafficSourceListResponse"),
|
|
11027
|
+
404: errorResponse("Project not found.")
|
|
10756
11028
|
}
|
|
10757
11029
|
},
|
|
10758
11030
|
{
|
|
@@ -10763,8 +11035,8 @@ var routeCatalog = [
|
|
|
10763
11035
|
tags: ["traffic"],
|
|
10764
11036
|
parameters: [nameParameter],
|
|
10765
11037
|
responses: {
|
|
10766
|
-
200:
|
|
10767
|
-
404:
|
|
11038
|
+
200: jsonResponse("Status returned.", "TrafficStatusResponse"),
|
|
11039
|
+
404: errorResponse("Project not found.")
|
|
10768
11040
|
}
|
|
10769
11041
|
},
|
|
10770
11042
|
{
|
|
@@ -10777,8 +11049,8 @@ var routeCatalog = [
|
|
|
10777
11049
|
{ name: "id", in: "path", required: true, description: "Traffic source ID.", schema: stringSchema }
|
|
10778
11050
|
],
|
|
10779
11051
|
responses: {
|
|
10780
|
-
200:
|
|
10781
|
-
404:
|
|
11052
|
+
200: jsonResponse("Source detail returned.", "TrafficSourceDetailDto"),
|
|
11053
|
+
404: errorResponse("Project or source not found.")
|
|
10782
11054
|
}
|
|
10783
11055
|
},
|
|
10784
11056
|
{
|
|
@@ -10796,9 +11068,9 @@ var routeCatalog = [
|
|
|
10796
11068
|
{ name: "sourceId", in: "query", description: "Restrict to a single traffic source.", schema: stringSchema }
|
|
10797
11069
|
],
|
|
10798
11070
|
responses: {
|
|
10799
|
-
200:
|
|
10800
|
-
400:
|
|
10801
|
-
404:
|
|
11071
|
+
200: jsonResponse("Events returned with windowed totals.", "TrafficEventsResponse"),
|
|
11072
|
+
400: errorResponse("Invalid query parameters."),
|
|
11073
|
+
404: errorResponse("Project not found.")
|
|
10802
11074
|
}
|
|
10803
11075
|
},
|
|
10804
11076
|
{
|
|
@@ -10829,10 +11101,11 @@ var routeCatalog = [
|
|
|
10829
11101
|
}
|
|
10830
11102
|
},
|
|
10831
11103
|
responses: {
|
|
10832
|
-
|
|
10833
|
-
|
|
10834
|
-
|
|
10835
|
-
|
|
11104
|
+
// TODO: Add `DiscoveryRunResponse` Zod schema in contracts (`{ runId, sessionId, status, consolidated }`).
|
|
11105
|
+
200: rawJsonResponse("An in-flight session with the same project + ICP was reused; returns { runId, sessionId, status, consolidated: true }. The request's dedupThreshold / maxProbes are ignored.", looseObjectSchema),
|
|
11106
|
+
201: rawJsonResponse("New discovery session enqueued; returns { runId, sessionId, status, consolidated: false }.", looseObjectSchema),
|
|
11107
|
+
400: errorResponse("Missing or invalid ICP / parameters."),
|
|
11108
|
+
404: errorResponse("Project not found.")
|
|
10836
11109
|
}
|
|
10837
11110
|
},
|
|
10838
11111
|
{
|
|
@@ -10846,8 +11119,8 @@ var routeCatalog = [
|
|
|
10846
11119
|
{ name: "limit", in: "query", description: "Max sessions returned. Default 50.", schema: stringSchema }
|
|
10847
11120
|
],
|
|
10848
11121
|
responses: {
|
|
10849
|
-
200:
|
|
10850
|
-
404:
|
|
11122
|
+
200: jsonArrayResponse("Sessions returned.", "DiscoverySessionDto"),
|
|
11123
|
+
404: errorResponse("Project not found.")
|
|
10851
11124
|
}
|
|
10852
11125
|
},
|
|
10853
11126
|
{
|
|
@@ -10861,8 +11134,8 @@ var routeCatalog = [
|
|
|
10861
11134
|
{ name: "id", in: "path", required: true, description: "Discovery session ID.", schema: stringSchema }
|
|
10862
11135
|
],
|
|
10863
11136
|
responses: {
|
|
10864
|
-
200:
|
|
10865
|
-
404:
|
|
11137
|
+
200: jsonResponse("Session detail returned.", "DiscoverySessionDetailDto"),
|
|
11138
|
+
404: errorResponse("Project or session not found.")
|
|
10866
11139
|
}
|
|
10867
11140
|
},
|
|
10868
11141
|
{
|
|
@@ -10876,8 +11149,8 @@ var routeCatalog = [
|
|
|
10876
11149
|
{ name: "id", in: "path", required: true, description: "Discovery session ID.", schema: stringSchema }
|
|
10877
11150
|
],
|
|
10878
11151
|
responses: {
|
|
10879
|
-
200:
|
|
10880
|
-
404:
|
|
11152
|
+
200: jsonResponse("Promote preview returned.", "DiscoveryPromotePreview"),
|
|
11153
|
+
404: errorResponse("Project or session not found.")
|
|
10881
11154
|
}
|
|
10882
11155
|
},
|
|
10883
11156
|
{
|
|
@@ -10920,9 +11193,9 @@ var routeCatalog = [
|
|
|
10920
11193
|
}
|
|
10921
11194
|
},
|
|
10922
11195
|
responses: {
|
|
10923
|
-
200:
|
|
10924
|
-
400:
|
|
10925
|
-
404:
|
|
11196
|
+
200: jsonResponse("Promotion applied; returns promoted + skipped query/competitor lists.", "DiscoveryPromoteResult"),
|
|
11197
|
+
400: errorResponse("Session is not completed, or invalid request body."),
|
|
11198
|
+
404: errorResponse("Project or session not found.")
|
|
10926
11199
|
}
|
|
10927
11200
|
}
|
|
10928
11201
|
];
|
|
@@ -10935,8 +11208,9 @@ var canonryLocalRouteCatalog = [
|
|
|
10935
11208
|
tags: ["agent"],
|
|
10936
11209
|
parameters: [nameParameter],
|
|
10937
11210
|
responses: {
|
|
10938
|
-
|
|
10939
|
-
|
|
11211
|
+
// TODO: Add `AgentTranscriptDto` Zod schema in contracts.
|
|
11212
|
+
200: rawJsonResponse("Transcript returned.", looseObjectSchema),
|
|
11213
|
+
404: errorResponse("Project not found.")
|
|
10940
11214
|
}
|
|
10941
11215
|
},
|
|
10942
11216
|
{
|
|
@@ -10947,8 +11221,9 @@ var canonryLocalRouteCatalog = [
|
|
|
10947
11221
|
tags: ["agent"],
|
|
10948
11222
|
parameters: [nameParameter],
|
|
10949
11223
|
responses: {
|
|
10950
|
-
|
|
10951
|
-
|
|
11224
|
+
// Returns { status: 'reset' } sentinel.
|
|
11225
|
+
200: rawJsonResponse("Session reset.", { type: "object", properties: { status: { type: "string", enum: ["reset"] } } }),
|
|
11226
|
+
404: errorResponse("Project not found.")
|
|
10952
11227
|
}
|
|
10953
11228
|
},
|
|
10954
11229
|
{
|
|
@@ -10959,8 +11234,9 @@ var canonryLocalRouteCatalog = [
|
|
|
10959
11234
|
tags: ["agent"],
|
|
10960
11235
|
parameters: [nameParameter],
|
|
10961
11236
|
responses: {
|
|
10962
|
-
|
|
10963
|
-
|
|
11237
|
+
// TODO: Add `AgentMemoryListResponse` Zod schema in contracts.
|
|
11238
|
+
200: rawJsonResponse("Memory entries returned.", looseObjectSchema),
|
|
11239
|
+
404: errorResponse("Project not found.")
|
|
10964
11240
|
}
|
|
10965
11241
|
},
|
|
10966
11242
|
{
|
|
@@ -10986,9 +11262,10 @@ var canonryLocalRouteCatalog = [
|
|
|
10986
11262
|
}
|
|
10987
11263
|
},
|
|
10988
11264
|
responses: {
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
11265
|
+
// TODO: Add `AgentMemoryEntryDto` Zod schema in contracts.
|
|
11266
|
+
200: rawJsonResponse("Entry upserted.", looseObjectSchema),
|
|
11267
|
+
400: errorResponse("Validation failed (key length, value size, reserved prefix)."),
|
|
11268
|
+
404: errorResponse("Project not found.")
|
|
10992
11269
|
}
|
|
10993
11270
|
},
|
|
10994
11271
|
{
|
|
@@ -11013,9 +11290,10 @@ var canonryLocalRouteCatalog = [
|
|
|
11013
11290
|
}
|
|
11014
11291
|
},
|
|
11015
11292
|
responses: {
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
|
|
11293
|
+
// Returns { status: 'removed' | 'missing' } sentinel.
|
|
11294
|
+
200: rawJsonResponse("Entry removed or already absent.", { type: "object", properties: { status: { type: "string", enum: ["removed", "missing"] } } }),
|
|
11295
|
+
400: errorResponse("Validation failed (reserved prefix)."),
|
|
11296
|
+
404: errorResponse("Project not found.")
|
|
11019
11297
|
}
|
|
11020
11298
|
},
|
|
11021
11299
|
{
|
|
@@ -11026,8 +11304,8 @@ var canonryLocalRouteCatalog = [
|
|
|
11026
11304
|
tags: ["agent"],
|
|
11027
11305
|
parameters: [nameParameter],
|
|
11028
11306
|
responses: {
|
|
11029
|
-
200:
|
|
11030
|
-
404:
|
|
11307
|
+
200: jsonResponse("Providers returned.", "AgentProvidersResponseDto"),
|
|
11308
|
+
404: errorResponse("Project not found.")
|
|
11031
11309
|
}
|
|
11032
11310
|
},
|
|
11033
11311
|
{
|
|
@@ -11066,10 +11344,11 @@ var canonryLocalRouteCatalog = [
|
|
|
11066
11344
|
}
|
|
11067
11345
|
},
|
|
11068
11346
|
responses: {
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
|
|
11072
|
-
|
|
11347
|
+
// Returns text/event-stream — codegen consumers should treat as a stream.
|
|
11348
|
+
200: { description: "SSE stream of AgentEvent frames.", content: { "text/event-stream": { schema: { type: "string" } } } },
|
|
11349
|
+
400: errorResponse("Missing or empty prompt."),
|
|
11350
|
+
404: errorResponse("Project not found."),
|
|
11351
|
+
409: errorResponse("Another Aero turn is already in flight.")
|
|
11073
11352
|
}
|
|
11074
11353
|
}
|
|
11075
11354
|
];
|
|
@@ -11095,8 +11374,14 @@ function buildOpenApiDocument(info = {}) {
|
|
|
11095
11374
|
acc[fullPath] = pathItem;
|
|
11096
11375
|
return acc;
|
|
11097
11376
|
}, {});
|
|
11377
|
+
const schemas = buildComponentSchemas();
|
|
11098
11378
|
return {
|
|
11099
|
-
|
|
11379
|
+
// OpenAPI 3.0 (not 3.1) so `nullable: true` on emitted schemas is the
|
|
11380
|
+
// canonical nullability marker. `z.toJSONSchema(..., { target: 'openapi-3.0' })`
|
|
11381
|
+
// outputs `nullable: true`; declaring 3.1 would tell consumers (and the
|
|
11382
|
+
// hey-api codegen) to expect 3.1-style `type: ["string", "null"]` instead,
|
|
11383
|
+
// and they'd silently strip the `null` from optional fields.
|
|
11384
|
+
openapi: "3.0.0",
|
|
11100
11385
|
info: {
|
|
11101
11386
|
title: info.title ?? "Canonry API",
|
|
11102
11387
|
version: info.version ?? "0.0.0",
|
|
@@ -11115,7 +11400,8 @@ function buildOpenApiDocument(info = {}) {
|
|
|
11115
11400
|
scheme: "bearer",
|
|
11116
11401
|
bearerFormat: "API key"
|
|
11117
11402
|
}
|
|
11118
|
-
}
|
|
11403
|
+
},
|
|
11404
|
+
schemas
|
|
11119
11405
|
},
|
|
11120
11406
|
paths
|
|
11121
11407
|
};
|
|
@@ -11290,12 +11576,12 @@ async function telemetryRoutes(app, opts) {
|
|
|
11290
11576
|
|
|
11291
11577
|
// ../api-routes/src/schedules.ts
|
|
11292
11578
|
import crypto11 from "crypto";
|
|
11293
|
-
import { and as
|
|
11579
|
+
import { and as and11, eq as eq16 } from "drizzle-orm";
|
|
11294
11580
|
function parseKindParam(raw) {
|
|
11295
11581
|
if (raw === void 0 || raw === null || raw === "") return SchedulableRunKinds["answer-visibility"];
|
|
11296
11582
|
const parsed = schedulableRunKindSchema.safeParse(raw);
|
|
11297
11583
|
if (!parsed.success) {
|
|
11298
|
-
throw validationError(`Invalid kind "${
|
|
11584
|
+
throw validationError(`Invalid kind "${JSON.stringify(raw)}". Must be one of: ${Object.values(SchedulableRunKinds).join(", ")}`);
|
|
11299
11585
|
}
|
|
11300
11586
|
return parsed.data;
|
|
11301
11587
|
}
|
|
@@ -11356,7 +11642,7 @@ async function scheduleRoutes(app, opts) {
|
|
|
11356
11642
|
}
|
|
11357
11643
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11358
11644
|
const enabledInt = enabled === false ? 0 : 1;
|
|
11359
|
-
const existing = app.db.select().from(schedules).where(
|
|
11645
|
+
const existing = app.db.select().from(schedules).where(and11(eq16(schedules.projectId, project.id), eq16(schedules.kind, kind))).get();
|
|
11360
11646
|
if (existing) {
|
|
11361
11647
|
app.db.update(schedules).set({
|
|
11362
11648
|
cronExpr,
|
|
@@ -11390,13 +11676,13 @@ async function scheduleRoutes(app, opts) {
|
|
|
11390
11676
|
diff: { kind, cronExpr, preset, timezone, providers, sourceId }
|
|
11391
11677
|
});
|
|
11392
11678
|
opts.onScheduleUpdated?.("upsert", project.id, kind);
|
|
11393
|
-
const schedule = app.db.select().from(schedules).where(
|
|
11679
|
+
const schedule = app.db.select().from(schedules).where(and11(eq16(schedules.projectId, project.id), eq16(schedules.kind, kind))).get();
|
|
11394
11680
|
return reply.status(existing ? 200 : 201).send(formatSchedule(schedule));
|
|
11395
11681
|
});
|
|
11396
11682
|
app.get("/projects/:name/schedule", async (request, reply) => {
|
|
11397
11683
|
const project = resolveProject(app.db, request.params.name);
|
|
11398
11684
|
const kind = parseKindParam(request.query?.kind);
|
|
11399
|
-
const schedule = app.db.select().from(schedules).where(
|
|
11685
|
+
const schedule = app.db.select().from(schedules).where(and11(eq16(schedules.projectId, project.id), eq16(schedules.kind, kind))).get();
|
|
11400
11686
|
if (!schedule) {
|
|
11401
11687
|
throw notFound("Schedule", `${request.params.name} (kind=${kind})`);
|
|
11402
11688
|
}
|
|
@@ -11405,7 +11691,7 @@ async function scheduleRoutes(app, opts) {
|
|
|
11405
11691
|
app.delete("/projects/:name/schedule", async (request, reply) => {
|
|
11406
11692
|
const project = resolveProject(app.db, request.params.name);
|
|
11407
11693
|
const kind = parseKindParam(request.query?.kind);
|
|
11408
|
-
const schedule = app.db.select().from(schedules).where(
|
|
11694
|
+
const schedule = app.db.select().from(schedules).where(and11(eq16(schedules.projectId, project.id), eq16(schedules.kind, kind))).get();
|
|
11409
11695
|
if (!schedule) {
|
|
11410
11696
|
throw notFound("Schedule", `${request.params.name} (kind=${kind})`);
|
|
11411
11697
|
}
|
|
@@ -11562,7 +11848,7 @@ function formatNotification(row) {
|
|
|
11562
11848
|
|
|
11563
11849
|
// ../api-routes/src/google.ts
|
|
11564
11850
|
import crypto14 from "crypto";
|
|
11565
|
-
import { eq as eq18, and as
|
|
11851
|
+
import { eq as eq18, and as and12, desc as desc8, sql as sql7 } from "drizzle-orm";
|
|
11566
11852
|
|
|
11567
11853
|
// ../integration-google/src/constants.ts
|
|
11568
11854
|
var GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
@@ -11946,6 +12232,22 @@ var GA4_DEFAULT_SYNC_DAYS = 30;
|
|
|
11946
12232
|
var GA4_MAX_SYNC_DAYS = 90;
|
|
11947
12233
|
var GA4_REQUEST_TIMEOUT_MS = 3e4;
|
|
11948
12234
|
var GA4_MAX_PAGES = 50;
|
|
12235
|
+
var GA4_DIMENSIONS = {
|
|
12236
|
+
date: "date",
|
|
12237
|
+
landingPagePlusQueryString: "landingPagePlusQueryString",
|
|
12238
|
+
sessionSource: "sessionSource",
|
|
12239
|
+
sessionMedium: "sessionMedium",
|
|
12240
|
+
sessionManualSource: "sessionManualSource",
|
|
12241
|
+
sessionManualMedium: "sessionManualMedium",
|
|
12242
|
+
firstUserSource: "firstUserSource",
|
|
12243
|
+
firstUserMedium: "firstUserMedium",
|
|
12244
|
+
sessionDefaultChannelGrouping: "sessionDefaultChannelGrouping",
|
|
12245
|
+
sessionDefaultChannelGroup: "sessionDefaultChannelGroup"
|
|
12246
|
+
};
|
|
12247
|
+
var GA4_METRICS = {
|
|
12248
|
+
sessions: "sessions",
|
|
12249
|
+
totalUsers: "totalUsers"
|
|
12250
|
+
};
|
|
11949
12251
|
|
|
11950
12252
|
// ../integration-google-analytics/src/types.ts
|
|
11951
12253
|
var GA4ApiError = class extends Error {
|
|
@@ -12137,8 +12439,8 @@ var AI_REFERRAL_SOURCE_FILTERS = [
|
|
|
12137
12439
|
{ matchType: "CONTAINS", value: "anthropic" },
|
|
12138
12440
|
{ matchType: "CONTAINS", value: "copilot" },
|
|
12139
12441
|
{ matchType: "CONTAINS", value: "phind" },
|
|
12140
|
-
{ matchType: "EXACT", value:
|
|
12141
|
-
{ matchType: "CONTAINS", value:
|
|
12442
|
+
{ matchType: "EXACT", value: AI_ENGINE_DOMAINS.you },
|
|
12443
|
+
{ matchType: "CONTAINS", value: AI_ENGINE_DOMAINS.metaAi }
|
|
12142
12444
|
];
|
|
12143
12445
|
async function fetchTrafficByLandingPage(accessToken, propertyId, days) {
|
|
12144
12446
|
validateAccessToken2(accessToken);
|
|
@@ -12157,12 +12459,12 @@ async function fetchTrafficByLandingPage(accessToken, propertyId, days) {
|
|
|
12157
12459
|
const request = {
|
|
12158
12460
|
dateRanges: [{ startDate: formatDate2(startDate), endDate: formatDate2(endDate) }],
|
|
12159
12461
|
dimensions: [
|
|
12160
|
-
{ name:
|
|
12161
|
-
{ name:
|
|
12462
|
+
{ name: GA4_DIMENSIONS.date },
|
|
12463
|
+
{ name: GA4_DIMENSIONS.landingPagePlusQueryString }
|
|
12162
12464
|
],
|
|
12163
12465
|
metrics: [
|
|
12164
|
-
{ name:
|
|
12165
|
-
{ name:
|
|
12466
|
+
{ name: GA4_METRICS.sessions },
|
|
12467
|
+
{ name: GA4_METRICS.totalUsers }
|
|
12166
12468
|
],
|
|
12167
12469
|
limit: PAGE_SIZE,
|
|
12168
12470
|
offset
|
|
@@ -12191,11 +12493,11 @@ async function fetchTrafficByLandingPage(accessToken, propertyId, days) {
|
|
|
12191
12493
|
organicPageCount++;
|
|
12192
12494
|
const organicRequest = {
|
|
12193
12495
|
dateRanges: [{ startDate: formatDate2(startDate), endDate: formatDate2(endDate) }],
|
|
12194
|
-
dimensions: [{ name:
|
|
12195
|
-
metrics: [{ name:
|
|
12496
|
+
dimensions: [{ name: GA4_DIMENSIONS.date }, { name: GA4_DIMENSIONS.landingPagePlusQueryString }],
|
|
12497
|
+
metrics: [{ name: GA4_METRICS.sessions }],
|
|
12196
12498
|
dimensionFilter: {
|
|
12197
12499
|
filter: {
|
|
12198
|
-
fieldName:
|
|
12500
|
+
fieldName: GA4_DIMENSIONS.sessionDefaultChannelGrouping,
|
|
12199
12501
|
stringFilter: { matchType: "EXACT", value: "Organic Search" }
|
|
12200
12502
|
}
|
|
12201
12503
|
},
|
|
@@ -12219,11 +12521,11 @@ async function fetchTrafficByLandingPage(accessToken, propertyId, days) {
|
|
|
12219
12521
|
directPageCount++;
|
|
12220
12522
|
const directRequest = {
|
|
12221
12523
|
dateRanges: [{ startDate: formatDate2(startDate), endDate: formatDate2(endDate) }],
|
|
12222
|
-
dimensions: [{ name:
|
|
12223
|
-
metrics: [{ name:
|
|
12524
|
+
dimensions: [{ name: GA4_DIMENSIONS.date }, { name: GA4_DIMENSIONS.landingPagePlusQueryString }],
|
|
12525
|
+
metrics: [{ name: GA4_METRICS.sessions }],
|
|
12224
12526
|
dimensionFilter: {
|
|
12225
12527
|
filter: {
|
|
12226
|
-
fieldName:
|
|
12528
|
+
fieldName: GA4_DIMENSIONS.sessionDefaultChannelGrouping,
|
|
12227
12529
|
stringFilter: { matchType: "EXACT", value: "Direct" }
|
|
12228
12530
|
}
|
|
12229
12531
|
},
|
|
@@ -12268,8 +12570,8 @@ async function verifyConnectionWithToken(accessToken, propertyId) {
|
|
|
12268
12570
|
startDate.setDate(startDate.getDate() - 1);
|
|
12269
12571
|
await runReport(accessToken, propertyId, {
|
|
12270
12572
|
dateRanges: [{ startDate: formatDate2(startDate), endDate: formatDate2(endDate) }],
|
|
12271
|
-
dimensions: [{ name:
|
|
12272
|
-
metrics: [{ name:
|
|
12573
|
+
dimensions: [{ name: GA4_DIMENSIONS.date }],
|
|
12574
|
+
metrics: [{ name: GA4_METRICS.sessions }],
|
|
12273
12575
|
limit: 1
|
|
12274
12576
|
});
|
|
12275
12577
|
return true;
|
|
@@ -12287,16 +12589,16 @@ async function fetchAggregateSummary(accessToken, propertyId, days) {
|
|
|
12287
12589
|
{
|
|
12288
12590
|
dateRanges: [dateRange],
|
|
12289
12591
|
dimensions: [],
|
|
12290
|
-
metrics: [{ name:
|
|
12592
|
+
metrics: [{ name: GA4_METRICS.sessions }, { name: GA4_METRICS.totalUsers }],
|
|
12291
12593
|
limit: 1
|
|
12292
12594
|
},
|
|
12293
12595
|
{
|
|
12294
12596
|
dateRanges: [dateRange],
|
|
12295
12597
|
dimensions: [],
|
|
12296
|
-
metrics: [{ name:
|
|
12598
|
+
metrics: [{ name: GA4_METRICS.sessions }],
|
|
12297
12599
|
dimensionFilter: {
|
|
12298
12600
|
filter: {
|
|
12299
|
-
fieldName:
|
|
12601
|
+
fieldName: GA4_DIMENSIONS.sessionDefaultChannelGrouping,
|
|
12300
12602
|
stringFilter: { matchType: "EXACT", value: "Organic Search" }
|
|
12301
12603
|
}
|
|
12302
12604
|
},
|
|
@@ -12332,16 +12634,16 @@ async function fetchWindowSummary(accessToken, propertyId, windowKey) {
|
|
|
12332
12634
|
{
|
|
12333
12635
|
dateRanges: [dateRange],
|
|
12334
12636
|
dimensions: [],
|
|
12335
|
-
metrics: [{ name:
|
|
12637
|
+
metrics: [{ name: GA4_METRICS.sessions }, { name: GA4_METRICS.totalUsers }],
|
|
12336
12638
|
limit: 1
|
|
12337
12639
|
},
|
|
12338
12640
|
{
|
|
12339
12641
|
dateRanges: [dateRange],
|
|
12340
12642
|
dimensions: [],
|
|
12341
|
-
metrics: [{ name:
|
|
12643
|
+
metrics: [{ name: GA4_METRICS.sessions }],
|
|
12342
12644
|
dimensionFilter: {
|
|
12343
12645
|
filter: {
|
|
12344
|
-
fieldName:
|
|
12646
|
+
fieldName: GA4_DIMENSIONS.sessionDefaultChannelGrouping,
|
|
12345
12647
|
stringFilter: { matchType: "EXACT", value: "Organic Search" }
|
|
12346
12648
|
}
|
|
12347
12649
|
},
|
|
@@ -12350,10 +12652,10 @@ async function fetchWindowSummary(accessToken, propertyId, windowKey) {
|
|
|
12350
12652
|
{
|
|
12351
12653
|
dateRanges: [dateRange],
|
|
12352
12654
|
dimensions: [],
|
|
12353
|
-
metrics: [{ name:
|
|
12655
|
+
metrics: [{ name: GA4_METRICS.sessions }],
|
|
12354
12656
|
dimensionFilter: {
|
|
12355
12657
|
filter: {
|
|
12356
|
-
fieldName:
|
|
12658
|
+
fieldName: GA4_DIMENSIONS.sessionDefaultChannelGrouping,
|
|
12357
12659
|
stringFilter: { matchType: "EXACT", value: "Direct" }
|
|
12358
12660
|
}
|
|
12359
12661
|
},
|
|
@@ -12386,9 +12688,9 @@ async function fetchAiReferrals(accessToken, propertyId, days) {
|
|
|
12386
12688
|
const PAGE_SIZE = 1e3;
|
|
12387
12689
|
const rows = [];
|
|
12388
12690
|
const dimensionPairs = [
|
|
12389
|
-
[
|
|
12390
|
-
[
|
|
12391
|
-
[
|
|
12691
|
+
[GA4_DIMENSIONS.sessionSource, GA4_DIMENSIONS.sessionMedium, "session"],
|
|
12692
|
+
[GA4_DIMENSIONS.firstUserSource, GA4_DIMENSIONS.firstUserMedium, "first_user"],
|
|
12693
|
+
[GA4_DIMENSIONS.sessionManualSource, GA4_DIMENSIONS.sessionManualMedium, "manual_utm"]
|
|
12392
12694
|
];
|
|
12393
12695
|
for (const [sourceDim, mediumDim, dimLabel] of dimensionPairs) {
|
|
12394
12696
|
let offset = 0;
|
|
@@ -12398,15 +12700,15 @@ async function fetchAiReferrals(accessToken, propertyId, days) {
|
|
|
12398
12700
|
const request = {
|
|
12399
12701
|
dateRanges: [{ startDate: formatDate2(startDate), endDate: formatDate2(endDate) }],
|
|
12400
12702
|
dimensions: [
|
|
12401
|
-
{ name:
|
|
12703
|
+
{ name: GA4_DIMENSIONS.date },
|
|
12402
12704
|
{ name: sourceDim },
|
|
12403
12705
|
{ name: mediumDim },
|
|
12404
|
-
{ name:
|
|
12405
|
-
{ name:
|
|
12706
|
+
{ name: GA4_DIMENSIONS.sessionDefaultChannelGrouping },
|
|
12707
|
+
{ name: GA4_DIMENSIONS.landingPagePlusQueryString }
|
|
12406
12708
|
],
|
|
12407
12709
|
metrics: [
|
|
12408
|
-
{ name:
|
|
12409
|
-
{ name:
|
|
12710
|
+
{ name: GA4_METRICS.sessions },
|
|
12711
|
+
{ name: GA4_METRICS.totalUsers }
|
|
12410
12712
|
],
|
|
12411
12713
|
dimensionFilter: {
|
|
12412
12714
|
orGroup: {
|
|
@@ -12479,20 +12781,20 @@ async function fetchSocialReferrals(accessToken, propertyId, days) {
|
|
|
12479
12781
|
const request = {
|
|
12480
12782
|
dateRanges: [{ startDate: formatDate2(startDate), endDate: formatDate2(endDate) }],
|
|
12481
12783
|
dimensions: [
|
|
12482
|
-
{ name:
|
|
12483
|
-
{ name:
|
|
12484
|
-
{ name:
|
|
12485
|
-
{ name:
|
|
12784
|
+
{ name: GA4_DIMENSIONS.date },
|
|
12785
|
+
{ name: GA4_DIMENSIONS.sessionSource },
|
|
12786
|
+
{ name: GA4_DIMENSIONS.sessionMedium },
|
|
12787
|
+
{ name: GA4_DIMENSIONS.sessionDefaultChannelGroup }
|
|
12486
12788
|
],
|
|
12487
12789
|
metrics: [
|
|
12488
|
-
{ name:
|
|
12489
|
-
{ name:
|
|
12790
|
+
{ name: GA4_METRICS.sessions },
|
|
12791
|
+
{ name: GA4_METRICS.totalUsers }
|
|
12490
12792
|
],
|
|
12491
12793
|
dimensionFilter: {
|
|
12492
12794
|
orGroup: {
|
|
12493
12795
|
expressions: SOCIAL_CHANNEL_GROUPS.map((value) => ({
|
|
12494
12796
|
filter: {
|
|
12495
|
-
fieldName:
|
|
12797
|
+
fieldName: GA4_DIMENSIONS.sessionDefaultChannelGroup,
|
|
12496
12798
|
stringFilter: { matchType: "EXACT", value }
|
|
12497
12799
|
}
|
|
12498
12800
|
}))
|
|
@@ -12662,7 +12964,8 @@ async function googleRoutes(app, opts) {
|
|
|
12662
12964
|
<li>Under "Authorized redirect URIs", add:<br><code style="background:#1e1e1e;color:#e0e0e0;padding:4px 8px;border-radius:4px;display:inline-block;margin-top:4px">${request.query.state ? (() => {
|
|
12663
12965
|
try {
|
|
12664
12966
|
const s = verifySignedState(request.query.state, stateSecret);
|
|
12665
|
-
|
|
12967
|
+
const uri = s?.redirectUri;
|
|
12968
|
+
return escapeHtml2(typeof uri === "string" ? uri : "Could not determine URI");
|
|
12666
12969
|
} catch {
|
|
12667
12970
|
return "Could not determine URI";
|
|
12668
12971
|
}
|
|
@@ -12799,7 +13102,7 @@ async function googleRoutes(app, opts) {
|
|
|
12799
13102
|
if (page) conditions.push(sql7`${gscSearchData.page} LIKE ${"%" + page + "%"}`);
|
|
12800
13103
|
const limitVal = Math.max(parseInt(limit ?? "500", 10) || 0, 1);
|
|
12801
13104
|
const offsetVal = Math.max(parseInt(offset ?? "0", 10) || 0, 0);
|
|
12802
|
-
const rows = app.db.select().from(gscSearchData).where(
|
|
13105
|
+
const rows = app.db.select().from(gscSearchData).where(and12(...conditions)).orderBy(desc8(gscSearchData.date)).limit(limitVal).offset(offsetVal).all();
|
|
12803
13106
|
return rows.map((r) => ({
|
|
12804
13107
|
date: r.date,
|
|
12805
13108
|
query: r.query,
|
|
@@ -12824,7 +13127,7 @@ async function googleRoutes(app, opts) {
|
|
|
12824
13127
|
date: gscSearchData.date,
|
|
12825
13128
|
clicks: sql7`COALESCE(SUM(${gscSearchData.clicks}), 0)`,
|
|
12826
13129
|
impressions: sql7`COALESCE(SUM(${gscSearchData.impressions}), 0)`
|
|
12827
|
-
}).from(gscSearchData).where(
|
|
13130
|
+
}).from(gscSearchData).where(and12(...conditions)).groupBy(gscSearchData.date).orderBy(gscSearchData.date).all();
|
|
12828
13131
|
const daily = rows.map((r) => ({
|
|
12829
13132
|
date: r.date,
|
|
12830
13133
|
clicks: r.clicks,
|
|
@@ -12904,7 +13207,7 @@ async function googleRoutes(app, opts) {
|
|
|
12904
13207
|
const { url, limit } = request.query;
|
|
12905
13208
|
const conditions = [eq18(gscUrlInspections.projectId, project.id)];
|
|
12906
13209
|
if (url) conditions.push(eq18(gscUrlInspections.url, url));
|
|
12907
|
-
const rows = app.db.select().from(gscUrlInspections).where(
|
|
13210
|
+
const rows = app.db.select().from(gscUrlInspections).where(and12(...conditions)).orderBy(desc8(gscUrlInspections.inspectedAt)).limit(parseInt(limit ?? "100", 10)).all();
|
|
12908
13211
|
return rows.map((r) => ({
|
|
12909
13212
|
id: r.id,
|
|
12910
13213
|
url: r.url,
|
|
@@ -13256,7 +13559,7 @@ async function googleRoutes(app, opts) {
|
|
|
13256
13559
|
|
|
13257
13560
|
// ../api-routes/src/bing.ts
|
|
13258
13561
|
import crypto15 from "crypto";
|
|
13259
|
-
import { eq as eq19, and as
|
|
13562
|
+
import { eq as eq19, and as and13, desc as desc9 } from "drizzle-orm";
|
|
13260
13563
|
|
|
13261
13564
|
// ../integration-bing/src/constants.ts
|
|
13262
13565
|
var BING_WMT_API_BASE = "https://ssl.bing.com/webmaster/api.svc/json";
|
|
@@ -13670,7 +13973,7 @@ async function bingRoutes(app, opts) {
|
|
|
13670
13973
|
requireConnectionStore();
|
|
13671
13974
|
const project = resolveProject(app.db, request.params.name);
|
|
13672
13975
|
const { url, limit } = request.query;
|
|
13673
|
-
const whereClause = url ?
|
|
13976
|
+
const whereClause = url ? and13(eq19(bingUrlInspections.projectId, project.id), eq19(bingUrlInspections.url, url)) : eq19(bingUrlInspections.projectId, project.id);
|
|
13674
13977
|
const filtered = app.db.select().from(bingUrlInspections).where(whereClause).orderBy(desc9(bingUrlInspections.inspectedAt)).limit(Math.max(1, Math.min(parseInt(limit ?? "100", 10) || 100, 1e3))).all();
|
|
13675
13978
|
return filtered.map((r) => ({
|
|
13676
13979
|
id: r.id,
|
|
@@ -13902,7 +14205,7 @@ async function bingRoutes(app, opts) {
|
|
|
13902
14205
|
import fs from "fs";
|
|
13903
14206
|
import path from "path";
|
|
13904
14207
|
import os2 from "os";
|
|
13905
|
-
import { eq as eq20, and as
|
|
14208
|
+
import { eq as eq20, and as and14 } from "drizzle-orm";
|
|
13906
14209
|
function getScreenshotDir() {
|
|
13907
14210
|
return path.join(os2.homedir(), ".canonry", "screenshots");
|
|
13908
14211
|
}
|
|
@@ -13975,7 +14278,7 @@ async function cdpRoutes(app, opts) {
|
|
|
13975
14278
|
async (request, reply) => {
|
|
13976
14279
|
const project = resolveProject(app.db, request.params.name);
|
|
13977
14280
|
const { runId } = request.params;
|
|
13978
|
-
const run = app.db.select().from(runs).where(
|
|
14281
|
+
const run = app.db.select().from(runs).where(and14(eq20(runs.id, runId), eq20(runs.projectId, project.id))).get();
|
|
13979
14282
|
if (!run) {
|
|
13980
14283
|
const err = notFound("Run", runId);
|
|
13981
14284
|
return reply.code(err.statusCode).send(err.toJSON());
|
|
@@ -14072,7 +14375,7 @@ async function cdpRoutes(app, opts) {
|
|
|
14072
14375
|
|
|
14073
14376
|
// ../api-routes/src/ga.ts
|
|
14074
14377
|
import crypto16 from "crypto";
|
|
14075
|
-
import { eq as eq21, desc as desc10, and as
|
|
14378
|
+
import { eq as eq21, desc as desc10, and as and15, sql as sql8 } from "drizzle-orm";
|
|
14076
14379
|
function gaLog(level, action, ctx) {
|
|
14077
14380
|
const entry = { ts: (/* @__PURE__ */ new Date()).toISOString(), level, module: "GA4Routes", action, ...ctx };
|
|
14078
14381
|
const stream = level === "error" ? process.stderr : process.stdout;
|
|
@@ -14367,7 +14670,7 @@ async function ga4Routes(app, opts) {
|
|
|
14367
14670
|
app.db.transaction((tx) => {
|
|
14368
14671
|
if (syncTraffic) {
|
|
14369
14672
|
tx.delete(gaTrafficSnapshots).where(
|
|
14370
|
-
|
|
14673
|
+
and15(
|
|
14371
14674
|
eq21(gaTrafficSnapshots.projectId, project.id),
|
|
14372
14675
|
sql8`${gaTrafficSnapshots.date} >= ${summary.periodStart}`,
|
|
14373
14676
|
sql8`${gaTrafficSnapshots.date} <= ${summary.periodEnd}`
|
|
@@ -14391,7 +14694,7 @@ async function ga4Routes(app, opts) {
|
|
|
14391
14694
|
}
|
|
14392
14695
|
if (syncAi) {
|
|
14393
14696
|
tx.delete(gaAiReferrals).where(
|
|
14394
|
-
|
|
14697
|
+
and15(
|
|
14395
14698
|
eq21(gaAiReferrals.projectId, project.id),
|
|
14396
14699
|
sql8`${gaAiReferrals.date} >= ${summary.periodStart}`,
|
|
14397
14700
|
sql8`${gaAiReferrals.date} <= ${summary.periodEnd}`
|
|
@@ -14417,7 +14720,7 @@ async function ga4Routes(app, opts) {
|
|
|
14417
14720
|
}
|
|
14418
14721
|
if (syncSocial) {
|
|
14419
14722
|
tx.delete(gaSocialReferrals).where(
|
|
14420
|
-
|
|
14723
|
+
and15(
|
|
14421
14724
|
eq21(gaSocialReferrals.projectId, project.id),
|
|
14422
14725
|
sql8`${gaSocialReferrals.date} >= ${summary.periodStart}`,
|
|
14423
14726
|
sql8`${gaSocialReferrals.date} <= ${summary.periodEnd}`
|
|
@@ -14521,7 +14824,7 @@ async function ga4Routes(app, opts) {
|
|
|
14521
14824
|
totalDirectSessions: gaTrafficWindowSummaries.totalDirectSessions,
|
|
14522
14825
|
totalUsers: gaTrafficWindowSummaries.totalUsers
|
|
14523
14826
|
}).from(gaTrafficWindowSummaries).where(
|
|
14524
|
-
|
|
14827
|
+
and15(
|
|
14525
14828
|
eq21(gaTrafficWindowSummaries.projectId, project.id),
|
|
14526
14829
|
eq21(gaTrafficWindowSummaries.windowKey, window)
|
|
14527
14830
|
)
|
|
@@ -14530,7 +14833,7 @@ async function ga4Routes(app, opts) {
|
|
|
14530
14833
|
totalSessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.sessions}), 0)`,
|
|
14531
14834
|
totalOrganicSessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.organicSessions}), 0)`,
|
|
14532
14835
|
totalUsers: sql8`COALESCE(SUM(${gaTrafficSnapshots.users}), 0)`
|
|
14533
|
-
}).from(gaTrafficSnapshots).where(
|
|
14836
|
+
}).from(gaTrafficSnapshots).where(and15(...snapshotConditions)).get() : null;
|
|
14534
14837
|
const summaryRow = cutoffDate ? windowSummaryRow ?? snapshotTotalsRow : app.db.select({
|
|
14535
14838
|
totalSessions: gaTrafficSummaries.totalSessions,
|
|
14536
14839
|
totalOrganicSessions: gaTrafficSummaries.totalOrganicSessions,
|
|
@@ -14538,7 +14841,7 @@ async function ga4Routes(app, opts) {
|
|
|
14538
14841
|
}).from(gaTrafficSummaries).where(eq21(gaTrafficSummaries.projectId, project.id)).get();
|
|
14539
14842
|
const directTotalRow = windowSummaryRow ? { totalDirectSessions: windowSummaryRow.totalDirectSessions } : app.db.select({
|
|
14540
14843
|
totalDirectSessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)`
|
|
14541
|
-
}).from(gaTrafficSnapshots).where(
|
|
14844
|
+
}).from(gaTrafficSnapshots).where(and15(...snapshotConditions)).get();
|
|
14542
14845
|
const summaryMeta = app.db.select({
|
|
14543
14846
|
periodStart: gaTrafficSummaries.periodStart,
|
|
14544
14847
|
periodEnd: gaTrafficSummaries.periodEnd
|
|
@@ -14549,14 +14852,14 @@ async function ga4Routes(app, opts) {
|
|
|
14549
14852
|
organicSessions: sql8`SUM(${gaTrafficSnapshots.organicSessions})`,
|
|
14550
14853
|
directSessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)`,
|
|
14551
14854
|
users: sql8`SUM(${gaTrafficSnapshots.users})`
|
|
14552
|
-
}).from(gaTrafficSnapshots).where(
|
|
14855
|
+
}).from(gaTrafficSnapshots).where(and15(...snapshotConditions)).groupBy(sql8`COALESCE(${gaTrafficSnapshots.landingPageNormalized}, ${gaTrafficSnapshots.landingPage})`).orderBy(sql8`SUM(${gaTrafficSnapshots.sessions}) DESC`).limit(limit).all();
|
|
14553
14856
|
const aiReferralRows = app.db.select({
|
|
14554
14857
|
source: gaAiReferrals.source,
|
|
14555
14858
|
medium: gaAiReferrals.medium,
|
|
14556
14859
|
sourceDimension: gaAiReferrals.sourceDimension,
|
|
14557
14860
|
sessions: sql8`SUM(${gaAiReferrals.sessions})`,
|
|
14558
14861
|
users: sql8`SUM(${gaAiReferrals.users})`
|
|
14559
|
-
}).from(gaAiReferrals).where(
|
|
14862
|
+
}).from(gaAiReferrals).where(and15(...aiConditions)).groupBy(gaAiReferrals.source, gaAiReferrals.medium, gaAiReferrals.sourceDimension).all();
|
|
14560
14863
|
const aiReferralLandingPageRows = app.db.select({
|
|
14561
14864
|
source: gaAiReferrals.source,
|
|
14562
14865
|
medium: gaAiReferrals.medium,
|
|
@@ -14564,7 +14867,7 @@ async function ga4Routes(app, opts) {
|
|
|
14564
14867
|
landingPage: sql8`COALESCE(${gaAiReferrals.landingPageNormalized}, ${gaAiReferrals.landingPage})`,
|
|
14565
14868
|
sessions: sql8`SUM(${gaAiReferrals.sessions})`,
|
|
14566
14869
|
users: sql8`SUM(${gaAiReferrals.users})`
|
|
14567
|
-
}).from(gaAiReferrals).where(
|
|
14870
|
+
}).from(gaAiReferrals).where(and15(...aiConditions)).groupBy(
|
|
14568
14871
|
gaAiReferrals.source,
|
|
14569
14872
|
gaAiReferrals.medium,
|
|
14570
14873
|
gaAiReferrals.sourceDimension,
|
|
@@ -14601,7 +14904,7 @@ async function ga4Routes(app, opts) {
|
|
|
14601
14904
|
channelGroup: gaAiReferrals.channelGroup,
|
|
14602
14905
|
sessions: sql8`COALESCE(SUM(${gaAiReferrals.sessions}), 0)`,
|
|
14603
14906
|
users: sql8`COALESCE(SUM(${gaAiReferrals.users}), 0)`
|
|
14604
|
-
}).from(gaAiReferrals).where(
|
|
14907
|
+
}).from(gaAiReferrals).where(and15(...aiConditions, eq21(gaAiReferrals.sourceDimension, "session"))).groupBy(gaAiReferrals.channelGroup).all();
|
|
14605
14908
|
const aiSessionsByChannelGroup = /* @__PURE__ */ new Map();
|
|
14606
14909
|
let aiBySessionUsers = 0;
|
|
14607
14910
|
for (const row of aiBySessionRows) {
|
|
@@ -14615,11 +14918,11 @@ async function ga4Routes(app, opts) {
|
|
|
14615
14918
|
channelGroup: gaSocialReferrals.channelGroup,
|
|
14616
14919
|
sessions: sql8`SUM(${gaSocialReferrals.sessions})`,
|
|
14617
14920
|
users: sql8`SUM(${gaSocialReferrals.users})`
|
|
14618
|
-
}).from(gaSocialReferrals).where(
|
|
14921
|
+
}).from(gaSocialReferrals).where(and15(...socialConditions)).groupBy(gaSocialReferrals.source, gaSocialReferrals.medium, gaSocialReferrals.channelGroup).orderBy(sql8`SUM(${gaSocialReferrals.sessions}) DESC`).all();
|
|
14619
14922
|
const socialTotals = app.db.select({
|
|
14620
14923
|
sessions: sql8`SUM(${gaSocialReferrals.sessions})`,
|
|
14621
14924
|
users: sql8`SUM(${gaSocialReferrals.users})`
|
|
14622
|
-
}).from(gaSocialReferrals).where(
|
|
14925
|
+
}).from(gaSocialReferrals).where(and15(...socialConditions)).get();
|
|
14623
14926
|
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq21(gaTrafficSummaries.projectId, project.id)).orderBy(desc10(gaTrafficSummaries.syncedAt)).limit(1).get();
|
|
14624
14927
|
const total = summaryRow?.totalSessions ?? 0;
|
|
14625
14928
|
const totalDirectSessions = directTotalRow?.totalDirectSessions ?? 0;
|
|
@@ -14710,7 +15013,7 @@ async function ga4Routes(app, opts) {
|
|
|
14710
15013
|
sourceDimension: gaAiReferrals.sourceDimension,
|
|
14711
15014
|
sessions: sql8`SUM(${gaAiReferrals.sessions})`,
|
|
14712
15015
|
users: sql8`SUM(${gaAiReferrals.users})`
|
|
14713
|
-
}).from(gaAiReferrals).where(
|
|
15016
|
+
}).from(gaAiReferrals).where(and15(...conditions)).groupBy(
|
|
14714
15017
|
gaAiReferrals.date,
|
|
14715
15018
|
gaAiReferrals.source,
|
|
14716
15019
|
gaAiReferrals.medium,
|
|
@@ -14732,7 +15035,7 @@ async function ga4Routes(app, opts) {
|
|
|
14732
15035
|
channelGroup: gaSocialReferrals.channelGroup,
|
|
14733
15036
|
sessions: gaSocialReferrals.sessions,
|
|
14734
15037
|
users: gaSocialReferrals.users
|
|
14735
|
-
}).from(gaSocialReferrals).where(
|
|
15038
|
+
}).from(gaSocialReferrals).where(and15(...conditions)).orderBy(gaSocialReferrals.date).all();
|
|
14736
15039
|
return rows;
|
|
14737
15040
|
});
|
|
14738
15041
|
app.get("/projects/:name/ga/social-referral-trend", async (request, _reply) => {
|
|
@@ -14745,7 +15048,7 @@ async function ga4Routes(app, opts) {
|
|
|
14745
15048
|
d.setDate(d.getDate() - n);
|
|
14746
15049
|
return fmt(d);
|
|
14747
15050
|
};
|
|
14748
|
-
const sumSocial = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaSocialReferrals.sessions}), 0)` }).from(gaSocialReferrals).where(
|
|
15051
|
+
const sumSocial = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaSocialReferrals.sessions}), 0)` }).from(gaSocialReferrals).where(and15(
|
|
14749
15052
|
eq21(gaSocialReferrals.projectId, project.id),
|
|
14750
15053
|
sql8`${gaSocialReferrals.date} >= ${from}`,
|
|
14751
15054
|
sql8`${gaSocialReferrals.date} < ${to}`
|
|
@@ -14758,7 +15061,7 @@ async function ga4Routes(app, opts) {
|
|
|
14758
15061
|
const sourceCurrent = app.db.select({
|
|
14759
15062
|
source: gaSocialReferrals.source,
|
|
14760
15063
|
sessions: sql8`SUM(${gaSocialReferrals.sessions})`
|
|
14761
|
-
}).from(gaSocialReferrals).where(
|
|
15064
|
+
}).from(gaSocialReferrals).where(and15(
|
|
14762
15065
|
eq21(gaSocialReferrals.projectId, project.id),
|
|
14763
15066
|
sql8`${gaSocialReferrals.date} >= ${daysAgo2(7)}`,
|
|
14764
15067
|
sql8`${gaSocialReferrals.date} < ${fmt(today)}`
|
|
@@ -14766,7 +15069,7 @@ async function ga4Routes(app, opts) {
|
|
|
14766
15069
|
const sourcePrev = app.db.select({
|
|
14767
15070
|
source: gaSocialReferrals.source,
|
|
14768
15071
|
sessions: sql8`SUM(${gaSocialReferrals.sessions})`
|
|
14769
|
-
}).from(gaSocialReferrals).where(
|
|
15072
|
+
}).from(gaSocialReferrals).where(and15(
|
|
14770
15073
|
eq21(gaSocialReferrals.projectId, project.id),
|
|
14771
15074
|
sql8`${gaSocialReferrals.date} >= ${daysAgo2(14)}`,
|
|
14772
15075
|
sql8`${gaSocialReferrals.date} < ${daysAgo2(7)}`
|
|
@@ -14808,16 +15111,16 @@ async function ga4Routes(app, opts) {
|
|
|
14808
15111
|
return fmt(d);
|
|
14809
15112
|
};
|
|
14810
15113
|
const pct = (cur, prev) => prev === 0 ? null : Math.round((cur - prev) / prev * 100);
|
|
14811
|
-
const sumTotal = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.sessions}), 0)` }).from(gaTrafficSnapshots).where(
|
|
14812
|
-
const sumOrganic = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.organicSessions}), 0)` }).from(gaTrafficSnapshots).where(
|
|
14813
|
-
const sumDirect = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)` }).from(gaTrafficSnapshots).where(
|
|
14814
|
-
const sumAi = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(
|
|
15114
|
+
const sumTotal = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.sessions}), 0)` }).from(gaTrafficSnapshots).where(and15(eq21(gaTrafficSnapshots.projectId, project.id), sql8`${gaTrafficSnapshots.date} >= ${from}`, sql8`${gaTrafficSnapshots.date} < ${to}`)).get();
|
|
15115
|
+
const sumOrganic = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.organicSessions}), 0)` }).from(gaTrafficSnapshots).where(and15(eq21(gaTrafficSnapshots.projectId, project.id), sql8`${gaTrafficSnapshots.date} >= ${from}`, sql8`${gaTrafficSnapshots.date} < ${to}`)).get();
|
|
15116
|
+
const sumDirect = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)` }).from(gaTrafficSnapshots).where(and15(eq21(gaTrafficSnapshots.projectId, project.id), sql8`${gaTrafficSnapshots.date} >= ${from}`, sql8`${gaTrafficSnapshots.date} < ${to}`)).get();
|
|
15117
|
+
const sumAi = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and15(
|
|
14815
15118
|
eq21(gaAiReferrals.projectId, project.id),
|
|
14816
15119
|
sql8`${gaAiReferrals.date} >= ${from}`,
|
|
14817
15120
|
sql8`${gaAiReferrals.date} < ${to}`,
|
|
14818
15121
|
eq21(gaAiReferrals.sourceDimension, "session")
|
|
14819
15122
|
)).get();
|
|
14820
|
-
const sumSocial = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaSocialReferrals.sessions}), 0)` }).from(gaSocialReferrals).where(
|
|
15123
|
+
const sumSocial = (from, to) => app.db.select({ sessions: sql8`COALESCE(SUM(${gaSocialReferrals.sessions}), 0)` }).from(gaSocialReferrals).where(and15(eq21(gaSocialReferrals.projectId, project.id), sql8`${gaSocialReferrals.date} >= ${from}`, sql8`${gaSocialReferrals.date} < ${to}`)).get();
|
|
14821
15124
|
const todayStr = fmt(today);
|
|
14822
15125
|
const buildTrend = (sum) => {
|
|
14823
15126
|
const c7 = sum(daysAgo2(7), todayStr)?.sessions ?? 0;
|
|
@@ -14826,13 +15129,13 @@ async function ga4Routes(app, opts) {
|
|
|
14826
15129
|
const p30 = sum(daysAgo2(60), daysAgo2(30))?.sessions ?? 0;
|
|
14827
15130
|
return { sessions7d: c7, sessionsPrev7d: p7, trend7dPct: pct(c7, p7), sessions30d: c30, sessionsPrev30d: p30, trend30dPct: pct(c30, p30) };
|
|
14828
15131
|
};
|
|
14829
|
-
const aiSourceCurrent = app.db.select({ source: gaAiReferrals.source, sessions: sql8`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(
|
|
15132
|
+
const aiSourceCurrent = app.db.select({ source: gaAiReferrals.source, sessions: sql8`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and15(
|
|
14830
15133
|
eq21(gaAiReferrals.projectId, project.id),
|
|
14831
15134
|
sql8`${gaAiReferrals.date} >= ${daysAgo2(7)}`,
|
|
14832
15135
|
sql8`${gaAiReferrals.date} < ${todayStr}`,
|
|
14833
15136
|
eq21(gaAiReferrals.sourceDimension, "session")
|
|
14834
15137
|
)).groupBy(gaAiReferrals.source).all();
|
|
14835
|
-
const aiSourcePrev = app.db.select({ source: gaAiReferrals.source, sessions: sql8`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(
|
|
15138
|
+
const aiSourcePrev = app.db.select({ source: gaAiReferrals.source, sessions: sql8`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and15(
|
|
14836
15139
|
eq21(gaAiReferrals.projectId, project.id),
|
|
14837
15140
|
sql8`${gaAiReferrals.date} >= ${daysAgo2(14)}`,
|
|
14838
15141
|
sql8`${gaAiReferrals.date} < ${daysAgo2(7)}`,
|
|
@@ -14852,8 +15155,8 @@ async function ga4Routes(app, opts) {
|
|
|
14852
15155
|
}
|
|
14853
15156
|
return mover;
|
|
14854
15157
|
};
|
|
14855
|
-
const socialSourceCurrent = app.db.select({ source: gaSocialReferrals.source, sessions: sql8`SUM(${gaSocialReferrals.sessions})` }).from(gaSocialReferrals).where(
|
|
14856
|
-
const socialSourcePrev = app.db.select({ source: gaSocialReferrals.source, sessions: sql8`SUM(${gaSocialReferrals.sessions})` }).from(gaSocialReferrals).where(
|
|
15158
|
+
const socialSourceCurrent = app.db.select({ source: gaSocialReferrals.source, sessions: sql8`SUM(${gaSocialReferrals.sessions})` }).from(gaSocialReferrals).where(and15(eq21(gaSocialReferrals.projectId, project.id), sql8`${gaSocialReferrals.date} >= ${daysAgo2(7)}`, sql8`${gaSocialReferrals.date} < ${todayStr}`)).groupBy(gaSocialReferrals.source).all();
|
|
15159
|
+
const socialSourcePrev = app.db.select({ source: gaSocialReferrals.source, sessions: sql8`SUM(${gaSocialReferrals.sessions})` }).from(gaSocialReferrals).where(and15(eq21(gaSocialReferrals.projectId, project.id), sql8`${gaSocialReferrals.date} >= ${daysAgo2(14)}`, sql8`${gaSocialReferrals.date} < ${daysAgo2(7)}`)).groupBy(gaSocialReferrals.source).all();
|
|
14857
15160
|
return {
|
|
14858
15161
|
total: buildTrend(sumTotal),
|
|
14859
15162
|
organic: buildTrend(sumOrganic),
|
|
@@ -14875,7 +15178,7 @@ async function ga4Routes(app, opts) {
|
|
|
14875
15178
|
sessions: sql8`SUM(${gaTrafficSnapshots.sessions})`,
|
|
14876
15179
|
organicSessions: sql8`SUM(${gaTrafficSnapshots.organicSessions})`,
|
|
14877
15180
|
users: sql8`SUM(${gaTrafficSnapshots.users})`
|
|
14878
|
-
}).from(gaTrafficSnapshots).where(
|
|
15181
|
+
}).from(gaTrafficSnapshots).where(and15(...conditions)).groupBy(gaTrafficSnapshots.date).orderBy(gaTrafficSnapshots.date).all();
|
|
14879
15182
|
return rows.map((r) => ({
|
|
14880
15183
|
date: r.date,
|
|
14881
15184
|
sessions: r.sessions ?? 0,
|
|
@@ -15669,7 +15972,7 @@ async function deploySchema(connection, slug, schemas, env) {
|
|
|
15669
15972
|
return {
|
|
15670
15973
|
slug,
|
|
15671
15974
|
status: "stripped",
|
|
15672
|
-
schemasInjected: schemas.map((s) =>
|
|
15975
|
+
schemasInjected: schemas.map((s) => typeof s["@type"] === "string" ? s["@type"] : "Unknown"),
|
|
15673
15976
|
manualAssist: {
|
|
15674
15977
|
manualRequired: true,
|
|
15675
15978
|
targetUrl: page.link ?? `${site.siteUrl}/${slug}`,
|
|
@@ -15686,7 +15989,7 @@ async function deploySchema(connection, slug, schemas, env) {
|
|
|
15686
15989
|
return {
|
|
15687
15990
|
slug,
|
|
15688
15991
|
status: "deployed",
|
|
15689
|
-
schemasInjected: schemas.map((s) =>
|
|
15992
|
+
schemasInjected: schemas.map((s) => typeof s["@type"] === "string" ? s["@type"] : "Unknown")
|
|
15690
15993
|
};
|
|
15691
15994
|
} catch (error) {
|
|
15692
15995
|
if (error instanceof WordpressApiError && error.code === "NOT_FOUND") {
|
|
@@ -15746,7 +16049,7 @@ async function getSchemaStatus(connection, env) {
|
|
|
15746
16049
|
while ((jsonMatch = jsonLdRegex.exec(match[1])) !== null) {
|
|
15747
16050
|
try {
|
|
15748
16051
|
const parsed = JSON.parse(jsonMatch[1].trim());
|
|
15749
|
-
canonrySchemas.push(
|
|
16052
|
+
canonrySchemas.push(typeof parsed["@type"] === "string" ? parsed["@type"] : "Unknown");
|
|
15750
16053
|
} catch {
|
|
15751
16054
|
}
|
|
15752
16055
|
}
|
|
@@ -16477,7 +16780,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
16477
16780
|
steps.push({ name: "google-submit", status: "completed", summary: `${succeeded}/${pageUrls.length} URLs submitted` });
|
|
16478
16781
|
} else {
|
|
16479
16782
|
const body = JSON.parse(googleRes.body);
|
|
16480
|
-
const msg = body.message
|
|
16783
|
+
const msg = body.message ?? body.error ?? `HTTP ${googleRes.statusCode}`;
|
|
16481
16784
|
if (googleRes.statusCode === 400 || googleRes.statusCode === 404) {
|
|
16482
16785
|
steps.push({ name: "google-submit", status: "skipped", summary: msg });
|
|
16483
16786
|
} else {
|
|
@@ -16502,7 +16805,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
16502
16805
|
steps.push({ name: "bing-submit", status: "completed", summary: `${succeeded}/${pageUrls.length} URLs submitted` });
|
|
16503
16806
|
} else {
|
|
16504
16807
|
const body = JSON.parse(bingRes.body);
|
|
16505
|
-
const msg = body.message
|
|
16808
|
+
const msg = body.message ?? body.error ?? `HTTP ${bingRes.statusCode}`;
|
|
16506
16809
|
if (bingRes.statusCode === 400 || bingRes.statusCode === 404) {
|
|
16507
16810
|
steps.push({ name: "bing-submit", status: "skipped", summary: msg });
|
|
16508
16811
|
} else {
|
|
@@ -16528,7 +16831,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
16528
16831
|
|
|
16529
16832
|
// ../api-routes/src/backlinks.ts
|
|
16530
16833
|
import crypto18 from "crypto";
|
|
16531
|
-
import { and as
|
|
16834
|
+
import { and as and17, asc as asc2, desc as desc11, eq as eq22, sql as sql9 } from "drizzle-orm";
|
|
16532
16835
|
|
|
16533
16836
|
// ../integration-commoncrawl/src/constants.ts
|
|
16534
16837
|
import os3 from "os";
|
|
@@ -16925,7 +17228,7 @@ function pruneCachedRelease(release, opts = {}) {
|
|
|
16925
17228
|
}
|
|
16926
17229
|
|
|
16927
17230
|
// ../api-routes/src/backlinks-filter.ts
|
|
16928
|
-
import { and as
|
|
17231
|
+
import { and as and16, ne as ne3, notLike } from "drizzle-orm";
|
|
16929
17232
|
var BACKLINK_FILTER_PATTERNS = [
|
|
16930
17233
|
"*.google.com",
|
|
16931
17234
|
"*.googleusercontent.com",
|
|
@@ -16942,13 +17245,13 @@ function backlinkCrawlerExclusionClause() {
|
|
|
16942
17245
|
for (const pattern of BACKLINK_FILTER_PATTERNS) {
|
|
16943
17246
|
if (pattern.startsWith("*.")) {
|
|
16944
17247
|
const suffix = pattern.slice(2);
|
|
16945
|
-
conditions.push(
|
|
17248
|
+
conditions.push(ne3(backlinkDomains.linkingDomain, suffix));
|
|
16946
17249
|
conditions.push(notLike(backlinkDomains.linkingDomain, `%.${suffix}`));
|
|
16947
17250
|
} else {
|
|
16948
|
-
conditions.push(
|
|
17251
|
+
conditions.push(ne3(backlinkDomains.linkingDomain, pattern));
|
|
16949
17252
|
}
|
|
16950
17253
|
}
|
|
16951
|
-
const combined =
|
|
17254
|
+
const combined = and16(...conditions);
|
|
16952
17255
|
if (!combined) throw new Error("BACKLINK_FILTER_PATTERNS is unexpectedly empty");
|
|
16953
17256
|
return combined;
|
|
16954
17257
|
}
|
|
@@ -17009,7 +17312,7 @@ function mapRunRow(row) {
|
|
|
17009
17312
|
};
|
|
17010
17313
|
}
|
|
17011
17314
|
function latestSummaryForProject(db, projectId, release) {
|
|
17012
|
-
const condition = release ?
|
|
17315
|
+
const condition = release ? and17(eq22(backlinkSummaries.projectId, projectId), eq22(backlinkSummaries.release, release)) : eq22(backlinkSummaries.projectId, projectId);
|
|
17013
17316
|
return db.select().from(backlinkSummaries).where(condition).orderBy(desc11(backlinkSummaries.queriedAt)).limit(1).get();
|
|
17014
17317
|
}
|
|
17015
17318
|
function parseExcludeCrawlers(value) {
|
|
@@ -17018,11 +17321,11 @@ function parseExcludeCrawlers(value) {
|
|
|
17018
17321
|
return lower === "1" || lower === "true" || lower === "yes";
|
|
17019
17322
|
}
|
|
17020
17323
|
function computeFilteredSummary(db, base) {
|
|
17021
|
-
const baseDomainCondition =
|
|
17324
|
+
const baseDomainCondition = and17(
|
|
17022
17325
|
eq22(backlinkDomains.projectId, base.projectId),
|
|
17023
17326
|
eq22(backlinkDomains.release, base.release)
|
|
17024
17327
|
);
|
|
17025
|
-
const filteredCondition =
|
|
17328
|
+
const filteredCondition = and17(baseDomainCondition, backlinkCrawlerExclusionClause());
|
|
17026
17329
|
const unfilteredAgg = db.select({
|
|
17027
17330
|
count: sql9`count(*)`,
|
|
17028
17331
|
total: sql9`coalesce(sum(${backlinkDomains.numHosts}), 0)`
|
|
@@ -17198,11 +17501,11 @@ async function backlinksRoutes(app, opts) {
|
|
|
17198
17501
|
const limit = Math.min(Math.max(parseInt(request.query.limit ?? "50", 10) || 50, 1), 500);
|
|
17199
17502
|
const offset = Math.max(parseInt(request.query.offset ?? "0", 10) || 0, 0);
|
|
17200
17503
|
const excludeCrawlers = parseExcludeCrawlers(request.query.excludeCrawlers);
|
|
17201
|
-
const baseDomainCondition =
|
|
17504
|
+
const baseDomainCondition = and17(
|
|
17202
17505
|
eq22(backlinkDomains.projectId, project.id),
|
|
17203
17506
|
eq22(backlinkDomains.release, targetRelease)
|
|
17204
17507
|
);
|
|
17205
|
-
const domainCondition = excludeCrawlers ?
|
|
17508
|
+
const domainCondition = excludeCrawlers ? and17(baseDomainCondition, backlinkCrawlerExclusionClause()) : baseDomainCondition;
|
|
17206
17509
|
const totalRow = app.db.select({ count: sql9`count(*)` }).from(backlinkDomains).where(domainCondition).get();
|
|
17207
17510
|
const rows = app.db.select({
|
|
17208
17511
|
linkingDomain: backlinkDomains.linkingDomain,
|
|
@@ -17238,7 +17541,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
17238
17541
|
|
|
17239
17542
|
// ../api-routes/src/traffic.ts
|
|
17240
17543
|
import crypto20 from "crypto";
|
|
17241
|
-
import { and as
|
|
17544
|
+
import { and as and18, desc as desc12, eq as eq23, gte as gte2, lte as lte2, sql as sql10 } from "drizzle-orm";
|
|
17242
17545
|
|
|
17243
17546
|
// ../integration-cloud-run/src/auth.ts
|
|
17244
17547
|
import crypto19 from "crypto";
|
|
@@ -17521,6 +17824,7 @@ async function listCloudRunTrafficEvents(accessToken, options) {
|
|
|
17521
17824
|
}
|
|
17522
17825
|
|
|
17523
17826
|
// ../integration-traffic/src/rules.ts
|
|
17827
|
+
var LEGACY_CHATGPT_DOMAIN = "chat.openai.com";
|
|
17524
17828
|
var DEFAULT_AI_CRAWLER_RULES = [
|
|
17525
17829
|
{
|
|
17526
17830
|
id: "openai-gptbot",
|
|
@@ -17615,15 +17919,15 @@ var DEFAULT_AI_CRAWLER_RULES = [
|
|
|
17615
17919
|
}
|
|
17616
17920
|
];
|
|
17617
17921
|
var DEFAULT_AI_REFERRER_RULES = [
|
|
17618
|
-
{ domain:
|
|
17619
|
-
{ domain:
|
|
17620
|
-
{ domain:
|
|
17621
|
-
{ domain:
|
|
17622
|
-
{ domain:
|
|
17623
|
-
{ domain:
|
|
17624
|
-
{ domain:
|
|
17625
|
-
{ domain:
|
|
17626
|
-
{ domain:
|
|
17922
|
+
{ domain: AI_ENGINE_DOMAINS.chatgpt, operator: "OpenAI", product: "ChatGPT" },
|
|
17923
|
+
{ domain: LEGACY_CHATGPT_DOMAIN, operator: "OpenAI", product: "ChatGPT" },
|
|
17924
|
+
{ domain: AI_ENGINE_DOMAINS.perplexity, operator: "Perplexity", product: "Perplexity" },
|
|
17925
|
+
{ domain: AI_ENGINE_DOMAINS.claude, operator: "Anthropic", product: "Claude" },
|
|
17926
|
+
{ domain: AI_ENGINE_DOMAINS.gemini, operator: "Google", product: "Gemini" },
|
|
17927
|
+
{ domain: AI_ENGINE_DOMAINS.copilotMicrosoft, operator: "Microsoft", product: "Copilot" },
|
|
17928
|
+
{ domain: AI_ENGINE_DOMAINS.phind, operator: "Phind", product: "Phind" },
|
|
17929
|
+
{ domain: AI_ENGINE_DOMAINS.you, operator: "You.com", product: "You.com" },
|
|
17930
|
+
{ domain: AI_ENGINE_DOMAINS.metaAi, operator: "Meta", product: "Meta AI" }
|
|
17627
17931
|
];
|
|
17628
17932
|
|
|
17629
17933
|
// ../integration-traffic/src/classifier.ts
|
|
@@ -18386,21 +18690,21 @@ async function runBackfillTask(options) {
|
|
|
18386
18690
|
try {
|
|
18387
18691
|
app.db.transaction((tx) => {
|
|
18388
18692
|
tx.delete(crawlerEventsHourly).where(
|
|
18389
|
-
|
|
18693
|
+
and18(
|
|
18390
18694
|
eq23(crawlerEventsHourly.sourceId, sourceRow.id),
|
|
18391
18695
|
gte2(crawlerEventsHourly.tsHour, windowStartIso),
|
|
18392
18696
|
lte2(crawlerEventsHourly.tsHour, windowEndIso)
|
|
18393
18697
|
)
|
|
18394
18698
|
).run();
|
|
18395
18699
|
tx.delete(aiReferralEventsHourly).where(
|
|
18396
|
-
|
|
18700
|
+
and18(
|
|
18397
18701
|
eq23(aiReferralEventsHourly.sourceId, sourceRow.id),
|
|
18398
18702
|
gte2(aiReferralEventsHourly.tsHour, windowStartIso),
|
|
18399
18703
|
lte2(aiReferralEventsHourly.tsHour, windowEndIso)
|
|
18400
18704
|
)
|
|
18401
18705
|
).run();
|
|
18402
18706
|
tx.delete(rawEventSamples).where(
|
|
18403
|
-
|
|
18707
|
+
and18(
|
|
18404
18708
|
eq23(rawEventSamples.sourceId, sourceRow.id),
|
|
18405
18709
|
gte2(rawEventSamples.ts, windowStartIso),
|
|
18406
18710
|
lte2(rawEventSamples.ts, windowEndIso)
|
|
@@ -19264,25 +19568,25 @@ async function trafficRoutes(app, opts) {
|
|
|
19264
19568
|
});
|
|
19265
19569
|
function buildSourceDetail(projectId, row, since) {
|
|
19266
19570
|
const crawlerTotals = app.db.select({ total: sql10`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
|
|
19267
|
-
|
|
19571
|
+
and18(
|
|
19268
19572
|
eq23(crawlerEventsHourly.sourceId, row.id),
|
|
19269
19573
|
gte2(crawlerEventsHourly.tsHour, since)
|
|
19270
19574
|
)
|
|
19271
19575
|
).get();
|
|
19272
19576
|
const aiTotals = app.db.select({ total: sql10`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
|
|
19273
|
-
|
|
19577
|
+
and18(
|
|
19274
19578
|
eq23(aiReferralEventsHourly.sourceId, row.id),
|
|
19275
19579
|
gte2(aiReferralEventsHourly.tsHour, since)
|
|
19276
19580
|
)
|
|
19277
19581
|
).get();
|
|
19278
19582
|
const sampleTotals = app.db.select({ total: sql10`COUNT(*)` }).from(rawEventSamples).where(
|
|
19279
|
-
|
|
19583
|
+
and18(
|
|
19280
19584
|
eq23(rawEventSamples.sourceId, row.id),
|
|
19281
19585
|
gte2(rawEventSamples.ts, since)
|
|
19282
19586
|
)
|
|
19283
19587
|
).get();
|
|
19284
19588
|
const latestRun = app.db.select().from(runs).where(
|
|
19285
|
-
|
|
19589
|
+
and18(
|
|
19286
19590
|
eq23(runs.projectId, projectId),
|
|
19287
19591
|
eq23(runs.kind, RunKinds["traffic-sync"]),
|
|
19288
19592
|
eq23(runs.sourceId, row.id)
|
|
@@ -19376,7 +19680,7 @@ async function trafficRoutes(app, opts) {
|
|
|
19376
19680
|
lte2(crawlerEventsHourly.tsHour, untilIso)
|
|
19377
19681
|
];
|
|
19378
19682
|
if (sourceIdParam) crawlerFilters.push(eq23(crawlerEventsHourly.sourceId, sourceIdParam));
|
|
19379
|
-
const crawlerWhere =
|
|
19683
|
+
const crawlerWhere = and18(...crawlerFilters);
|
|
19380
19684
|
const total = app.db.select({ total: sql10`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(crawlerWhere).get();
|
|
19381
19685
|
crawlerTotal = Number(total?.total ?? 0);
|
|
19382
19686
|
const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(desc12(crawlerEventsHourly.tsHour)).limit(limit).all();
|
|
@@ -19401,7 +19705,7 @@ async function trafficRoutes(app, opts) {
|
|
|
19401
19705
|
lte2(aiReferralEventsHourly.tsHour, untilIso)
|
|
19402
19706
|
];
|
|
19403
19707
|
if (sourceIdParam) aiFilters.push(eq23(aiReferralEventsHourly.sourceId, sourceIdParam));
|
|
19404
|
-
const aiWhere =
|
|
19708
|
+
const aiWhere = and18(...aiFilters);
|
|
19405
19709
|
const total = app.db.select({ total: sql10`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(aiWhere).get();
|
|
19406
19710
|
aiReferralTotal = Number(total?.total ?? 0);
|
|
19407
19711
|
const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(desc12(aiReferralEventsHourly.tsHour)).limit(limit).all();
|
|
@@ -20125,7 +20429,7 @@ var providersConfiguredCheck = {
|
|
|
20125
20429
|
var PROVIDERS_CHECKS = [providersConfiguredCheck];
|
|
20126
20430
|
|
|
20127
20431
|
// ../api-routes/src/doctor/checks/traffic-source.ts
|
|
20128
|
-
import { and as
|
|
20432
|
+
import { and as and19, eq as eq24, gte as gte3, ne as ne4, sql as sql11 } from "drizzle-orm";
|
|
20129
20433
|
var RECENT_DATA_WARN_DAYS = 7;
|
|
20130
20434
|
var RECENT_DATA_FAIL_DAYS = 30;
|
|
20131
20435
|
function skippedNoProject2() {
|
|
@@ -20139,9 +20443,9 @@ function skippedNoProject2() {
|
|
|
20139
20443
|
function loadProbes(ctx) {
|
|
20140
20444
|
if (!ctx.project) return [];
|
|
20141
20445
|
const rows = ctx.db.select().from(trafficSources).where(
|
|
20142
|
-
|
|
20446
|
+
and19(
|
|
20143
20447
|
eq24(trafficSources.projectId, ctx.project.id),
|
|
20144
|
-
|
|
20448
|
+
ne4(trafficSources.status, TrafficSourceStatuses.archived)
|
|
20145
20449
|
)
|
|
20146
20450
|
).all();
|
|
20147
20451
|
return rows.map((r) => ({
|
|
@@ -20220,7 +20524,7 @@ var recentDataCheck = {
|
|
|
20220
20524
|
const failCutoff = new Date(now.getTime() - RECENT_DATA_FAIL_DAYS * 24 * 60 * 6e4).toISOString();
|
|
20221
20525
|
const recentCrawlers = Number(
|
|
20222
20526
|
ctx.db.select({ total: sql11`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
|
|
20223
|
-
|
|
20527
|
+
and19(
|
|
20224
20528
|
eq24(crawlerEventsHourly.projectId, ctx.project.id),
|
|
20225
20529
|
gte3(crawlerEventsHourly.tsHour, warnCutoff)
|
|
20226
20530
|
)
|
|
@@ -20228,7 +20532,7 @@ var recentDataCheck = {
|
|
|
20228
20532
|
);
|
|
20229
20533
|
const recentReferrals = Number(
|
|
20230
20534
|
ctx.db.select({ total: sql11`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
|
|
20231
|
-
|
|
20535
|
+
and19(
|
|
20232
20536
|
eq24(aiReferralEventsHourly.projectId, ctx.project.id),
|
|
20233
20537
|
gte3(aiReferralEventsHourly.tsHour, warnCutoff)
|
|
20234
20538
|
)
|
|
@@ -20244,7 +20548,7 @@ var recentDataCheck = {
|
|
|
20244
20548
|
}
|
|
20245
20549
|
const olderCrawlers = Number(
|
|
20246
20550
|
ctx.db.select({ total: sql11`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
|
|
20247
|
-
|
|
20551
|
+
and19(
|
|
20248
20552
|
eq24(crawlerEventsHourly.projectId, ctx.project.id),
|
|
20249
20553
|
gte3(crawlerEventsHourly.tsHour, failCutoff)
|
|
20250
20554
|
)
|
|
@@ -20252,7 +20556,7 @@ var recentDataCheck = {
|
|
|
20252
20556
|
);
|
|
20253
20557
|
const olderReferrals = Number(
|
|
20254
20558
|
ctx.db.select({ total: sql11`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
|
|
20255
|
-
|
|
20559
|
+
and19(
|
|
20256
20560
|
eq24(aiReferralEventsHourly.projectId, ctx.project.id),
|
|
20257
20561
|
gte3(aiReferralEventsHourly.tsHour, failCutoff)
|
|
20258
20562
|
)
|
|
@@ -20436,9 +20740,6 @@ var ALL_CHECKS = [
|
|
|
20436
20740
|
...TRAFFIC_SOURCE_CHECKS,
|
|
20437
20741
|
...AGENT_CHECKS
|
|
20438
20742
|
];
|
|
20439
|
-
var CHECK_BY_ID = Object.fromEntries(
|
|
20440
|
-
ALL_CHECKS.map((check) => [check.id, check])
|
|
20441
|
-
);
|
|
20442
20743
|
|
|
20443
20744
|
// ../api-routes/src/doctor/runner.ts
|
|
20444
20745
|
function matchesCheckId(checkId, filters) {
|
|
@@ -20551,7 +20852,7 @@ async function doctorRoutes(app, opts) {
|
|
|
20551
20852
|
|
|
20552
20853
|
// ../api-routes/src/discovery/routes.ts
|
|
20553
20854
|
import crypto21 from "crypto";
|
|
20554
|
-
import { and as
|
|
20855
|
+
import { and as and20, desc as desc13, eq as eq25, gte as gte4, inArray as inArray9 } from "drizzle-orm";
|
|
20555
20856
|
var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
|
|
20556
20857
|
async function discoveryRoutes(app, opts) {
|
|
20557
20858
|
app.post("/projects/:name/discover/run", async (request, reply) => {
|
|
@@ -20583,7 +20884,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
20583
20884
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20584
20885
|
const ageFloorIso = new Date(Date.now() - MAX_INFLIGHT_DISCOVERY_AGE_MS).toISOString();
|
|
20585
20886
|
const decision = app.db.transaction((tx) => {
|
|
20586
|
-
const existing = tx.select({ id: discoverySessions.id, runId: discoverySessions.runId }).from(discoverySessions).where(
|
|
20887
|
+
const existing = tx.select({ id: discoverySessions.id, runId: discoverySessions.runId }).from(discoverySessions).where(and20(
|
|
20587
20888
|
eq25(discoverySessions.projectId, project.id),
|
|
20588
20889
|
eq25(discoverySessions.icpDescription, icpDescription),
|
|
20589
20890
|
inArray9(discoverySessions.status, [
|
|
@@ -21560,10 +21861,10 @@ function extractDomainFromUri(uri) {
|
|
|
21560
21861
|
try {
|
|
21561
21862
|
const url = new URL(uri);
|
|
21562
21863
|
const hostname = url.hostname.replace(/^www\./, "").toLowerCase();
|
|
21563
|
-
if (
|
|
21864
|
+
if (AI_ENGINE_SELF_DOMAINS.chatgpt.some((self) => hostname.includes(self))) {
|
|
21564
21865
|
return null;
|
|
21565
21866
|
}
|
|
21566
|
-
if (hostname ===
|
|
21867
|
+
if (hostname === VERTEX_AI_SEARCH_PROXY_DOMAIN) {
|
|
21567
21868
|
const redirectPath = url.pathname.replace(/^\/grounding-api-redirect\//, "");
|
|
21568
21869
|
if (redirectPath && redirectPath !== url.pathname) {
|
|
21569
21870
|
try {
|
|
@@ -21831,7 +22132,7 @@ async function healthcheck2(config) {
|
|
|
21831
22132
|
async function executeTrackedQuery2(input) {
|
|
21832
22133
|
const model = input.config.model ?? DEFAULT_MODEL2;
|
|
21833
22134
|
const client = new OpenAI({ apiKey: input.config.apiKey });
|
|
21834
|
-
const webSearchTool = { type: "
|
|
22135
|
+
const webSearchTool = { type: "web_search" };
|
|
21835
22136
|
if (input.location) {
|
|
21836
22137
|
webSearchTool.user_location = {
|
|
21837
22138
|
type: "approximate",
|
|
@@ -21993,7 +22294,7 @@ function extractDomainFromUri2(uri) {
|
|
|
21993
22294
|
try {
|
|
21994
22295
|
const url = new URL(uri);
|
|
21995
22296
|
const hostname = url.hostname.replace(/^www\./, "").toLowerCase();
|
|
21996
|
-
if (
|
|
22297
|
+
if (AI_ENGINE_SELF_DOMAINS.chatgpt.some((self) => hostname.includes(self))) {
|
|
21997
22298
|
return null;
|
|
21998
22299
|
}
|
|
21999
22300
|
return hostname;
|
|
@@ -22372,7 +22673,7 @@ function extractDomainFromUri3(uri) {
|
|
|
22372
22673
|
try {
|
|
22373
22674
|
const url = new URL(uri);
|
|
22374
22675
|
const hostname = url.hostname.replace(/^www\./, "").toLowerCase();
|
|
22375
|
-
if (
|
|
22676
|
+
if (AI_ENGINE_SELF_DOMAINS.chatgpt.some((self) => hostname.includes(self))) {
|
|
22376
22677
|
return null;
|
|
22377
22678
|
}
|
|
22378
22679
|
return hostname;
|
|
@@ -22917,8 +23218,8 @@ async function waitForStabilization(client, selector, opts = {}) {
|
|
|
22917
23218
|
// ../provider-cdp/src/targets/chatgpt.ts
|
|
22918
23219
|
var chatgptTarget = {
|
|
22919
23220
|
name: "chatgpt",
|
|
22920
|
-
baseUrl:
|
|
22921
|
-
newConversationUrl:
|
|
23221
|
+
baseUrl: `https://${AI_ENGINE_DOMAINS.chatgpt}`,
|
|
23222
|
+
newConversationUrl: `https://${AI_ENGINE_DOMAINS.chatgpt}/?model=auto`,
|
|
22922
23223
|
responseSelector: '[data-testid="conversation-turn-3"], article:last-of-type, .agent-turn:last-of-type',
|
|
22923
23224
|
async submitQuery(client, query) {
|
|
22924
23225
|
const inputReady = await waitForElement(
|
|
@@ -23022,8 +23323,10 @@ var chatgptTarget = {
|
|
|
23022
23323
|
},
|
|
23023
23324
|
extractCitations(client) {
|
|
23024
23325
|
return (async () => {
|
|
23326
|
+
const selfDomainsLiteral = JSON.stringify(AI_ENGINE_SELF_DOMAINS.chatgpt);
|
|
23025
23327
|
const { result } = await client.Runtime.evaluate({
|
|
23026
23328
|
expression: `(() => {
|
|
23329
|
+
const SELF_DOMAINS = ${selfDomainsLiteral};
|
|
23027
23330
|
const sources = [];
|
|
23028
23331
|
const seen = new Set();
|
|
23029
23332
|
const turns = document.querySelectorAll('[data-message-author-role="assistant"]');
|
|
@@ -23047,7 +23350,7 @@ var chatgptTarget = {
|
|
|
23047
23350
|
}
|
|
23048
23351
|
}
|
|
23049
23352
|
|
|
23050
|
-
if (!seen.has(href) &&
|
|
23353
|
+
if (!seen.has(href) && !SELF_DOMAINS.includes(hostname)) {
|
|
23051
23354
|
seen.add(href);
|
|
23052
23355
|
sources.push({
|
|
23053
23356
|
uri: href,
|
|
@@ -23064,7 +23367,7 @@ var chatgptTarget = {
|
|
|
23064
23367
|
if (href && !seen.has(href)) {
|
|
23065
23368
|
let hostname = '';
|
|
23066
23369
|
try { hostname = new URL(href).hostname.replace(/^www\\./, ''); } catch {}
|
|
23067
|
-
if (
|
|
23370
|
+
if (!SELF_DOMAINS.includes(hostname)) {
|
|
23068
23371
|
seen.add(href);
|
|
23069
23372
|
sources.push({ uri: href, title: title || hostname || href });
|
|
23070
23373
|
}
|
|
@@ -23154,7 +23457,7 @@ function extractCitedDomains(groundingSources) {
|
|
|
23154
23457
|
try {
|
|
23155
23458
|
const url = new URL(source.uri);
|
|
23156
23459
|
const domain = url.hostname.replace(/^www\./, "").toLowerCase();
|
|
23157
|
-
if (!
|
|
23460
|
+
if (!AI_ENGINE_SELF_DOMAINS.chatgpt.some((self) => domain.includes(self))) {
|
|
23158
23461
|
domains.add(domain);
|
|
23159
23462
|
}
|
|
23160
23463
|
} catch {
|
|
@@ -23539,7 +23842,7 @@ function extractDomainFromUri4(uri) {
|
|
|
23539
23842
|
try {
|
|
23540
23843
|
const url = new URL(uri);
|
|
23541
23844
|
const hostname = url.hostname.replace(/^www\./, "").toLowerCase();
|
|
23542
|
-
if (
|
|
23845
|
+
if (AI_ENGINE_SELF_DOMAINS.chatgpt.some((self) => hostname.includes(self))) {
|
|
23543
23846
|
return null;
|
|
23544
23847
|
}
|
|
23545
23848
|
return hostname;
|
|
@@ -23904,7 +24207,7 @@ import crypto24 from "crypto";
|
|
|
23904
24207
|
import fs8 from "fs";
|
|
23905
24208
|
import path10 from "path";
|
|
23906
24209
|
import os5 from "os";
|
|
23907
|
-
import { and as
|
|
24210
|
+
import { and as and21, eq as eq27, inArray as inArray10, sql as sql12 } from "drizzle-orm";
|
|
23908
24211
|
|
|
23909
24212
|
// src/run-telemetry.ts
|
|
23910
24213
|
import crypto23 from "crypto";
|
|
@@ -24287,7 +24590,7 @@ var JobRunner = class {
|
|
|
24287
24590
|
throw new Error(`Run ${runId} is not executable from status '${existingRun.status}'`);
|
|
24288
24591
|
}
|
|
24289
24592
|
if (existingRun.status === "queued") {
|
|
24290
|
-
this.db.update(runs).set({ status: "running", startedAt: now }).where(
|
|
24593
|
+
this.db.update(runs).set({ status: "running", startedAt: now }).where(and21(eq27(runs.id, runId), eq27(runs.status, "queued"))).run();
|
|
24291
24594
|
}
|
|
24292
24595
|
this.throwIfRunCancelled(runId);
|
|
24293
24596
|
const project = this.db.select().from(projects).where(eq27(projects.id, projectId)).get();
|
|
@@ -24312,7 +24615,7 @@ var JobRunner = class {
|
|
|
24312
24615
|
}
|
|
24313
24616
|
log.info("run.dispatch", { runId, providerCount: activeProviders.length, providers: activeProviders.map((p) => p.adapter.name) });
|
|
24314
24617
|
const scopedQueryNames = parseJsonColumn(existingRun.queries, null);
|
|
24315
|
-
projectQueries = scopedQueryNames ? this.db.select().from(queries).where(
|
|
24618
|
+
projectQueries = scopedQueryNames ? this.db.select().from(queries).where(and21(eq27(queries.projectId, projectId), inArray10(queries.query, scopedQueryNames))).all() : this.db.select().from(queries).where(eq27(queries.projectId, projectId)).all();
|
|
24316
24619
|
const projectCompetitors = this.db.select().from(competitors).where(eq27(competitors.projectId, projectId)).all();
|
|
24317
24620
|
const competitorDomains = projectCompetitors.map((c) => c.domain);
|
|
24318
24621
|
const allDomains = effectiveDomains({
|
|
@@ -24655,7 +24958,7 @@ function buildPhases(input) {
|
|
|
24655
24958
|
|
|
24656
24959
|
// src/gsc-sync.ts
|
|
24657
24960
|
import crypto25 from "crypto";
|
|
24658
|
-
import { eq as eq28, and as
|
|
24961
|
+
import { eq as eq28, and as and22, sql as sql13 } from "drizzle-orm";
|
|
24659
24962
|
var log2 = createLogger("GscSync");
|
|
24660
24963
|
function formatDate3(d) {
|
|
24661
24964
|
return d.toISOString().split("T")[0];
|
|
@@ -24707,7 +25010,7 @@ async function executeGscSync(db, runId, projectId, opts) {
|
|
|
24707
25010
|
});
|
|
24708
25011
|
log2.info("fetch.complete", { runId, projectId, rowCount: rows.length });
|
|
24709
25012
|
db.delete(gscSearchData).where(
|
|
24710
|
-
|
|
25013
|
+
and22(
|
|
24711
25014
|
eq28(gscSearchData.projectId, projectId),
|
|
24712
25015
|
sql13`${gscSearchData.date} >= ${startDate}`,
|
|
24713
25016
|
sql13`${gscSearchData.date} <= ${endDate}`
|
|
@@ -24796,7 +25099,7 @@ async function executeGscSync(db, runId, projectId, opts) {
|
|
|
24796
25099
|
}
|
|
24797
25100
|
}
|
|
24798
25101
|
const snapshotDate = formatDate3(/* @__PURE__ */ new Date());
|
|
24799
|
-
db.delete(gscCoverageSnapshots).where(
|
|
25102
|
+
db.delete(gscCoverageSnapshots).where(and22(eq28(gscCoverageSnapshots.projectId, projectId), eq28(gscCoverageSnapshots.date, snapshotDate))).run();
|
|
24800
25103
|
db.insert(gscCoverageSnapshots).values({
|
|
24801
25104
|
id: crypto25.randomUUID(),
|
|
24802
25105
|
projectId,
|
|
@@ -24819,7 +25122,7 @@ async function executeGscSync(db, runId, projectId, opts) {
|
|
|
24819
25122
|
|
|
24820
25123
|
// src/gsc-inspect-sitemap.ts
|
|
24821
25124
|
import crypto26 from "crypto";
|
|
24822
|
-
import { eq as eq29, and as
|
|
25125
|
+
import { eq as eq29, and as and23 } from "drizzle-orm";
|
|
24823
25126
|
|
|
24824
25127
|
// src/sitemap-parser.ts
|
|
24825
25128
|
var log3 = createLogger("SitemapParser");
|
|
@@ -25037,7 +25340,7 @@ async function executeInspectSitemap(db, runId, projectId, opts) {
|
|
|
25037
25340
|
}
|
|
25038
25341
|
}
|
|
25039
25342
|
const snapshotDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
25040
|
-
db.delete(gscCoverageSnapshots).where(
|
|
25343
|
+
db.delete(gscCoverageSnapshots).where(and23(eq29(gscCoverageSnapshots.projectId, projectId), eq29(gscCoverageSnapshots.date, snapshotDate))).run();
|
|
25041
25344
|
db.insert(gscCoverageSnapshots).values({
|
|
25042
25345
|
id: crypto26.randomUUID(),
|
|
25043
25346
|
projectId,
|
|
@@ -25248,7 +25551,7 @@ async function executeBingInspectSitemap(db, runId, projectId, opts) {
|
|
|
25248
25551
|
// src/commoncrawl-sync.ts
|
|
25249
25552
|
import crypto28 from "crypto";
|
|
25250
25553
|
import path11 from "path";
|
|
25251
|
-
import { and as
|
|
25554
|
+
import { and as and24, eq as eq31, sql as sql14 } from "drizzle-orm";
|
|
25252
25555
|
var log6 = createLogger("CommonCrawlSync");
|
|
25253
25556
|
var INSERT_CHUNK_SIZE = 1e4;
|
|
25254
25557
|
function defaultDeps() {
|
|
@@ -25439,7 +25742,7 @@ function computeSummary(rows) {
|
|
|
25439
25742
|
// src/backlink-extract.ts
|
|
25440
25743
|
import crypto29 from "crypto";
|
|
25441
25744
|
import fs9 from "fs";
|
|
25442
|
-
import { and as
|
|
25745
|
+
import { and as and25, desc as desc15, eq as eq32 } from "drizzle-orm";
|
|
25443
25746
|
var log7 = createLogger("BacklinkExtract");
|
|
25444
25747
|
function defaultDeps2() {
|
|
25445
25748
|
return {
|
|
@@ -25485,7 +25788,7 @@ async function executeBacklinkExtract(db, runId, projectId, opts = {}) {
|
|
|
25485
25788
|
const targetDomain = project.canonicalDomain;
|
|
25486
25789
|
db.transaction((tx) => {
|
|
25487
25790
|
tx.delete(backlinkDomains).where(
|
|
25488
|
-
|
|
25791
|
+
and25(eq32(backlinkDomains.projectId, projectId), eq32(backlinkDomains.release, release))
|
|
25489
25792
|
).run();
|
|
25490
25793
|
if (rows.length > 0) {
|
|
25491
25794
|
const values = rows.map((r) => ({
|
|
@@ -25556,7 +25859,7 @@ function computeSummary2(rows) {
|
|
|
25556
25859
|
|
|
25557
25860
|
// src/discovery-run.ts
|
|
25558
25861
|
import crypto30 from "crypto";
|
|
25559
|
-
import { and as
|
|
25862
|
+
import { and as and26, eq as eq33 } from "drizzle-orm";
|
|
25560
25863
|
var log8 = createLogger("DiscoveryRun");
|
|
25561
25864
|
var DEFAULT_SEED_COUNT = 30;
|
|
25562
25865
|
var QUERIES_PER_INTENT_BUCKET = 6;
|
|
@@ -25816,7 +26119,7 @@ function writeDiscoveryInsight(db, input) {
|
|
|
25816
26119
|
totalProbes
|
|
25817
26120
|
});
|
|
25818
26121
|
db.transaction((tx) => {
|
|
25819
|
-
tx.update(insights).set({ dismissed: true }).where(
|
|
26122
|
+
tx.update(insights).set({ dismissed: true }).where(and26(
|
|
25820
26123
|
eq33(insights.projectId, input.projectId),
|
|
25821
26124
|
eq33(insights.type, "discovery.basket-divergence"),
|
|
25822
26125
|
eq33(insights.dismissed, false)
|
|
@@ -25860,7 +26163,7 @@ function buildDiscoveryInsightTitle(input) {
|
|
|
25860
26163
|
}
|
|
25861
26164
|
|
|
25862
26165
|
// src/commands/backfill.ts
|
|
25863
|
-
import { and as
|
|
26166
|
+
import { and as and27, eq as eq34, inArray as inArray11 } from "drizzle-orm";
|
|
25864
26167
|
var SNAPSHOT_BATCH_SIZE = 500;
|
|
25865
26168
|
async function backfillAnswerVisibilityCommand(opts) {
|
|
25866
26169
|
const config = loadConfig();
|
|
@@ -25876,7 +26179,7 @@ async function backfillAnswerVisibilityCommand(opts) {
|
|
|
25876
26179
|
let reparsed = 0;
|
|
25877
26180
|
let providerErrors = 0;
|
|
25878
26181
|
if (scopedProjects.length > 0) {
|
|
25879
|
-
const runRows = projectFilter ? db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(
|
|
26182
|
+
const runRows = projectFilter ? db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(and27(
|
|
25880
26183
|
eq34(runs.kind, RunKinds["answer-visibility"]),
|
|
25881
26184
|
inArray11(runs.projectId, scopedProjects.map((project) => project.id))
|
|
25882
26185
|
)).all() : db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(eq34(runs.kind, RunKinds["answer-visibility"])).all();
|
|
@@ -26034,7 +26337,7 @@ function backfillNormalizedPaths(db, opts) {
|
|
|
26034
26337
|
id: gaTrafficSnapshots.id,
|
|
26035
26338
|
landingPage: gaTrafficSnapshots.landingPage,
|
|
26036
26339
|
landingPageNormalized: gaTrafficSnapshots.landingPageNormalized
|
|
26037
|
-
}).from(gaTrafficSnapshots).where(baseConditions.length > 0 ?
|
|
26340
|
+
}).from(gaTrafficSnapshots).where(baseConditions.length > 0 ? and27(...baseConditions) : void 0).all();
|
|
26038
26341
|
let updated = 0;
|
|
26039
26342
|
let unchanged = 0;
|
|
26040
26343
|
if (rows.length > 0) {
|
|
@@ -26106,7 +26409,7 @@ function backfillAiReferralPaths(db, opts) {
|
|
|
26106
26409
|
id: gaAiReferrals.id,
|
|
26107
26410
|
landingPage: gaAiReferrals.landingPage,
|
|
26108
26411
|
landingPageNormalized: gaAiReferrals.landingPageNormalized
|
|
26109
|
-
}).from(gaAiReferrals).where(baseConditions.length > 0 ?
|
|
26412
|
+
}).from(gaAiReferrals).where(baseConditions.length > 0 ? and27(...baseConditions) : void 0).all();
|
|
26110
26413
|
let updated = 0;
|
|
26111
26414
|
let unchanged = 0;
|
|
26112
26415
|
if (rows.length > 0) {
|
|
@@ -26174,7 +26477,7 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
|
|
|
26174
26477
|
const project = db.select().from(projects).where(eq34(projects.id, projectId)).get();
|
|
26175
26478
|
if (!project) return { examined: 0, updated: 0, mentioned: 0 };
|
|
26176
26479
|
const competitorDomains = db.select({ domain: competitors.domain }).from(competitors).where(eq34(competitors.projectId, projectId)).all().map((row) => row.domain);
|
|
26177
|
-
const runRows = db.select({ id: runs.id }).from(runs).where(
|
|
26480
|
+
const runRows = db.select({ id: runs.id }).from(runs).where(and27(eq34(runs.kind, RunKinds["answer-visibility"]), eq34(runs.projectId, projectId))).all();
|
|
26178
26481
|
const runIds = runRows.map((r) => r.id);
|
|
26179
26482
|
let examined = 0;
|
|
26180
26483
|
let updated = 0;
|
|
@@ -26325,7 +26628,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
26325
26628
|
return result;
|
|
26326
26629
|
}
|
|
26327
26630
|
async function backfillInsightsCommand(project, opts) {
|
|
26328
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
26631
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-TY7IPRST.js");
|
|
26329
26632
|
const config = loadConfig();
|
|
26330
26633
|
const db = createClient(config.database);
|
|
26331
26634
|
migrate(db);
|
|
@@ -26474,7 +26777,7 @@ var ProviderRegistry = class {
|
|
|
26474
26777
|
|
|
26475
26778
|
// src/scheduler.ts
|
|
26476
26779
|
import cron from "node-cron";
|
|
26477
|
-
import { and as
|
|
26780
|
+
import { and as and28, eq as eq35 } from "drizzle-orm";
|
|
26478
26781
|
var log9 = createLogger("Scheduler");
|
|
26479
26782
|
function taskKey(projectId, kind) {
|
|
26480
26783
|
return `${projectId}::${kind}`;
|
|
@@ -26519,7 +26822,7 @@ var Scheduler = class {
|
|
|
26519
26822
|
this.stopTask(key, existing, "Stopped");
|
|
26520
26823
|
this.tasks.delete(key);
|
|
26521
26824
|
}
|
|
26522
|
-
const schedule = this.db.select().from(schedules).where(
|
|
26825
|
+
const schedule = this.db.select().from(schedules).where(and28(eq35(schedules.projectId, projectId), eq35(schedules.kind, kind))).get();
|
|
26523
26826
|
if (schedule && schedule.enabled === 1) {
|
|
26524
26827
|
this.registerCronTask(schedule);
|
|
26525
26828
|
}
|
|
@@ -26540,8 +26843,8 @@ var Scheduler = class {
|
|
|
26540
26843
|
}
|
|
26541
26844
|
}
|
|
26542
26845
|
stopTask(key, task, verb) {
|
|
26543
|
-
task.stop();
|
|
26544
|
-
task.destroy();
|
|
26846
|
+
void task.stop();
|
|
26847
|
+
void task.destroy();
|
|
26545
26848
|
log9.info(`task.${verb.toLowerCase()}`, { key });
|
|
26546
26849
|
}
|
|
26547
26850
|
registerCronTask(schedule) {
|
|
@@ -26643,7 +26946,7 @@ var Scheduler = class {
|
|
|
26643
26946
|
};
|
|
26644
26947
|
|
|
26645
26948
|
// src/notifier.ts
|
|
26646
|
-
import { eq as eq36, desc as desc16, and as
|
|
26949
|
+
import { eq as eq36, desc as desc16, and as and29, inArray as inArray12, or as or5 } from "drizzle-orm";
|
|
26647
26950
|
import crypto31 from "crypto";
|
|
26648
26951
|
var log10 = createLogger("Notifier");
|
|
26649
26952
|
var Notifier = class {
|
|
@@ -26750,7 +27053,7 @@ var Notifier = class {
|
|
|
26750
27053
|
computeTransitions(runId, projectId) {
|
|
26751
27054
|
const thisRun = this.db.select().from(runs).where(eq36(runs.id, runId)).get();
|
|
26752
27055
|
if (!thisRun) return [];
|
|
26753
|
-
const groupSiblings = this.db.select().from(runs).where(
|
|
27056
|
+
const groupSiblings = this.db.select().from(runs).where(and29(
|
|
26754
27057
|
eq36(runs.projectId, projectId),
|
|
26755
27058
|
eq36(runs.kind, thisRun.kind),
|
|
26756
27059
|
eq36(runs.createdAt, thisRun.createdAt)
|
|
@@ -26776,7 +27079,7 @@ var Notifier = class {
|
|
|
26776
27079
|
);
|
|
26777
27080
|
const RECENT_FETCH_LIMIT = Math.max(8, locationCount * 4);
|
|
26778
27081
|
const recentRuns = this.db.select().from(runs).where(
|
|
26779
|
-
|
|
27082
|
+
and29(
|
|
26780
27083
|
eq36(runs.projectId, projectId),
|
|
26781
27084
|
eq36(runs.kind, thisRun.kind),
|
|
26782
27085
|
or5(eq36(runs.status, "completed"), eq36(runs.status, "partial"))
|
|
@@ -26889,6 +27192,10 @@ var RunCoordinator = class {
|
|
|
26889
27192
|
async onRunCompleted(runId, projectId) {
|
|
26890
27193
|
const runRow = this.db.select().from(runs).where(eq37(runs.id, runId)).get();
|
|
26891
27194
|
const kind = runRow?.kind ?? RunKinds["answer-visibility"];
|
|
27195
|
+
if (runRow?.trigger === RunTriggers.probe) {
|
|
27196
|
+
log11.info("probe.skip-side-effects", { runId, projectId, kind });
|
|
27197
|
+
return;
|
|
27198
|
+
}
|
|
26892
27199
|
let insightCount = 0;
|
|
26893
27200
|
let criticalOrHigh = 0;
|
|
26894
27201
|
if (kind === RunKinds["answer-visibility"]) {
|
|
@@ -27315,7 +27622,7 @@ function resolveSessionProviderAndModel(config, opts) {
|
|
|
27315
27622
|
|
|
27316
27623
|
// src/agent/memory-store.ts
|
|
27317
27624
|
import crypto32 from "crypto";
|
|
27318
|
-
import { and as
|
|
27625
|
+
import { and as and30, desc as desc17, eq as eq38, like as like2, sql as sql15 } from "drizzle-orm";
|
|
27319
27626
|
var COMPACTION_KEY_PREFIX = "compaction:";
|
|
27320
27627
|
var COMPACTION_NOTES_PER_SESSION = 3;
|
|
27321
27628
|
function rowToDto2(row) {
|
|
@@ -27360,12 +27667,12 @@ function upsertMemoryEntry(db, args) {
|
|
|
27360
27667
|
updatedAt: now
|
|
27361
27668
|
}
|
|
27362
27669
|
}).run();
|
|
27363
|
-
const row = db.select().from(agentMemory).where(
|
|
27670
|
+
const row = db.select().from(agentMemory).where(and30(eq38(agentMemory.projectId, args.projectId), eq38(agentMemory.key, args.key))).get();
|
|
27364
27671
|
if (!row) throw new Error("memory upsert produced no row");
|
|
27365
27672
|
return rowToDto2(row);
|
|
27366
27673
|
}
|
|
27367
27674
|
function deleteMemoryEntry(db, projectId, key) {
|
|
27368
|
-
const result = db.delete(agentMemory).where(
|
|
27675
|
+
const result = db.delete(agentMemory).where(and30(eq38(agentMemory.projectId, projectId), eq38(agentMemory.key, key))).run();
|
|
27369
27676
|
const changes = result.changes ?? 0;
|
|
27370
27677
|
return changes > 0;
|
|
27371
27678
|
}
|
|
@@ -27394,7 +27701,7 @@ function writeCompactionNote(db, args) {
|
|
|
27394
27701
|
}).run();
|
|
27395
27702
|
const sessionPrefix = `${COMPACTION_KEY_PREFIX}${args.sessionId}:`;
|
|
27396
27703
|
const existing = tx.select({ id: agentMemory.id, updatedAt: agentMemory.updatedAt }).from(agentMemory).where(
|
|
27397
|
-
|
|
27704
|
+
and30(
|
|
27398
27705
|
eq38(agentMemory.projectId, args.projectId),
|
|
27399
27706
|
like2(agentMemory.key, `${sessionPrefix}%`)
|
|
27400
27707
|
)
|
|
@@ -27403,7 +27710,7 @@ function writeCompactionNote(db, args) {
|
|
|
27403
27710
|
if (stale.length > 0) {
|
|
27404
27711
|
tx.delete(agentMemory).where(sql15`${agentMemory.id} IN (${sql15.join(stale.map((s) => sql15`${s}`), sql15`, `)})`).run();
|
|
27405
27712
|
}
|
|
27406
|
-
const row = tx.select().from(agentMemory).where(
|
|
27713
|
+
const row = tx.select().from(agentMemory).where(and30(eq38(agentMemory.projectId, args.projectId), eq38(agentMemory.key, key))).get();
|
|
27407
27714
|
if (row) inserted = rowToDto2(row);
|
|
27408
27715
|
});
|
|
27409
27716
|
if (!inserted) throw new Error("compaction note write produced no row");
|