@consilioweb/payload-seo-analyzer 1.16.0 → 1.17.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 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` | `15` | Documents processed per batch. Lower it on very small hosts. |
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/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 || "15", 10) || 15));
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: 1,
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) => setImmediate(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 || "15", 10) || 15));
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: 1,
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) => setImmediate(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.16.0",
3
+ "version": "1.17.0",
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",