@consilioweb/payload-seo-analyzer 1.13.0 → 1.14.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/dist/client.cjs +27 -5
- package/dist/client.js +27 -5
- package/dist/index.cjs +19 -13
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +19 -13
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -1068,6 +1068,8 @@ var fr = {
|
|
|
1068
1068
|
bulkOptimizeMeta: "Optimiser m\xE9ta (IA)",
|
|
1069
1069
|
bulkOptimizing: "Analyse\u2026",
|
|
1070
1070
|
bulkConfirm: "Confirmer ?",
|
|
1071
|
+
optimizeSite: "Optimiser le site",
|
|
1072
|
+
optimizeSiteHint: "Cible automatiquement les pages \xE0 probl\xE8me (m\xE9ta manquante, sans mot-cl\xE9, score faible) \u2192 aper\xE7u \u2192 appliquer",
|
|
1071
1073
|
bulkPreviewTitle: "Corrections m\xE9ta propos\xE9es",
|
|
1072
1074
|
bulkApply: "Appliquer",
|
|
1073
1075
|
bulkApplying: "Application\u2026",
|
|
@@ -1670,6 +1672,8 @@ var en = {
|
|
|
1670
1672
|
bulkOptimizeMeta: "Optimize meta (AI)",
|
|
1671
1673
|
bulkOptimizing: "Analyzing\u2026",
|
|
1672
1674
|
bulkConfirm: "Confirm?",
|
|
1675
|
+
optimizeSite: "Optimize site",
|
|
1676
|
+
optimizeSiteHint: "Auto-targets pages that need work (missing meta, no keyword, low score) \u2192 preview \u2192 apply",
|
|
1673
1677
|
bulkPreviewTitle: "Proposed meta corrections",
|
|
1674
1678
|
bulkApply: "Apply",
|
|
1675
1679
|
bulkApplying: "Applying\u2026",
|
|
@@ -9544,9 +9548,9 @@ function SeoView() {
|
|
|
9544
9548
|
},
|
|
9545
9549
|
[selectedIds, fetchAudit]
|
|
9546
9550
|
);
|
|
9547
|
-
const
|
|
9548
|
-
const
|
|
9549
|
-
if (
|
|
9551
|
+
const runBulkPreview = React4.useCallback(async (ids) => {
|
|
9552
|
+
const clean = ids.filter((k) => !k.startsWith("global:"));
|
|
9553
|
+
if (clean.length === 0) return;
|
|
9550
9554
|
setBulkOptimizing(true);
|
|
9551
9555
|
setBulkPreview(null);
|
|
9552
9556
|
try {
|
|
@@ -9554,7 +9558,7 @@ function SeoView() {
|
|
|
9554
9558
|
method: "POST",
|
|
9555
9559
|
headers: { "Content-Type": "application/json" },
|
|
9556
9560
|
credentials: "include",
|
|
9557
|
-
body: JSON.stringify({ ids, apply: false, limit: 100 })
|
|
9561
|
+
body: JSON.stringify({ ids: clean, apply: false, limit: 100 })
|
|
9558
9562
|
});
|
|
9559
9563
|
if (res.ok) {
|
|
9560
9564
|
const data = await res.json();
|
|
@@ -9564,7 +9568,15 @@ function SeoView() {
|
|
|
9564
9568
|
} catch {
|
|
9565
9569
|
}
|
|
9566
9570
|
setBulkOptimizing(false);
|
|
9567
|
-
}, [
|
|
9571
|
+
}, []);
|
|
9572
|
+
const handleBulkOptimizeMeta = React4.useCallback(
|
|
9573
|
+
() => runBulkPreview(Array.from(selectedIds)),
|
|
9574
|
+
[selectedIds, runBulkPreview]
|
|
9575
|
+
);
|
|
9576
|
+
const handleOptimizeSite = React4.useCallback(() => {
|
|
9577
|
+
const targets = items.filter((i) => !i.collection.startsWith("global:")).filter((i) => !i.metaTitle || !i.metaDescription || !i.focusKeyword || i.score < 70).slice(0, 100).map(itemKey);
|
|
9578
|
+
runBulkPreview(targets);
|
|
9579
|
+
}, [items, runBulkPreview]);
|
|
9568
9580
|
const handleBulkApplyPreview = React4.useCallback(async () => {
|
|
9569
9581
|
if (!bulkPreview || bulkPreview.results.length === 0) return;
|
|
9570
9582
|
setBulkApplying(true);
|
|
@@ -9931,6 +9943,16 @@ function SeoView() {
|
|
|
9931
9943
|
] })
|
|
9932
9944
|
] }),
|
|
9933
9945
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 8 }, children: [
|
|
9946
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9947
|
+
"button",
|
|
9948
|
+
{
|
|
9949
|
+
onClick: handleOptimizeSite,
|
|
9950
|
+
disabled: bulkOptimizing || items.length === 0,
|
|
9951
|
+
title: t.seoView.optimizeSiteHint,
|
|
9952
|
+
style: { ...btnBase, backgroundColor: "#7c3aed", color: "#fff", opacity: bulkOptimizing || items.length === 0 ? 0.6 : 1 },
|
|
9953
|
+
children: bulkOptimizing ? t.seoView.bulkOptimizing : `\u2728 ${t.seoView.optimizeSite}`
|
|
9954
|
+
}
|
|
9955
|
+
),
|
|
9934
9956
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9935
9957
|
"button",
|
|
9936
9958
|
{
|
package/dist/client.js
CHANGED
|
@@ -1062,6 +1062,8 @@ var fr = {
|
|
|
1062
1062
|
bulkOptimizeMeta: "Optimiser m\xE9ta (IA)",
|
|
1063
1063
|
bulkOptimizing: "Analyse\u2026",
|
|
1064
1064
|
bulkConfirm: "Confirmer ?",
|
|
1065
|
+
optimizeSite: "Optimiser le site",
|
|
1066
|
+
optimizeSiteHint: "Cible automatiquement les pages \xE0 probl\xE8me (m\xE9ta manquante, sans mot-cl\xE9, score faible) \u2192 aper\xE7u \u2192 appliquer",
|
|
1065
1067
|
bulkPreviewTitle: "Corrections m\xE9ta propos\xE9es",
|
|
1066
1068
|
bulkApply: "Appliquer",
|
|
1067
1069
|
bulkApplying: "Application\u2026",
|
|
@@ -1664,6 +1666,8 @@ var en = {
|
|
|
1664
1666
|
bulkOptimizeMeta: "Optimize meta (AI)",
|
|
1665
1667
|
bulkOptimizing: "Analyzing\u2026",
|
|
1666
1668
|
bulkConfirm: "Confirm?",
|
|
1669
|
+
optimizeSite: "Optimize site",
|
|
1670
|
+
optimizeSiteHint: "Auto-targets pages that need work (missing meta, no keyword, low score) \u2192 preview \u2192 apply",
|
|
1667
1671
|
bulkPreviewTitle: "Proposed meta corrections",
|
|
1668
1672
|
bulkApply: "Apply",
|
|
1669
1673
|
bulkApplying: "Applying\u2026",
|
|
@@ -9538,9 +9542,9 @@ function SeoView() {
|
|
|
9538
9542
|
},
|
|
9539
9543
|
[selectedIds, fetchAudit]
|
|
9540
9544
|
);
|
|
9541
|
-
const
|
|
9542
|
-
const
|
|
9543
|
-
if (
|
|
9545
|
+
const runBulkPreview = useCallback(async (ids) => {
|
|
9546
|
+
const clean = ids.filter((k) => !k.startsWith("global:"));
|
|
9547
|
+
if (clean.length === 0) return;
|
|
9544
9548
|
setBulkOptimizing(true);
|
|
9545
9549
|
setBulkPreview(null);
|
|
9546
9550
|
try {
|
|
@@ -9548,7 +9552,7 @@ function SeoView() {
|
|
|
9548
9552
|
method: "POST",
|
|
9549
9553
|
headers: { "Content-Type": "application/json" },
|
|
9550
9554
|
credentials: "include",
|
|
9551
|
-
body: JSON.stringify({ ids, apply: false, limit: 100 })
|
|
9555
|
+
body: JSON.stringify({ ids: clean, apply: false, limit: 100 })
|
|
9552
9556
|
});
|
|
9553
9557
|
if (res.ok) {
|
|
9554
9558
|
const data = await res.json();
|
|
@@ -9558,7 +9562,15 @@ function SeoView() {
|
|
|
9558
9562
|
} catch {
|
|
9559
9563
|
}
|
|
9560
9564
|
setBulkOptimizing(false);
|
|
9561
|
-
}, [
|
|
9565
|
+
}, []);
|
|
9566
|
+
const handleBulkOptimizeMeta = useCallback(
|
|
9567
|
+
() => runBulkPreview(Array.from(selectedIds)),
|
|
9568
|
+
[selectedIds, runBulkPreview]
|
|
9569
|
+
);
|
|
9570
|
+
const handleOptimizeSite = useCallback(() => {
|
|
9571
|
+
const targets = items.filter((i) => !i.collection.startsWith("global:")).filter((i) => !i.metaTitle || !i.metaDescription || !i.focusKeyword || i.score < 70).slice(0, 100).map(itemKey);
|
|
9572
|
+
runBulkPreview(targets);
|
|
9573
|
+
}, [items, runBulkPreview]);
|
|
9562
9574
|
const handleBulkApplyPreview = useCallback(async () => {
|
|
9563
9575
|
if (!bulkPreview || bulkPreview.results.length === 0) return;
|
|
9564
9576
|
setBulkApplying(true);
|
|
@@ -9925,6 +9937,16 @@ function SeoView() {
|
|
|
9925
9937
|
] })
|
|
9926
9938
|
] }),
|
|
9927
9939
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8 }, children: [
|
|
9940
|
+
/* @__PURE__ */ jsx(
|
|
9941
|
+
"button",
|
|
9942
|
+
{
|
|
9943
|
+
onClick: handleOptimizeSite,
|
|
9944
|
+
disabled: bulkOptimizing || items.length === 0,
|
|
9945
|
+
title: t.seoView.optimizeSiteHint,
|
|
9946
|
+
style: { ...btnBase, backgroundColor: "#7c3aed", color: "#fff", opacity: bulkOptimizing || items.length === 0 ? 0.6 : 1 },
|
|
9947
|
+
children: bulkOptimizing ? t.seoView.bulkOptimizing : `\u2728 ${t.seoView.optimizeSite}`
|
|
9948
|
+
}
|
|
9949
|
+
),
|
|
9928
9950
|
/* @__PURE__ */ jsxs(
|
|
9929
9951
|
"button",
|
|
9930
9952
|
{
|
package/dist/index.cjs
CHANGED
|
@@ -1683,9 +1683,9 @@ function analyzeDoc(doc, collection, seoConfig) {
|
|
|
1683
1683
|
};
|
|
1684
1684
|
}
|
|
1685
1685
|
var CACHE_KEY = "audit";
|
|
1686
|
-
var
|
|
1687
|
-
async function buildAuditCache(payload, collections, globals, seoConfig) {
|
|
1688
|
-
const { config: mergedConfig, ignoredSlugs } = await loadMergedConfig(payload, seoConfig);
|
|
1686
|
+
var auditBuildsInFlight = /* @__PURE__ */ new Set();
|
|
1687
|
+
async function buildAuditCache(payload, collections, globals, seoConfig, reqLocale) {
|
|
1688
|
+
const { config: mergedConfig, ignoredSlugs } = await loadMergedConfig(payload, seoConfig, { reqLocale });
|
|
1689
1689
|
const BATCH_SIZE = Math.min(100, Math.max(1, parseInt(process.env.SEO_AUDIT_BATCH_SIZE || "15", 10) || 15));
|
|
1690
1690
|
const MAX_DOCS2 = Math.max(1, parseInt(process.env.SEO_AUDIT_MAX_DOCS || "1500", 10) || 1500);
|
|
1691
1691
|
const allResults = [];
|
|
@@ -1793,15 +1793,15 @@ async function buildAuditCache(payload, collections, globals, seoConfig) {
|
|
|
1793
1793
|
};
|
|
1794
1794
|
return { enrichedResults, stats, capped };
|
|
1795
1795
|
}
|
|
1796
|
-
function ensureAuditBuild(payload, collections, globals, seoConfig) {
|
|
1797
|
-
if (
|
|
1798
|
-
|
|
1799
|
-
void buildAuditCache(payload, collections, globals, seoConfig).then((result) => {
|
|
1800
|
-
seoCache.set(
|
|
1796
|
+
function ensureAuditBuild(payload, collections, globals, seoConfig, cacheKey, reqLocale) {
|
|
1797
|
+
if (auditBuildsInFlight.has(cacheKey)) return;
|
|
1798
|
+
auditBuildsInFlight.add(cacheKey);
|
|
1799
|
+
void buildAuditCache(payload, collections, globals, seoConfig, reqLocale).then((result) => {
|
|
1800
|
+
seoCache.set(cacheKey, result);
|
|
1801
1801
|
}).catch((e) => {
|
|
1802
1802
|
payload.logger.error(`[seo] audit build failed: ${e instanceof Error ? e.message : "unknown"}`);
|
|
1803
1803
|
}).finally(() => {
|
|
1804
|
-
|
|
1804
|
+
auditBuildsInFlight.delete(cacheKey);
|
|
1805
1805
|
});
|
|
1806
1806
|
}
|
|
1807
1807
|
function createAuditHandler(collections, seoConfig, globals = []) {
|
|
@@ -1814,12 +1814,14 @@ function createAuditHandler(collections, seoConfig, globals = []) {
|
|
|
1814
1814
|
const page = Math.max(1, parseInt(url.searchParams.get("page") || "1", 10));
|
|
1815
1815
|
const limit = Math.min(500, Math.max(1, parseInt(url.searchParams.get("limit") || "300", 10)));
|
|
1816
1816
|
const noCache = url.searchParams.get("nocache") === "1";
|
|
1817
|
-
|
|
1818
|
-
|
|
1817
|
+
const reqLocale = typeof req.locale === "string" && req.locale ? req.locale : void 0;
|
|
1818
|
+
const cacheKey = reqLocale ? `${CACHE_KEY}:${reqLocale}` : CACHE_KEY;
|
|
1819
|
+
if (noCache && !auditBuildsInFlight.has(cacheKey)) {
|
|
1820
|
+
seoCache.invalidateKey(cacheKey);
|
|
1819
1821
|
}
|
|
1820
|
-
const cached = seoCache.get(
|
|
1822
|
+
const cached = seoCache.get(cacheKey);
|
|
1821
1823
|
if (!cached) {
|
|
1822
|
-
ensureAuditBuild(req.payload, collections, globals, seoConfig);
|
|
1824
|
+
ensureAuditBuild(req.payload, collections, globals, seoConfig, cacheKey, reqLocale);
|
|
1823
1825
|
return Response.json(
|
|
1824
1826
|
{ building: true, results: [], stats: null },
|
|
1825
1827
|
{ status: 202, headers: { "Cache-Control": "no-store" } }
|
|
@@ -9154,6 +9156,8 @@ var fr = {
|
|
|
9154
9156
|
bulkOptimizeMeta: "Optimiser m\xE9ta (IA)",
|
|
9155
9157
|
bulkOptimizing: "Analyse\u2026",
|
|
9156
9158
|
bulkConfirm: "Confirmer ?",
|
|
9159
|
+
optimizeSite: "Optimiser le site",
|
|
9160
|
+
optimizeSiteHint: "Cible automatiquement les pages \xE0 probl\xE8me (m\xE9ta manquante, sans mot-cl\xE9, score faible) \u2192 aper\xE7u \u2192 appliquer",
|
|
9157
9161
|
bulkPreviewTitle: "Corrections m\xE9ta propos\xE9es",
|
|
9158
9162
|
bulkApply: "Appliquer",
|
|
9159
9163
|
bulkApplying: "Application\u2026",
|
|
@@ -9756,6 +9760,8 @@ var en = {
|
|
|
9756
9760
|
bulkOptimizeMeta: "Optimize meta (AI)",
|
|
9757
9761
|
bulkOptimizing: "Analyzing\u2026",
|
|
9758
9762
|
bulkConfirm: "Confirm?",
|
|
9763
|
+
optimizeSite: "Optimize site",
|
|
9764
|
+
optimizeSiteHint: "Auto-targets pages that need work (missing meta, no keyword, low score) \u2192 preview \u2192 apply",
|
|
9759
9765
|
bulkPreviewTitle: "Proposed meta corrections",
|
|
9760
9766
|
bulkApply: "Apply",
|
|
9761
9767
|
bulkApplying: "Applying\u2026",
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1681,9 +1681,9 @@ function analyzeDoc(doc, collection, seoConfig) {
|
|
|
1681
1681
|
};
|
|
1682
1682
|
}
|
|
1683
1683
|
var CACHE_KEY = "audit";
|
|
1684
|
-
var
|
|
1685
|
-
async function buildAuditCache(payload, collections, globals, seoConfig) {
|
|
1686
|
-
const { config: mergedConfig, ignoredSlugs } = await loadMergedConfig(payload, seoConfig);
|
|
1684
|
+
var auditBuildsInFlight = /* @__PURE__ */ new Set();
|
|
1685
|
+
async function buildAuditCache(payload, collections, globals, seoConfig, reqLocale) {
|
|
1686
|
+
const { config: mergedConfig, ignoredSlugs } = await loadMergedConfig(payload, seoConfig, { reqLocale });
|
|
1687
1687
|
const BATCH_SIZE = Math.min(100, Math.max(1, parseInt(process.env.SEO_AUDIT_BATCH_SIZE || "15", 10) || 15));
|
|
1688
1688
|
const MAX_DOCS2 = Math.max(1, parseInt(process.env.SEO_AUDIT_MAX_DOCS || "1500", 10) || 1500);
|
|
1689
1689
|
const allResults = [];
|
|
@@ -1791,15 +1791,15 @@ async function buildAuditCache(payload, collections, globals, seoConfig) {
|
|
|
1791
1791
|
};
|
|
1792
1792
|
return { enrichedResults, stats, capped };
|
|
1793
1793
|
}
|
|
1794
|
-
function ensureAuditBuild(payload, collections, globals, seoConfig) {
|
|
1795
|
-
if (
|
|
1796
|
-
|
|
1797
|
-
void buildAuditCache(payload, collections, globals, seoConfig).then((result) => {
|
|
1798
|
-
seoCache.set(
|
|
1794
|
+
function ensureAuditBuild(payload, collections, globals, seoConfig, cacheKey, reqLocale) {
|
|
1795
|
+
if (auditBuildsInFlight.has(cacheKey)) return;
|
|
1796
|
+
auditBuildsInFlight.add(cacheKey);
|
|
1797
|
+
void buildAuditCache(payload, collections, globals, seoConfig, reqLocale).then((result) => {
|
|
1798
|
+
seoCache.set(cacheKey, result);
|
|
1799
1799
|
}).catch((e) => {
|
|
1800
1800
|
payload.logger.error(`[seo] audit build failed: ${e instanceof Error ? e.message : "unknown"}`);
|
|
1801
1801
|
}).finally(() => {
|
|
1802
|
-
|
|
1802
|
+
auditBuildsInFlight.delete(cacheKey);
|
|
1803
1803
|
});
|
|
1804
1804
|
}
|
|
1805
1805
|
function createAuditHandler(collections, seoConfig, globals = []) {
|
|
@@ -1812,12 +1812,14 @@ function createAuditHandler(collections, seoConfig, globals = []) {
|
|
|
1812
1812
|
const page = Math.max(1, parseInt(url.searchParams.get("page") || "1", 10));
|
|
1813
1813
|
const limit = Math.min(500, Math.max(1, parseInt(url.searchParams.get("limit") || "300", 10)));
|
|
1814
1814
|
const noCache = url.searchParams.get("nocache") === "1";
|
|
1815
|
-
|
|
1816
|
-
|
|
1815
|
+
const reqLocale = typeof req.locale === "string" && req.locale ? req.locale : void 0;
|
|
1816
|
+
const cacheKey = reqLocale ? `${CACHE_KEY}:${reqLocale}` : CACHE_KEY;
|
|
1817
|
+
if (noCache && !auditBuildsInFlight.has(cacheKey)) {
|
|
1818
|
+
seoCache.invalidateKey(cacheKey);
|
|
1817
1819
|
}
|
|
1818
|
-
const cached = seoCache.get(
|
|
1820
|
+
const cached = seoCache.get(cacheKey);
|
|
1819
1821
|
if (!cached) {
|
|
1820
|
-
ensureAuditBuild(req.payload, collections, globals, seoConfig);
|
|
1822
|
+
ensureAuditBuild(req.payload, collections, globals, seoConfig, cacheKey, reqLocale);
|
|
1821
1823
|
return Response.json(
|
|
1822
1824
|
{ building: true, results: [], stats: null },
|
|
1823
1825
|
{ status: 202, headers: { "Cache-Control": "no-store" } }
|
|
@@ -9152,6 +9154,8 @@ var fr = {
|
|
|
9152
9154
|
bulkOptimizeMeta: "Optimiser m\xE9ta (IA)",
|
|
9153
9155
|
bulkOptimizing: "Analyse\u2026",
|
|
9154
9156
|
bulkConfirm: "Confirmer ?",
|
|
9157
|
+
optimizeSite: "Optimiser le site",
|
|
9158
|
+
optimizeSiteHint: "Cible automatiquement les pages \xE0 probl\xE8me (m\xE9ta manquante, sans mot-cl\xE9, score faible) \u2192 aper\xE7u \u2192 appliquer",
|
|
9155
9159
|
bulkPreviewTitle: "Corrections m\xE9ta propos\xE9es",
|
|
9156
9160
|
bulkApply: "Appliquer",
|
|
9157
9161
|
bulkApplying: "Application\u2026",
|
|
@@ -9754,6 +9758,8 @@ var en = {
|
|
|
9754
9758
|
bulkOptimizeMeta: "Optimize meta (AI)",
|
|
9755
9759
|
bulkOptimizing: "Analyzing\u2026",
|
|
9756
9760
|
bulkConfirm: "Confirm?",
|
|
9761
|
+
optimizeSite: "Optimize site",
|
|
9762
|
+
optimizeSiteHint: "Auto-targets pages that need work (missing meta, no keyword, low score) \u2192 preview \u2192 apply",
|
|
9757
9763
|
bulkPreviewTitle: "Proposed meta corrections",
|
|
9758
9764
|
bulkApply: "Apply",
|
|
9759
9765
|
bulkApplying: "Applying\u2026",
|
package/package.json
CHANGED