@orion-studios/payload-seo-audit 1.0.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/README.md +127 -0
- package/bin/init.js +267 -0
- package/dist/api/backlinks-import.d.ts +4 -0
- package/dist/api/backlinks-import.d.ts.map +1 -0
- package/dist/api/backlinks-import.js +182 -0
- package/dist/api/cron.d.ts +4 -0
- package/dist/api/cron.d.ts.map +1 -0
- package/dist/api/cron.js +89 -0
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +21 -0
- package/dist/api/page-result.d.ts +4 -0
- package/dist/api/page-result.d.ts.map +1 -0
- package/dist/api/page-result.js +93 -0
- package/dist/api/page-results.d.ts +4 -0
- package/dist/api/page-results.d.ts.map +1 -0
- package/dist/api/page-results.js +83 -0
- package/dist/api/run-stream.d.ts +4 -0
- package/dist/api/run-stream.d.ts.map +1 -0
- package/dist/api/run-stream.js +273 -0
- package/dist/api/run.d.ts +4 -0
- package/dist/api/run.d.ts.map +1 -0
- package/dist/api/run.js +102 -0
- package/dist/api/snapshot-report.d.ts +4 -0
- package/dist/api/snapshot-report.d.ts.map +1 -0
- package/dist/api/snapshot-report.js +130 -0
- package/dist/api/snapshots.d.ts +4 -0
- package/dist/api/snapshots.d.ts.map +1 -0
- package/dist/api/snapshots.js +138 -0
- package/dist/api/trend.d.ts +4 -0
- package/dist/api/trend.d.ts.map +1 -0
- package/dist/api/trend.js +71 -0
- package/dist/collections/SeoAuthoritySnapshots.d.ts +3 -0
- package/dist/collections/SeoAuthoritySnapshots.d.ts.map +1 -0
- package/dist/collections/SeoAuthoritySnapshots.js +83 -0
- package/dist/collections/SeoKeywordVisibility.d.ts +3 -0
- package/dist/collections/SeoKeywordVisibility.d.ts.map +1 -0
- package/dist/collections/SeoKeywordVisibility.js +65 -0
- package/dist/collections/SeoPageResults.d.ts +3 -0
- package/dist/collections/SeoPageResults.d.ts.map +1 -0
- package/dist/collections/SeoPageResults.js +170 -0
- package/dist/collections/SeoSnapshots.d.ts +3 -0
- package/dist/collections/SeoSnapshots.d.ts.map +1 -0
- package/dist/collections/SeoSnapshots.js +131 -0
- package/dist/components/hooks/useSeoApi.d.ts +7 -0
- package/dist/components/hooks/useSeoApi.d.ts.map +1 -0
- package/dist/components/hooks/useSeoApi.js +31 -0
- package/dist/components/hooks/useSeoPageResults.d.ts +19 -0
- package/dist/components/hooks/useSeoPageResults.d.ts.map +1 -0
- package/dist/components/hooks/useSeoPageResults.js +62 -0
- package/dist/components/hooks/useSeoSnapshot.d.ts +8 -0
- package/dist/components/hooks/useSeoSnapshot.d.ts.map +1 -0
- package/dist/components/hooks/useSeoSnapshot.js +39 -0
- package/dist/components/hooks/useSeoTrend.d.ts +8 -0
- package/dist/components/hooks/useSeoTrend.d.ts.map +1 -0
- package/dist/components/hooks/useSeoTrend.js +38 -0
- package/dist/components/layout/SeoReportHeader.d.ts +10 -0
- package/dist/components/layout/SeoReportHeader.d.ts.map +1 -0
- package/dist/components/layout/SeoReportHeader.js +18 -0
- package/dist/components/layout/SeoReportShell.d.ts +9 -0
- package/dist/components/layout/SeoReportShell.d.ts.map +1 -0
- package/dist/components/layout/SeoReportShell.js +17 -0
- package/dist/components/pdf/PdfDownloadButton.d.ts +9 -0
- package/dist/components/pdf/PdfDownloadButton.d.ts.map +1 -0
- package/dist/components/pdf/PdfDownloadButton.js +80 -0
- package/dist/components/tables/IssueTable.d.ts +11 -0
- package/dist/components/tables/IssueTable.d.ts.map +1 -0
- package/dist/components/tables/IssueTable.js +121 -0
- package/dist/components/tables/PageResultsTable.d.ts +18 -0
- package/dist/components/tables/PageResultsTable.d.ts.map +1 -0
- package/dist/components/tables/PageResultsTable.js +96 -0
- package/dist/components/types.d.ts +107 -0
- package/dist/components/types.d.ts.map +1 -0
- package/dist/components/types.js +22 -0
- package/dist/components/utils/formatters.d.ts +15 -0
- package/dist/components/utils/formatters.d.ts.map +1 -0
- package/dist/components/utils/formatters.js +98 -0
- package/dist/components/utils/scoreHelpers.d.ts +17 -0
- package/dist/components/utils/scoreHelpers.d.ts.map +1 -0
- package/dist/components/utils/scoreHelpers.js +139 -0
- package/dist/components/views/SeoDashboard.d.ts +3 -0
- package/dist/components/views/SeoDashboard.d.ts.map +1 -0
- package/dist/components/views/SeoDashboard.js +239 -0
- package/dist/components/views/SeoPageReport.d.ts +3 -0
- package/dist/components/views/SeoPageReport.d.ts.map +1 -0
- package/dist/components/views/SeoPageReport.js +234 -0
- package/dist/components/views/SeoSnapshotReport.d.ts +3 -0
- package/dist/components/views/SeoSnapshotReport.d.ts.map +1 -0
- package/dist/components/views/SeoSnapshotReport.js +224 -0
- package/dist/components/visualization/CategoryScoreCard.d.ts +11 -0
- package/dist/components/visualization/CategoryScoreCard.d.ts.map +1 -0
- package/dist/components/visualization/CategoryScoreCard.js +17 -0
- package/dist/components/visualization/CategoryScoreGrid.d.ts +9 -0
- package/dist/components/visualization/CategoryScoreGrid.d.ts.map +1 -0
- package/dist/components/visualization/CategoryScoreGrid.js +32 -0
- package/dist/components/visualization/IssueCategoryChart.d.ts +8 -0
- package/dist/components/visualization/IssueCategoryChart.d.ts.map +1 -0
- package/dist/components/visualization/IssueCategoryChart.js +47 -0
- package/dist/components/visualization/MetricCard.d.ts +11 -0
- package/dist/components/visualization/MetricCard.d.ts.map +1 -0
- package/dist/components/visualization/MetricCard.js +17 -0
- package/dist/components/visualization/MetricCardRow.d.ts +7 -0
- package/dist/components/visualization/MetricCardRow.d.ts.map +1 -0
- package/dist/components/visualization/MetricCardRow.js +12 -0
- package/dist/components/visualization/ScoreBar.d.ts +11 -0
- package/dist/components/visualization/ScoreBar.d.ts.map +1 -0
- package/dist/components/visualization/ScoreBar.js +34 -0
- package/dist/components/visualization/ScoreGauge.d.ts +11 -0
- package/dist/components/visualization/ScoreGauge.d.ts.map +1 -0
- package/dist/components/visualization/ScoreGauge.js +28 -0
- package/dist/components/visualization/ScoreTrendChart.d.ts +9 -0
- package/dist/components/visualization/ScoreTrendChart.d.ts.map +1 -0
- package/dist/components/visualization/ScoreTrendChart.js +43 -0
- package/dist/components/visualization/SeverityBadge.d.ts +8 -0
- package/dist/components/visualization/SeverityBadge.d.ts.map +1 -0
- package/dist/components/visualization/SeverityBadge.js +14 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +36 -0
- package/dist/exports/components.d.ts +4 -0
- package/dist/exports/components.d.ts.map +1 -0
- package/dist/exports/components.js +9 -0
- package/dist/globals/SeoDashboard.d.ts +3 -0
- package/dist/globals/SeoDashboard.d.ts.map +1 -0
- package/dist/globals/SeoDashboard.js +25 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/utilities/access.d.ts +8 -0
- package/dist/utilities/access.d.ts.map +1 -0
- package/dist/utilities/access.js +11 -0
- package/dist/utilities/auth.d.ts +7 -0
- package/dist/utilities/auth.d.ts.map +1 -0
- package/dist/utilities/auth.js +28 -0
- package/dist/utilities/checks.d.ts +3 -0
- package/dist/utilities/checks.d.ts.map +1 -0
- package/dist/utilities/checks.js +255 -0
- package/dist/utilities/crawler.d.ts +14 -0
- package/dist/utilities/crawler.d.ts.map +1 -0
- package/dist/utilities/crawler.js +152 -0
- package/dist/utilities/gsc.d.ts +15 -0
- package/dist/utilities/gsc.d.ts.map +1 -0
- package/dist/utilities/gsc.js +69 -0
- package/dist/utilities/helpers.d.ts +7 -0
- package/dist/utilities/helpers.d.ts.map +1 -0
- package/dist/utilities/helpers.js +44 -0
- package/dist/utilities/pagespeed.d.ts +3 -0
- package/dist/utilities/pagespeed.d.ts.map +1 -0
- package/dist/utilities/pagespeed.js +49 -0
- package/dist/utilities/providers.d.ts +3 -0
- package/dist/utilities/providers.d.ts.map +1 -0
- package/dist/utilities/providers.js +18 -0
- package/dist/utilities/runAudit.d.ts +14 -0
- package/dist/utilities/runAudit.d.ts.map +1 -0
- package/dist/utilities/runAudit.js +224 -0
- package/dist/utilities/scoring.d.ts +3 -0
- package/dist/utilities/scoring.d.ts.map +1 -0
- package/dist/utilities/scoring.js +45 -0
- package/dist/utilities/triggers.d.ts +3 -0
- package/dist/utilities/triggers.d.ts.map +1 -0
- package/dist/utilities/triggers.js +39 -0
- package/dist/utilities/types.d.ts +87 -0
- package/dist/utilities/types.d.ts.map +1 -0
- package/dist/utilities/types.js +2 -0
- package/package.json +63 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { handleSeoRun } from './run';
|
|
2
|
+
export { handleSeoRunStream } from './run-stream';
|
|
3
|
+
export { handleSeoSnapshots } from './snapshots';
|
|
4
|
+
export { handleSeoSnapshotReport } from './snapshot-report';
|
|
5
|
+
export { handleSeoPageResults } from './page-results';
|
|
6
|
+
export { handleSeoPageResult } from './page-result';
|
|
7
|
+
export { handleSeoTrend } from './trend';
|
|
8
|
+
export { handleSeoCron } from './cron';
|
|
9
|
+
export { handleSeoBacklinksImport } from './backlinks-import';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleSeoBacklinksImport = exports.handleSeoCron = exports.handleSeoTrend = exports.handleSeoPageResult = exports.handleSeoPageResults = exports.handleSeoSnapshotReport = exports.handleSeoSnapshots = exports.handleSeoRunStream = exports.handleSeoRun = void 0;
|
|
4
|
+
var run_1 = require("./run");
|
|
5
|
+
Object.defineProperty(exports, "handleSeoRun", { enumerable: true, get: function () { return run_1.handleSeoRun; } });
|
|
6
|
+
var run_stream_1 = require("./run-stream");
|
|
7
|
+
Object.defineProperty(exports, "handleSeoRunStream", { enumerable: true, get: function () { return run_stream_1.handleSeoRunStream; } });
|
|
8
|
+
var snapshots_1 = require("./snapshots");
|
|
9
|
+
Object.defineProperty(exports, "handleSeoSnapshots", { enumerable: true, get: function () { return snapshots_1.handleSeoSnapshots; } });
|
|
10
|
+
var snapshot_report_1 = require("./snapshot-report");
|
|
11
|
+
Object.defineProperty(exports, "handleSeoSnapshotReport", { enumerable: true, get: function () { return snapshot_report_1.handleSeoSnapshotReport; } });
|
|
12
|
+
var page_results_1 = require("./page-results");
|
|
13
|
+
Object.defineProperty(exports, "handleSeoPageResults", { enumerable: true, get: function () { return page_results_1.handleSeoPageResults; } });
|
|
14
|
+
var page_result_1 = require("./page-result");
|
|
15
|
+
Object.defineProperty(exports, "handleSeoPageResult", { enumerable: true, get: function () { return page_result_1.handleSeoPageResult; } });
|
|
16
|
+
var trend_1 = require("./trend");
|
|
17
|
+
Object.defineProperty(exports, "handleSeoTrend", { enumerable: true, get: function () { return trend_1.handleSeoTrend; } });
|
|
18
|
+
var cron_1 = require("./cron");
|
|
19
|
+
Object.defineProperty(exports, "handleSeoCron", { enumerable: true, get: function () { return cron_1.handleSeoCron; } });
|
|
20
|
+
var backlinks_import_1 = require("./backlinks-import");
|
|
21
|
+
Object.defineProperty(exports, "handleSeoBacklinksImport", { enumerable: true, get: function () { return backlinks_import_1.handleSeoBacklinksImport; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-result.d.ts","sourceRoot":"","sources":["../../src/api/page-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAO5D,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,CAAC,CA0EvB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleSeoPageResult = handleSeoPageResult;
|
|
37
|
+
const auth_1 = require("../utilities/auth");
|
|
38
|
+
async function handleSeoPageResult(payload, request) {
|
|
39
|
+
const { NextResponse } = await Promise.resolve().then(() => __importStar(require('next/server')));
|
|
40
|
+
try {
|
|
41
|
+
const user = await (0, auth_1.authenticateSEOAdmin)(payload, request);
|
|
42
|
+
if (!user) {
|
|
43
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
44
|
+
}
|
|
45
|
+
const { searchParams } = new URL(request.url);
|
|
46
|
+
const idParam = searchParams.get('id');
|
|
47
|
+
if (idParam) {
|
|
48
|
+
const pageResultID = Number.isFinite(Number(idParam)) ? Number(idParam) : idParam;
|
|
49
|
+
const doc = await payload.findByID({
|
|
50
|
+
collection: 'seo-page-results',
|
|
51
|
+
id: pageResultID,
|
|
52
|
+
depth: 1,
|
|
53
|
+
overrideAccess: true,
|
|
54
|
+
});
|
|
55
|
+
if (!doc) {
|
|
56
|
+
return NextResponse.json({ error: 'Page result not found.' }, { status: 404 });
|
|
57
|
+
}
|
|
58
|
+
return NextResponse.json({ pageResult: doc });
|
|
59
|
+
}
|
|
60
|
+
const pageURL = searchParams.get('url');
|
|
61
|
+
const snapshotParam = searchParams.get('snapshot');
|
|
62
|
+
const snapshotID = snapshotParam && Number.isFinite(Number(snapshotParam)) ? Number(snapshotParam) : null;
|
|
63
|
+
if (!pageURL) {
|
|
64
|
+
return NextResponse.json({ error: 'id or url query param is required.' }, { status: 400 });
|
|
65
|
+
}
|
|
66
|
+
const conditions = [{ url: { equals: pageURL } }];
|
|
67
|
+
if (snapshotID) {
|
|
68
|
+
conditions.push({
|
|
69
|
+
snapshot: { equals: snapshotID },
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const where = {
|
|
73
|
+
and: conditions,
|
|
74
|
+
};
|
|
75
|
+
const results = await payload.find({
|
|
76
|
+
collection: 'seo-page-results',
|
|
77
|
+
where,
|
|
78
|
+
limit: 1,
|
|
79
|
+
sort: '-checkedAt',
|
|
80
|
+
depth: 1,
|
|
81
|
+
overrideAccess: true,
|
|
82
|
+
});
|
|
83
|
+
const doc = results.docs[0];
|
|
84
|
+
if (!doc) {
|
|
85
|
+
return NextResponse.json({ error: 'Page result not found.' }, { status: 404 });
|
|
86
|
+
}
|
|
87
|
+
return NextResponse.json({ pageResult: doc });
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error('SEO page-result error:', error);
|
|
91
|
+
return NextResponse.json({ error: error instanceof Error ? error.message : 'Failed to load page result.' }, { status: 500 });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-results.d.ts","sourceRoot":"","sources":["../../src/api/page-results.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAM5D,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,CAAC,CA0DvB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleSeoPageResults = handleSeoPageResults;
|
|
37
|
+
const auth_1 = require("../utilities/auth");
|
|
38
|
+
async function handleSeoPageResults(payload, request) {
|
|
39
|
+
const { NextResponse } = await Promise.resolve().then(() => __importStar(require('next/server')));
|
|
40
|
+
try {
|
|
41
|
+
const user = await (0, auth_1.authenticateSEOAdmin)(payload, request);
|
|
42
|
+
if (!user) {
|
|
43
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
44
|
+
}
|
|
45
|
+
const { searchParams } = new URL(request.url);
|
|
46
|
+
const snapshotParam = searchParams.get('snapshot');
|
|
47
|
+
const snapshotID = snapshotParam && Number.isFinite(Number(snapshotParam)) ? Number(snapshotParam) : null;
|
|
48
|
+
if (!snapshotID) {
|
|
49
|
+
return NextResponse.json({ error: 'snapshot query param is required.' }, { status: 400 });
|
|
50
|
+
}
|
|
51
|
+
const sortField = searchParams.get('sort') || 'overallScore';
|
|
52
|
+
const order = searchParams.get('order') || 'asc';
|
|
53
|
+
const limit = Math.max(1, Math.min(100, Number(searchParams.get('limit') || 50)));
|
|
54
|
+
const page = Math.max(1, Number(searchParams.get('page') || 1));
|
|
55
|
+
const allowedSorts = ['overallScore', 'url', 'checkedAt', '-overallScore', '-url', '-checkedAt'];
|
|
56
|
+
const sortPrefix = order === 'desc' ? '-' : '';
|
|
57
|
+
let sortKey = `${sortPrefix}${sortField}`;
|
|
58
|
+
if (!allowedSorts.includes(sortKey) && !allowedSorts.includes(sortField)) {
|
|
59
|
+
sortKey = 'overallScore';
|
|
60
|
+
}
|
|
61
|
+
const results = await payload.find({
|
|
62
|
+
collection: 'seo-page-results',
|
|
63
|
+
where: { snapshot: { equals: snapshotID } },
|
|
64
|
+
limit,
|
|
65
|
+
page,
|
|
66
|
+
sort: sortKey,
|
|
67
|
+
depth: 0,
|
|
68
|
+
overrideAccess: true,
|
|
69
|
+
});
|
|
70
|
+
return NextResponse.json({
|
|
71
|
+
docs: results.docs,
|
|
72
|
+
totalDocs: results.totalDocs,
|
|
73
|
+
totalPages: results.totalPages,
|
|
74
|
+
page: results.page,
|
|
75
|
+
hasNextPage: results.hasNextPage,
|
|
76
|
+
hasPrevPage: results.hasPrevPage,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error('SEO page-results error:', error);
|
|
81
|
+
return NextResponse.json({ error: error instanceof Error ? error.message : 'Failed to load page results.' }, { status: 500 });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-stream.d.ts","sourceRoot":"","sources":["../../src/api/run-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAuE9C,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmQlG"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleSeoRunStream = handleSeoRunStream;
|
|
4
|
+
const auth_1 = require("../utilities/auth");
|
|
5
|
+
const index_1 = require("../index");
|
|
6
|
+
const checks_1 = require("../utilities/checks");
|
|
7
|
+
const crawler_1 = require("../utilities/crawler");
|
|
8
|
+
const helpers_1 = require("../utilities/helpers");
|
|
9
|
+
const gsc_1 = require("../utilities/gsc");
|
|
10
|
+
const pagespeed_1 = require("../utilities/pagespeed");
|
|
11
|
+
const scoring_1 = require("../utilities/scoring");
|
|
12
|
+
const providers_1 = require("../utilities/providers");
|
|
13
|
+
const resolveRunType = (value) => {
|
|
14
|
+
if (value === 'scheduled' || value === 'publish-triggered')
|
|
15
|
+
return value;
|
|
16
|
+
return 'manual';
|
|
17
|
+
};
|
|
18
|
+
const average = (values) => {
|
|
19
|
+
if (!values.length)
|
|
20
|
+
return 0;
|
|
21
|
+
return Math.round(values.reduce((sum, value) => sum + value, 0) / values.length);
|
|
22
|
+
};
|
|
23
|
+
const applyPerformanceIssues = (issues, pageSpeed, site) => {
|
|
24
|
+
if (!pageSpeed)
|
|
25
|
+
return issues;
|
|
26
|
+
const nextIssues = [...issues];
|
|
27
|
+
if (typeof pageSpeed.averagePerformanceScore === 'number' && pageSpeed.averagePerformanceScore < 70) {
|
|
28
|
+
nextIssues.push({
|
|
29
|
+
fingerprint: `perf-score-${pageSpeed.averagePerformanceScore}`,
|
|
30
|
+
ruleID: 'pagespeed-performance-low',
|
|
31
|
+
category: 'performance',
|
|
32
|
+
severity: pageSpeed.averagePerformanceScore < 50 ? 'high' : 'medium',
|
|
33
|
+
message: `Average Lighthouse performance score is ${pageSpeed.averagePerformanceScore}.`,
|
|
34
|
+
recommendation: 'Optimize render-blocking assets, image delivery, and JS execution.',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const targetLCP = Number(site.thresholds?.targetLCPMs || 2500);
|
|
38
|
+
if (typeof pageSpeed.averageLCPMs === 'number' && pageSpeed.averageLCPMs > targetLCP) {
|
|
39
|
+
nextIssues.push({
|
|
40
|
+
fingerprint: `perf-lcp-${pageSpeed.averageLCPMs}`,
|
|
41
|
+
ruleID: 'pagespeed-lcp-high',
|
|
42
|
+
category: 'performance',
|
|
43
|
+
severity: pageSpeed.averageLCPMs > targetLCP * 1.5 ? 'high' : 'medium',
|
|
44
|
+
message: `Average LCP is ${pageSpeed.averageLCPMs}ms.`,
|
|
45
|
+
recommendation: 'Improve server response times, preload key assets, and optimize hero content.',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const targetCLS = Number(site.thresholds?.targetCLS || 0.1);
|
|
49
|
+
if (typeof pageSpeed.averageCLS === 'number' && pageSpeed.averageCLS > targetCLS) {
|
|
50
|
+
nextIssues.push({
|
|
51
|
+
fingerprint: `perf-cls-${pageSpeed.averageCLS}`,
|
|
52
|
+
ruleID: 'pagespeed-cls-high',
|
|
53
|
+
category: 'performance',
|
|
54
|
+
severity: pageSpeed.averageCLS > targetCLS * 2 ? 'high' : 'medium',
|
|
55
|
+
message: `Average CLS is ${pageSpeed.averageCLS}.`,
|
|
56
|
+
recommendation: 'Set explicit media dimensions and reduce layout shifts from dynamic UI elements.',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return nextIssues;
|
|
60
|
+
};
|
|
61
|
+
async function handleSeoRunStream(payload, request) {
|
|
62
|
+
const body = (await request.json().catch(() => ({})));
|
|
63
|
+
const encoder = new TextEncoder();
|
|
64
|
+
const stream = new ReadableStream({
|
|
65
|
+
async start(controller) {
|
|
66
|
+
const send = (event, data) => {
|
|
67
|
+
controller.enqueue(encoder.encode(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`));
|
|
68
|
+
};
|
|
69
|
+
try {
|
|
70
|
+
send('progress', { step: 'auth', message: 'Authenticating...' });
|
|
71
|
+
const [user, secretAuthorized] = await Promise.all([
|
|
72
|
+
(0, auth_1.authenticateSEOAdmin)(payload, request),
|
|
73
|
+
Promise.resolve((0, auth_1.isValidSEOSecret)(request)),
|
|
74
|
+
]);
|
|
75
|
+
if (!user && !secretAuthorized) {
|
|
76
|
+
send('error', { message: 'Unauthorized' });
|
|
77
|
+
controller.close();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
send('progress', { step: 'site', message: 'Loading site configuration...' });
|
|
81
|
+
const seoConfig = (0, index_1.getSeoConfig)(payload);
|
|
82
|
+
if (!seoConfig) {
|
|
83
|
+
send('error', { message: 'SEO Audit plugin not configured' });
|
|
84
|
+
controller.close();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const site = {
|
|
88
|
+
id: 1,
|
|
89
|
+
name: seoConfig.site.name,
|
|
90
|
+
domain: seoConfig.site.domain,
|
|
91
|
+
canonicalHost: seoConfig.site.canonicalHost,
|
|
92
|
+
sitemapURL: seoConfig.site.sitemapURL,
|
|
93
|
+
keyURLs: seoConfig.site.keyURLs.map((url) => ({ url })),
|
|
94
|
+
crawlSettings: {
|
|
95
|
+
maxPages: seoConfig.crawl.maxPages,
|
|
96
|
+
maxDepth: seoConfig.crawl.maxDepth,
|
|
97
|
+
requestTimeoutMs: seoConfig.crawl.requestTimeoutMs,
|
|
98
|
+
includePatterns: seoConfig.crawl.includePatterns.map((pattern) => ({ pattern })),
|
|
99
|
+
excludePatterns: seoConfig.crawl.excludePatterns.map((pattern) => ({ pattern })),
|
|
100
|
+
},
|
|
101
|
+
integrations: {
|
|
102
|
+
enablePageSpeed: seoConfig.integrations.enablePageSpeed,
|
|
103
|
+
enableSearchConsole: seoConfig.integrations.enableSearchConsole,
|
|
104
|
+
},
|
|
105
|
+
thresholds: {
|
|
106
|
+
targetLCPMs: seoConfig.thresholds.targetLCPMs,
|
|
107
|
+
targetCLS: seoConfig.thresholds.targetCLS,
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
const runLabel = `${site.name} SEO Snapshot ${new Date().toISOString()}`;
|
|
111
|
+
send('progress', { step: 'snapshot', message: 'Creating snapshot record...' });
|
|
112
|
+
const snapshot = await payload.create({
|
|
113
|
+
collection: 'seo-snapshots',
|
|
114
|
+
data: {
|
|
115
|
+
runLabel,
|
|
116
|
+
runType: resolveRunType(body.runType),
|
|
117
|
+
status: 'pending',
|
|
118
|
+
startedAt: new Date().toISOString(),
|
|
119
|
+
},
|
|
120
|
+
overrideAccess: true,
|
|
121
|
+
});
|
|
122
|
+
send('progress', { step: 'crawl', message: 'Crawling site pages...' });
|
|
123
|
+
const crawl = await (0, crawler_1.crawlSiteForSEO)(site);
|
|
124
|
+
send('progress', {
|
|
125
|
+
step: 'crawl-complete',
|
|
126
|
+
message: `Found ${crawl.pages.length} pages`,
|
|
127
|
+
data: { pagesFound: crawl.pages.length },
|
|
128
|
+
});
|
|
129
|
+
send('progress', { step: 'checks', message: 'Running SEO checks on all pages...' });
|
|
130
|
+
const pageResults = crawl.pages.map((page) => {
|
|
131
|
+
const check = (0, checks_1.runSEOChecks)(page.url, page.html);
|
|
132
|
+
const score = (0, scoring_1.scoreSEOIssues)(check.issues);
|
|
133
|
+
return {
|
|
134
|
+
url: page.url,
|
|
135
|
+
path: page.path,
|
|
136
|
+
statusCode: page.statusCode,
|
|
137
|
+
check,
|
|
138
|
+
score,
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
send('progress', { step: 'checks-complete', message: 'SEO checks complete' });
|
|
142
|
+
send('progress', { step: 'pagespeed', message: 'Analyzing page performance...' });
|
|
143
|
+
const pageSpeedSummary = site.integrations?.enablePageSpeed !== false
|
|
144
|
+
? await (0, pagespeed_1.getPageSpeedSummary)(pageResults.map((page) => page.url))
|
|
145
|
+
: null;
|
|
146
|
+
if (pageSpeedSummary) {
|
|
147
|
+
send('progress', {
|
|
148
|
+
step: 'pagespeed-complete',
|
|
149
|
+
message: `Performance analysis complete (avg: ${pageSpeedSummary.averagePerformanceScore})`,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
send('progress', { step: 'pagespeed-skipped', message: 'PageSpeed analysis disabled' });
|
|
154
|
+
}
|
|
155
|
+
send('progress', { step: 'gsc', message: 'Syncing Google Search Console data...' });
|
|
156
|
+
const keywordVisibilitySync = await (0, gsc_1.syncGSCKeywordVisibility)({
|
|
157
|
+
payload,
|
|
158
|
+
site,
|
|
159
|
+
});
|
|
160
|
+
if (keywordVisibilitySync.enabled) {
|
|
161
|
+
send('progress', {
|
|
162
|
+
step: 'gsc-complete',
|
|
163
|
+
message: `Imported ${keywordVisibilitySync.imported} GSC keywords`,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
send('progress', { step: 'gsc-skipped', message: 'GSC sync disabled' });
|
|
168
|
+
}
|
|
169
|
+
const allIssues = applyPerformanceIssues(pageResults.flatMap((result) => result.check.issues), pageSpeedSummary, site);
|
|
170
|
+
const issueCounts = (0, helpers_1.countIssuesBySeverity)(allIssues);
|
|
171
|
+
const providerAdapter = (0, providers_1.getSEOProviderAdapter)();
|
|
172
|
+
const summaryText = keywordVisibilitySync.enabled
|
|
173
|
+
? `Automated audit completed using ${providerAdapter.name} authority adapter. GSC rows imported: ${keywordVisibilitySync.imported}.`
|
|
174
|
+
: `Automated audit completed using ${providerAdapter.name} authority adapter.`;
|
|
175
|
+
const scores = {
|
|
176
|
+
metadata: average(pageResults.map((result) => result.score.metadata)),
|
|
177
|
+
indexability: average(pageResults.map((result) => result.score.indexability)),
|
|
178
|
+
structure: average(pageResults.map((result) => result.score.structure)),
|
|
179
|
+
links: average(pageResults.map((result) => result.score.links)),
|
|
180
|
+
media: average(pageResults.map((result) => result.score.media)),
|
|
181
|
+
structuredData: average(pageResults.map((result) => result.score.structuredData)),
|
|
182
|
+
performance: typeof pageSpeedSummary?.averagePerformanceScore === 'number'
|
|
183
|
+
? pageSpeedSummary.averagePerformanceScore
|
|
184
|
+
: average(pageResults.map((result) => result.score.performance)),
|
|
185
|
+
};
|
|
186
|
+
const overallScore = Math.round(scores.metadata * 0.2 +
|
|
187
|
+
scores.indexability * 0.2 +
|
|
188
|
+
scores.structure * 0.15 +
|
|
189
|
+
scores.links * 0.1 +
|
|
190
|
+
scores.media * 0.1 +
|
|
191
|
+
scores.structuredData * 0.1 +
|
|
192
|
+
scores.performance * 0.15);
|
|
193
|
+
send('progress', { step: 'saving', message: 'Saving results to database...' });
|
|
194
|
+
const batchSize = 10;
|
|
195
|
+
for (let i = 0; i < pageResults.length; i += batchSize) {
|
|
196
|
+
const batch = pageResults.slice(i, i + batchSize);
|
|
197
|
+
await Promise.all(batch.map((result) => payload.create({
|
|
198
|
+
collection: 'seo-page-results',
|
|
199
|
+
data: {
|
|
200
|
+
snapshot: snapshot.id,
|
|
201
|
+
url: result.url,
|
|
202
|
+
path: result.path,
|
|
203
|
+
statusCode: result.statusCode,
|
|
204
|
+
title: result.check.title,
|
|
205
|
+
metaDescription: result.check.metaDescription,
|
|
206
|
+
canonical: result.check.canonical,
|
|
207
|
+
robotsMeta: result.check.robotsMeta,
|
|
208
|
+
h1Count: result.check.h1Count,
|
|
209
|
+
internalLinks: result.check.internalLinks,
|
|
210
|
+
externalLinks: result.check.externalLinks,
|
|
211
|
+
imagesTotal: result.check.imagesTotal,
|
|
212
|
+
imagesMissingAlt: result.check.imagesMissingAlt,
|
|
213
|
+
structuredDataBlocks: result.check.structuredDataBlocks,
|
|
214
|
+
headingOrderIssues: result.check.headingOrderIssues,
|
|
215
|
+
scoreBreakdown: result.score,
|
|
216
|
+
overallScore: Math.round(result.score.metadata * 0.2 +
|
|
217
|
+
result.score.indexability * 0.2 +
|
|
218
|
+
result.score.structure * 0.15 +
|
|
219
|
+
result.score.links * 0.1 +
|
|
220
|
+
result.score.media * 0.1 +
|
|
221
|
+
result.score.structuredData * 0.1 +
|
|
222
|
+
result.score.performance * 0.15),
|
|
223
|
+
issues: result.check.issues,
|
|
224
|
+
checkedAt: new Date().toISOString(),
|
|
225
|
+
},
|
|
226
|
+
overrideAccess: true,
|
|
227
|
+
})));
|
|
228
|
+
}
|
|
229
|
+
await payload.update({
|
|
230
|
+
collection: 'seo-snapshots',
|
|
231
|
+
id: snapshot.id,
|
|
232
|
+
data: {
|
|
233
|
+
status: 'completed',
|
|
234
|
+
completedAt: new Date().toISOString(),
|
|
235
|
+
scores: { ...scores, overall: overallScore },
|
|
236
|
+
metrics: {
|
|
237
|
+
pagesCrawled: crawl.pages.length,
|
|
238
|
+
pagesChecked: pageResults.length,
|
|
239
|
+
avgLighthousePerformance: pageSpeedSummary?.averagePerformanceScore,
|
|
240
|
+
avgLCPMs: pageSpeedSummary?.averageLCPMs,
|
|
241
|
+
avgCLS: pageSpeedSummary?.averageCLS,
|
|
242
|
+
},
|
|
243
|
+
issueCounts,
|
|
244
|
+
summary: summaryText,
|
|
245
|
+
},
|
|
246
|
+
overrideAccess: true,
|
|
247
|
+
});
|
|
248
|
+
send('complete', {
|
|
249
|
+
message: 'Audit complete!',
|
|
250
|
+
data: {
|
|
251
|
+
pagesChecked: pageResults.length,
|
|
252
|
+
overallScore,
|
|
253
|
+
snapshotId: snapshot.id,
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
controller.close();
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
send('error', {
|
|
260
|
+
message: error instanceof Error ? error.message : 'Failed to run SEO audit.',
|
|
261
|
+
});
|
|
262
|
+
controller.close();
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
return new Response(stream, {
|
|
267
|
+
headers: {
|
|
268
|
+
'Content-Type': 'text/event-stream',
|
|
269
|
+
'Cache-Control': 'no-cache',
|
|
270
|
+
Connection: 'keep-alive',
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/api/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAc5D,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CA4EhG"}
|
package/dist/api/run.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleSeoRun = handleSeoRun;
|
|
37
|
+
const auth_1 = require("../utilities/auth");
|
|
38
|
+
const runAudit_1 = require("../utilities/runAudit");
|
|
39
|
+
const index_1 = require("../index");
|
|
40
|
+
const resolveRunType = (value) => {
|
|
41
|
+
if (value === 'scheduled' || value === 'publish-triggered')
|
|
42
|
+
return value;
|
|
43
|
+
return 'manual';
|
|
44
|
+
};
|
|
45
|
+
async function handleSeoRun(payload, request) {
|
|
46
|
+
const { NextResponse } = await Promise.resolve().then(() => __importStar(require('next/server')));
|
|
47
|
+
try {
|
|
48
|
+
const [user, secretAuthorized] = await Promise.all([
|
|
49
|
+
(0, auth_1.authenticateSEOAdmin)(payload, request),
|
|
50
|
+
Promise.resolve((0, auth_1.isValidSEOSecret)(request)),
|
|
51
|
+
]);
|
|
52
|
+
if (!user && !secretAuthorized) {
|
|
53
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
54
|
+
}
|
|
55
|
+
const seoConfig = (0, index_1.getSeoConfig)(payload);
|
|
56
|
+
if (!seoConfig) {
|
|
57
|
+
return NextResponse.json({ error: 'SEO Audit plugin not configured' }, { status: 500 });
|
|
58
|
+
}
|
|
59
|
+
const body = (await request.json().catch(() => ({})));
|
|
60
|
+
const site = {
|
|
61
|
+
id: 1,
|
|
62
|
+
name: seoConfig.site.name,
|
|
63
|
+
domain: seoConfig.site.domain,
|
|
64
|
+
canonicalHost: seoConfig.site.canonicalHost,
|
|
65
|
+
sitemapURL: seoConfig.site.sitemapURL,
|
|
66
|
+
keyURLs: seoConfig.site.keyURLs.map(url => ({ url })),
|
|
67
|
+
crawlSettings: {
|
|
68
|
+
maxPages: seoConfig.crawl.maxPages,
|
|
69
|
+
maxDepth: seoConfig.crawl.maxDepth,
|
|
70
|
+
requestTimeoutMs: seoConfig.crawl.requestTimeoutMs,
|
|
71
|
+
includePatterns: seoConfig.crawl.includePatterns.map(pattern => ({ pattern })),
|
|
72
|
+
excludePatterns: seoConfig.crawl.excludePatterns.map(pattern => ({ pattern })),
|
|
73
|
+
},
|
|
74
|
+
integrations: {
|
|
75
|
+
enablePageSpeed: seoConfig.integrations.enablePageSpeed,
|
|
76
|
+
enableSearchConsole: seoConfig.integrations.enableSearchConsole,
|
|
77
|
+
},
|
|
78
|
+
thresholds: {
|
|
79
|
+
targetLCPMs: seoConfig.thresholds.targetLCPMs,
|
|
80
|
+
targetCLS: seoConfig.thresholds.targetCLS,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
const result = await (0, runAudit_1.runSEOSnapshot)({
|
|
84
|
+
payload,
|
|
85
|
+
site,
|
|
86
|
+
runType: resolveRunType(body.runType),
|
|
87
|
+
});
|
|
88
|
+
return NextResponse.json({
|
|
89
|
+
success: true,
|
|
90
|
+
snapshotID: result.snapshotID,
|
|
91
|
+
pagesChecked: result.pagesChecked,
|
|
92
|
+
overallScore: result.overallScore,
|
|
93
|
+
issueCounts: result.issueCounts,
|
|
94
|
+
status: 'completed',
|
|
95
|
+
completedAt: new Date().toISOString(),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
console.error('SEO run error:', error);
|
|
100
|
+
return NextResponse.json({ error: error instanceof Error ? error.message : 'Failed to run SEO audit.' }, { status: 500 });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-report.d.ts","sourceRoot":"","sources":["../../src/api/snapshot-report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAM5D,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,CAAC,CAuHvB"}
|