@consilioweb/payload-seo-analyzer 1.16.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/client.cjs +6 -2
- package/dist/client.js +6 -2
- package/dist/index.cjs +6 -3
- package/dist/index.js +6 -3
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -724,10 +724,12 @@ The site-wide audit (`/admin/seo` dashboard) is the heaviest operation. On const
|
|
|
724
724
|
|
|
725
725
|
| Env var | Default | Purpose |
|
|
726
726
|
|---|---|---|
|
|
727
|
-
| `SEO_AUDIT_BATCH_SIZE` | `
|
|
727
|
+
| `SEO_AUDIT_BATCH_SIZE` | `10` | Documents processed per batch. Lower it on very small hosts. |
|
|
728
|
+
| `SEO_AUDIT_BATCH_DELAY_MS` | `100` | **Pause between batches** — throttles CPU so the build never saturates the site. Raise it (e.g. `300`) on the tiniest shared hosts; lower it (`0`) for speed on a beefy server. |
|
|
729
|
+
| `SEO_AUDIT_DEPTH` | `1` | Relationship depth when loading docs. Set `0` to cut memory/CPU (image-dimension sub-checks then see IDs, a minor score difference). |
|
|
728
730
|
| `SEO_AUDIT_MAX_DOCS` | `1500` | Hard cap on documents audited. |
|
|
729
731
|
|
|
730
|
-
For the lowest-memory tiers you can also set `features: { warmCache: false }` to skip the startup/hourly pre-load entirely.
|
|
732
|
+
The audit runs **single-flight in the background and throttled** — a constrained host (Infomaniak) stays responsive while it builds, then the dashboard polls until ready. If it still feels heavy, raise `SEO_AUDIT_BATCH_DELAY_MS` and/or set `SEO_AUDIT_DEPTH=0`. For the lowest-memory tiers you can also set `features: { warmCache: false }` to skip the startup/hourly pre-load entirely.
|
|
731
733
|
|
|
732
734
|
<img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
|
|
733
735
|
|
package/dist/client.cjs
CHANGED
|
@@ -17135,6 +17135,10 @@ function GscPanel({ locale }) {
|
|
|
17135
17135
|
setError(null);
|
|
17136
17136
|
try {
|
|
17137
17137
|
const res = await fetch("/api/seo-plugin/gsc/status", { credentials: "include" });
|
|
17138
|
+
if (res.status === 404) {
|
|
17139
|
+
setStatus({ configured: false, connected: false, connectedEmail: null, connectedAt: null, propertyUrl: null, redirectUri: null });
|
|
17140
|
+
return;
|
|
17141
|
+
}
|
|
17138
17142
|
const json = await res.json();
|
|
17139
17143
|
if (!res.ok) setError(json.error || `Error ${res.status}`);
|
|
17140
17144
|
else setStatus(json);
|
|
@@ -17340,7 +17344,7 @@ function RankTrackingPanel({ locale }) {
|
|
|
17340
17344
|
setError(null);
|
|
17341
17345
|
try {
|
|
17342
17346
|
const res = await fetch("/api/seo-plugin/rank-history", { credentials: "include", cache: "no-store" });
|
|
17343
|
-
if (res.status === 403 || res.status === 409) {
|
|
17347
|
+
if (res.status === 404 || res.status === 403 || res.status === 409) {
|
|
17344
17348
|
setNotConnected(true);
|
|
17345
17349
|
setMovers(null);
|
|
17346
17350
|
return;
|
|
@@ -17517,7 +17521,7 @@ function CtrOpportunitiesPanel({ locale }) {
|
|
|
17517
17521
|
setError(null);
|
|
17518
17522
|
try {
|
|
17519
17523
|
const res = await fetch("/api/seo-plugin/ctr-opportunities", { credentials: "include", cache: "no-store" });
|
|
17520
|
-
if (res.status === 403 || res.status === 409 || res.status === 400) {
|
|
17524
|
+
if (res.status === 404 || res.status === 403 || res.status === 409 || res.status === 400) {
|
|
17521
17525
|
setNotConnected(true);
|
|
17522
17526
|
return;
|
|
17523
17527
|
}
|
package/dist/client.js
CHANGED
|
@@ -17129,6 +17129,10 @@ function GscPanel({ locale }) {
|
|
|
17129
17129
|
setError(null);
|
|
17130
17130
|
try {
|
|
17131
17131
|
const res = await fetch("/api/seo-plugin/gsc/status", { credentials: "include" });
|
|
17132
|
+
if (res.status === 404) {
|
|
17133
|
+
setStatus({ configured: false, connected: false, connectedEmail: null, connectedAt: null, propertyUrl: null, redirectUri: null });
|
|
17134
|
+
return;
|
|
17135
|
+
}
|
|
17132
17136
|
const json = await res.json();
|
|
17133
17137
|
if (!res.ok) setError(json.error || `Error ${res.status}`);
|
|
17134
17138
|
else setStatus(json);
|
|
@@ -17334,7 +17338,7 @@ function RankTrackingPanel({ locale }) {
|
|
|
17334
17338
|
setError(null);
|
|
17335
17339
|
try {
|
|
17336
17340
|
const res = await fetch("/api/seo-plugin/rank-history", { credentials: "include", cache: "no-store" });
|
|
17337
|
-
if (res.status === 403 || res.status === 409) {
|
|
17341
|
+
if (res.status === 404 || res.status === 403 || res.status === 409) {
|
|
17338
17342
|
setNotConnected(true);
|
|
17339
17343
|
setMovers(null);
|
|
17340
17344
|
return;
|
|
@@ -17511,7 +17515,7 @@ function CtrOpportunitiesPanel({ locale }) {
|
|
|
17511
17515
|
setError(null);
|
|
17512
17516
|
try {
|
|
17513
17517
|
const res = await fetch("/api/seo-plugin/ctr-opportunities", { credentials: "include", cache: "no-store" });
|
|
17514
|
-
if (res.status === 403 || res.status === 409 || res.status === 400) {
|
|
17518
|
+
if (res.status === 404 || res.status === 403 || res.status === 409 || res.status === 400) {
|
|
17515
17519
|
setNotConnected(true);
|
|
17516
17520
|
return;
|
|
17517
17521
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1686,8 +1686,11 @@ var CACHE_KEY = "audit";
|
|
|
1686
1686
|
var auditBuildsInFlight = /* @__PURE__ */ new Set();
|
|
1687
1687
|
async function buildAuditCache(payload, collections, globals, seoConfig, reqLocale) {
|
|
1688
1688
|
const { config: mergedConfig, ignoredSlugs } = await loadMergedConfig(payload, seoConfig, { reqLocale });
|
|
1689
|
-
const BATCH_SIZE = Math.min(100, Math.max(1, parseInt(process.env.SEO_AUDIT_BATCH_SIZE || "
|
|
1689
|
+
const BATCH_SIZE = Math.min(100, Math.max(1, parseInt(process.env.SEO_AUDIT_BATCH_SIZE || "10", 10) || 10));
|
|
1690
1690
|
const MAX_DOCS2 = Math.max(1, parseInt(process.env.SEO_AUDIT_MAX_DOCS || "1500", 10) || 1500);
|
|
1691
|
+
const BATCH_DELAY_MS = Math.min(5e3, Math.max(0, parseInt(process.env.SEO_AUDIT_BATCH_DELAY_MS || "100", 10) || 0));
|
|
1692
|
+
const rawDepth = parseInt(process.env.SEO_AUDIT_DEPTH ?? "1", 10);
|
|
1693
|
+
const DEPTH = Number.isNaN(rawDepth) ? 1 : Math.min(2, Math.max(0, rawDepth));
|
|
1691
1694
|
const allResults = [];
|
|
1692
1695
|
let capped = false;
|
|
1693
1696
|
collectionsLoop:
|
|
@@ -1700,7 +1703,7 @@ async function buildAuditCache(payload, collections, globals, seoConfig, reqLoca
|
|
|
1700
1703
|
collection: collectionSlug,
|
|
1701
1704
|
limit: BATCH_SIZE,
|
|
1702
1705
|
page,
|
|
1703
|
-
depth:
|
|
1706
|
+
depth: DEPTH,
|
|
1704
1707
|
overrideAccess: true
|
|
1705
1708
|
});
|
|
1706
1709
|
for (const doc of result.docs) {
|
|
@@ -1720,7 +1723,7 @@ async function buildAuditCache(payload, collections, globals, seoConfig, reqLoca
|
|
|
1720
1723
|
}
|
|
1721
1724
|
hasMore = result.hasNextPage;
|
|
1722
1725
|
page++;
|
|
1723
|
-
await new Promise((resolve) =>
|
|
1726
|
+
await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY_MS));
|
|
1724
1727
|
}
|
|
1725
1728
|
} catch {
|
|
1726
1729
|
}
|
package/dist/index.js
CHANGED
|
@@ -1684,8 +1684,11 @@ var CACHE_KEY = "audit";
|
|
|
1684
1684
|
var auditBuildsInFlight = /* @__PURE__ */ new Set();
|
|
1685
1685
|
async function buildAuditCache(payload, collections, globals, seoConfig, reqLocale) {
|
|
1686
1686
|
const { config: mergedConfig, ignoredSlugs } = await loadMergedConfig(payload, seoConfig, { reqLocale });
|
|
1687
|
-
const BATCH_SIZE = Math.min(100, Math.max(1, parseInt(process.env.SEO_AUDIT_BATCH_SIZE || "
|
|
1687
|
+
const BATCH_SIZE = Math.min(100, Math.max(1, parseInt(process.env.SEO_AUDIT_BATCH_SIZE || "10", 10) || 10));
|
|
1688
1688
|
const MAX_DOCS2 = Math.max(1, parseInt(process.env.SEO_AUDIT_MAX_DOCS || "1500", 10) || 1500);
|
|
1689
|
+
const BATCH_DELAY_MS = Math.min(5e3, Math.max(0, parseInt(process.env.SEO_AUDIT_BATCH_DELAY_MS || "100", 10) || 0));
|
|
1690
|
+
const rawDepth = parseInt(process.env.SEO_AUDIT_DEPTH ?? "1", 10);
|
|
1691
|
+
const DEPTH = Number.isNaN(rawDepth) ? 1 : Math.min(2, Math.max(0, rawDepth));
|
|
1689
1692
|
const allResults = [];
|
|
1690
1693
|
let capped = false;
|
|
1691
1694
|
collectionsLoop:
|
|
@@ -1698,7 +1701,7 @@ async function buildAuditCache(payload, collections, globals, seoConfig, reqLoca
|
|
|
1698
1701
|
collection: collectionSlug,
|
|
1699
1702
|
limit: BATCH_SIZE,
|
|
1700
1703
|
page,
|
|
1701
|
-
depth:
|
|
1704
|
+
depth: DEPTH,
|
|
1702
1705
|
overrideAccess: true
|
|
1703
1706
|
});
|
|
1704
1707
|
for (const doc of result.docs) {
|
|
@@ -1718,7 +1721,7 @@ async function buildAuditCache(payload, collections, globals, seoConfig, reqLoca
|
|
|
1718
1721
|
}
|
|
1719
1722
|
hasMore = result.hasNextPage;
|
|
1720
1723
|
page++;
|
|
1721
|
-
await new Promise((resolve) =>
|
|
1724
|
+
await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY_MS));
|
|
1722
1725
|
}
|
|
1723
1726
|
} catch {
|
|
1724
1727
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@consilioweb/payload-seo-analyzer",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.1",
|
|
4
4
|
"description": "Payload CMS SEO plugin — 50+ checks, dashboard, Lexical JSON support, Flesch FR/EN readability, i18n",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -114,7 +114,11 @@
|
|
|
114
114
|
"node": ">=18"
|
|
115
115
|
},
|
|
116
116
|
"devDependencies": {
|
|
117
|
+
"@testing-library/react": "^16.3.2",
|
|
117
118
|
"@types/react": "^19.0.0",
|
|
119
|
+
"jsdom": "^29.1.1",
|
|
120
|
+
"react": "^19.2.7",
|
|
121
|
+
"react-dom": "^19.2.7",
|
|
118
122
|
"tsup": "^8.0.0",
|
|
119
123
|
"typescript": "^5.5.0",
|
|
120
124
|
"vitest": "^2.0.0"
|