@consilioweb/payload-seo-analyzer 1.17.1 → 1.17.3

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 CHANGED
@@ -1077,6 +1077,7 @@ var fr = {
1077
1077
  bulkExport: "Exporter CSV",
1078
1078
  bulkNoChanges: "Aucune correction n\xE9cessaire sur la s\xE9lection.",
1079
1079
  bulkCappedNote: "limite atteinte (affine la s\xE9lection)",
1080
+ bulkAppliedNote: "\u2713 Corrections appliqu\xE9es. Rafra\xEEchis pour recalculer les scores (une seule fois, apr\xE8s tes lots).",
1080
1081
  searchPlaceholder: "Rechercher (titre, slug, keyword)...",
1081
1082
  allCollections: "Toutes les collections",
1082
1083
  allScores: "Tous les scores",
@@ -1681,6 +1682,7 @@ var en = {
1681
1682
  bulkExport: "Export CSV",
1682
1683
  bulkNoChanges: "No corrections needed on the selection.",
1683
1684
  bulkCappedNote: "limit reached (narrow the selection)",
1685
+ bulkAppliedNote: "\u2713 Corrections applied. Refresh to recompute scores (once, after your batches).",
1684
1686
  searchPlaceholder: "Search (title, slug, keyword)...",
1685
1687
  allCollections: "All collections",
1686
1688
  allScores: "All scores",
@@ -9327,6 +9329,7 @@ function SeoView() {
9327
9329
  const [saveError, setSaveError] = React4.useState(null);
9328
9330
  const [bulkOptimizing, setBulkOptimizing] = React4.useState(false);
9329
9331
  const [bulkApplying, setBulkApplying] = React4.useState(false);
9332
+ const [bulkApplied, setBulkApplied] = React4.useState(false);
9330
9333
  const [bulkPreview, setBulkPreview] = React4.useState(null);
9331
9334
  const PAGE_SIZE = 50;
9332
9335
  const fetchAudit = React4.useCallback(async (forceRefresh = false) => {
@@ -9599,8 +9602,8 @@ function SeoView() {
9599
9602
  setBulkApplying(false);
9600
9603
  setBulkPreview(null);
9601
9604
  setSelectedIds(/* @__PURE__ */ new Set());
9602
- fetchAudit();
9603
- }, [bulkPreview, fetchAudit]);
9605
+ setBulkApplied(true);
9606
+ }, [bulkPreview]);
9604
9607
  const handleExportBulkPreviewCsv = React4.useCallback(() => {
9605
9608
  if (!bulkPreview) return;
9606
9609
  const header = [
@@ -9984,6 +9987,41 @@ function SeoView() {
9984
9987
  ]
9985
9988
  }
9986
9989
  ),
9990
+ bulkApplied && /* @__PURE__ */ jsxRuntime.jsxs(
9991
+ "div",
9992
+ {
9993
+ style: {
9994
+ marginBottom: 16,
9995
+ padding: "10px 14px",
9996
+ borderRadius: 8,
9997
+ border: `1px solid ${V2.border}`,
9998
+ backgroundColor: "rgba(34,197,94,0.10)",
9999
+ color: V2.text,
10000
+ fontSize: 13,
10001
+ display: "flex",
10002
+ alignItems: "center",
10003
+ justifyContent: "space-between",
10004
+ gap: 12
10005
+ },
10006
+ children: [
10007
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t.seoView.bulkAppliedNote }),
10008
+ /* @__PURE__ */ jsxRuntime.jsxs(
10009
+ "button",
10010
+ {
10011
+ onClick: () => {
10012
+ setBulkApplied(false);
10013
+ fetchAudit(true);
10014
+ },
10015
+ style: { ...btnBase, backgroundColor: V2.bgCard, color: V2.text },
10016
+ children: [
10017
+ "\u21BB ",
10018
+ t.common.refresh
10019
+ ]
10020
+ }
10021
+ )
10022
+ ]
10023
+ }
10024
+ ),
9987
10025
  stats && /* @__PURE__ */ jsxRuntime.jsxs(
9988
10026
  "div",
9989
10027
  {
package/dist/client.js CHANGED
@@ -1071,6 +1071,7 @@ var fr = {
1071
1071
  bulkExport: "Exporter CSV",
1072
1072
  bulkNoChanges: "Aucune correction n\xE9cessaire sur la s\xE9lection.",
1073
1073
  bulkCappedNote: "limite atteinte (affine la s\xE9lection)",
1074
+ bulkAppliedNote: "\u2713 Corrections appliqu\xE9es. Rafra\xEEchis pour recalculer les scores (une seule fois, apr\xE8s tes lots).",
1074
1075
  searchPlaceholder: "Rechercher (titre, slug, keyword)...",
1075
1076
  allCollections: "Toutes les collections",
1076
1077
  allScores: "Tous les scores",
@@ -1675,6 +1676,7 @@ var en = {
1675
1676
  bulkExport: "Export CSV",
1676
1677
  bulkNoChanges: "No corrections needed on the selection.",
1677
1678
  bulkCappedNote: "limit reached (narrow the selection)",
1679
+ bulkAppliedNote: "\u2713 Corrections applied. Refresh to recompute scores (once, after your batches).",
1678
1680
  searchPlaceholder: "Search (title, slug, keyword)...",
1679
1681
  allCollections: "All collections",
1680
1682
  allScores: "All scores",
@@ -9321,6 +9323,7 @@ function SeoView() {
9321
9323
  const [saveError, setSaveError] = useState(null);
9322
9324
  const [bulkOptimizing, setBulkOptimizing] = useState(false);
9323
9325
  const [bulkApplying, setBulkApplying] = useState(false);
9326
+ const [bulkApplied, setBulkApplied] = useState(false);
9324
9327
  const [bulkPreview, setBulkPreview] = useState(null);
9325
9328
  const PAGE_SIZE = 50;
9326
9329
  const fetchAudit = useCallback(async (forceRefresh = false) => {
@@ -9593,8 +9596,8 @@ function SeoView() {
9593
9596
  setBulkApplying(false);
9594
9597
  setBulkPreview(null);
9595
9598
  setSelectedIds(/* @__PURE__ */ new Set());
9596
- fetchAudit();
9597
- }, [bulkPreview, fetchAudit]);
9599
+ setBulkApplied(true);
9600
+ }, [bulkPreview]);
9598
9601
  const handleExportBulkPreviewCsv = useCallback(() => {
9599
9602
  if (!bulkPreview) return;
9600
9603
  const header = [
@@ -9978,6 +9981,41 @@ function SeoView() {
9978
9981
  ]
9979
9982
  }
9980
9983
  ),
9984
+ bulkApplied && /* @__PURE__ */ jsxs(
9985
+ "div",
9986
+ {
9987
+ style: {
9988
+ marginBottom: 16,
9989
+ padding: "10px 14px",
9990
+ borderRadius: 8,
9991
+ border: `1px solid ${V2.border}`,
9992
+ backgroundColor: "rgba(34,197,94,0.10)",
9993
+ color: V2.text,
9994
+ fontSize: 13,
9995
+ display: "flex",
9996
+ alignItems: "center",
9997
+ justifyContent: "space-between",
9998
+ gap: 12
9999
+ },
10000
+ children: [
10001
+ /* @__PURE__ */ jsx("span", { children: t.seoView.bulkAppliedNote }),
10002
+ /* @__PURE__ */ jsxs(
10003
+ "button",
10004
+ {
10005
+ onClick: () => {
10006
+ setBulkApplied(false);
10007
+ fetchAudit(true);
10008
+ },
10009
+ style: { ...btnBase, backgroundColor: V2.bgCard, color: V2.text },
10010
+ children: [
10011
+ "\u21BB ",
10012
+ t.common.refresh
10013
+ ]
10014
+ }
10015
+ )
10016
+ ]
10017
+ }
10018
+ ),
9981
10019
  stats && /* @__PURE__ */ jsxs(
9982
10020
  "div",
9983
10021
  {
package/dist/index.cjs CHANGED
@@ -1689,8 +1689,8 @@ async function buildAuditCache(payload, collections, globals, seoConfig, reqLoca
1689
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
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));
1692
+ const rawDepth = parseInt(process.env.SEO_AUDIT_DEPTH ?? "0", 10);
1693
+ const DEPTH = Number.isNaN(rawDepth) ? 0 : Math.min(2, Math.max(0, rawDepth));
1694
1694
  const allResults = [];
1695
1695
  let capped = false;
1696
1696
  collectionsLoop:
@@ -1720,10 +1720,11 @@ async function buildAuditCache(payload, collections, globals, seoConfig, reqLoca
1720
1720
  `[seo] audit: skipped ${collectionSlug}/${doc.id}: ${e instanceof Error ? e.message : "error"}`
1721
1721
  );
1722
1722
  }
1723
+ await new Promise((resolve) => setImmediate(resolve));
1723
1724
  }
1724
1725
  hasMore = result.hasNextPage;
1725
1726
  page++;
1726
- await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY_MS));
1727
+ if (BATCH_DELAY_MS > 0) await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY_MS));
1727
1728
  }
1728
1729
  } catch {
1729
1730
  }
@@ -2365,7 +2366,7 @@ function isAdmin(user) {
2365
2366
  if (!user) return false;
2366
2367
  if (user.role === "admin") return true;
2367
2368
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
2368
- return false;
2369
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
2369
2370
  }
2370
2371
  function createSettingsHandler() {
2371
2372
  return async (req) => {
@@ -2526,7 +2527,7 @@ function isAdmin2(user) {
2526
2527
  if (!user) return false;
2527
2528
  if (user.role === "admin") return true;
2528
2529
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
2529
- return false;
2530
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
2530
2531
  }
2531
2532
  function createRedirectHandler(redirectsCollection) {
2532
2533
  return async (req) => {
@@ -2621,7 +2622,7 @@ function isAdmin3(user) {
2621
2622
  if (!user) return false;
2622
2623
  if (user.role === "admin") return true;
2623
2624
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
2624
- return false;
2625
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
2625
2626
  }
2626
2627
  function createRedirectsHandler(redirectsCollection) {
2627
2628
  return async (req) => {
@@ -3196,7 +3197,7 @@ function isGscAdmin(user) {
3196
3197
  if (!user) return false;
3197
3198
  if (user.role === "admin") return true;
3198
3199
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
3199
- return false;
3200
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
3200
3201
  }
3201
3202
  function resolveGscSiteUrl(seoConfig) {
3202
3203
  return (seoConfig?.siteUrl || process.env.NEXT_PUBLIC_SERVER_URL || process.env.PAYLOAD_PUBLIC_SERVER_URL || void 0)?.replace(/\/$/, "");
@@ -3275,7 +3276,7 @@ function isAdmin4(user) {
3275
3276
  if (!user) return false;
3276
3277
  if (user.role === "admin") return true;
3277
3278
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
3278
- return false;
3279
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
3279
3280
  }
3280
3281
  function resolveImageUrl(media, siteUrl) {
3281
3282
  const raw = typeof media.url === "string" && media.url || (typeof media.filename === "string" ? `/media/${media.filename}` : "");
@@ -3599,7 +3600,7 @@ function isAdmin5(user) {
3599
3600
  if (!user) return false;
3600
3601
  if (user.role === "admin") return true;
3601
3602
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
3602
- return false;
3603
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
3603
3604
  }
3604
3605
  function createAiOptimizeBulkHandler(targetCollections, seoConfig, localeMapping) {
3605
3606
  return async (req) => {
@@ -4350,7 +4351,7 @@ function isAdmin6(user) {
4350
4351
  if (!user) return false;
4351
4352
  if (user.role === "admin") return true;
4352
4353
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
4353
- return false;
4354
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
4354
4355
  }
4355
4356
  function createPerformanceHandler() {
4356
4357
  return async (req) => {
@@ -6169,7 +6170,7 @@ function isAdmin7(user) {
6169
6170
  if (!user) return false;
6170
6171
  if (user.role === "admin") return true;
6171
6172
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
6172
- return false;
6173
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
6173
6174
  }
6174
6175
  function createRobotsHandler(targetCollections) {
6175
6176
  return async (req) => {
@@ -7533,7 +7534,7 @@ function isAdmin8(user) {
7533
7534
  if (!user) return false;
7534
7535
  if (user.role === "admin") return true;
7535
7536
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
7536
- return false;
7537
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
7537
7538
  }
7538
7539
  function createSeoHealthHandler(basePath, seoConfig) {
7539
7540
  return async (req) => {
@@ -7605,7 +7606,7 @@ function isAdmin9(user) {
7605
7606
  if (!user) return false;
7606
7607
  if (user.role === "admin") return true;
7607
7608
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
7608
- return false;
7609
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
7609
7610
  }
7610
7611
  function docToUrl(slug, siteUrl) {
7611
7612
  const base = siteUrl.replace(/\/$/, "");
@@ -7747,7 +7748,7 @@ function isAdmin10(user) {
7747
7748
  if (!user) return false;
7748
7749
  if (user.role === "admin") return true;
7749
7750
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
7750
- return false;
7751
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
7751
7752
  }
7752
7753
  function createSeoLogsHandler(seoLogsSecret) {
7753
7754
  const postLimiter = createRateLimiter(30, 6e4);
@@ -8086,7 +8087,7 @@ function isAdmin11(user) {
8086
8087
  if (!user) return false;
8087
8088
  if (user.role === "admin") return true;
8088
8089
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
8089
- return false;
8090
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
8090
8091
  }
8091
8092
  function getAlertConfig() {
8092
8093
  return {
@@ -9336,6 +9337,7 @@ var fr = {
9336
9337
  bulkExport: "Exporter CSV",
9337
9338
  bulkNoChanges: "Aucune correction n\xE9cessaire sur la s\xE9lection.",
9338
9339
  bulkCappedNote: "limite atteinte (affine la s\xE9lection)",
9340
+ bulkAppliedNote: "\u2713 Corrections appliqu\xE9es. Rafra\xEEchis pour recalculer les scores (une seule fois, apr\xE8s tes lots).",
9339
9341
  searchPlaceholder: "Rechercher (titre, slug, keyword)...",
9340
9342
  allCollections: "Toutes les collections",
9341
9343
  allScores: "Tous les scores",
@@ -9940,6 +9942,7 @@ var en = {
9940
9942
  bulkExport: "Export CSV",
9941
9943
  bulkNoChanges: "No corrections needed on the selection.",
9942
9944
  bulkCappedNote: "limit reached (narrow the selection)",
9945
+ bulkAppliedNote: "\u2713 Corrections applied. Refresh to recompute scores (once, after your batches).",
9943
9946
  searchPlaceholder: "Search (title, slug, keyword)...",
9944
9947
  allCollections: "All collections",
9945
9948
  allScores: "All scores",
package/dist/index.d.cts CHANGED
@@ -485,6 +485,7 @@ interface DashboardTranslations {
485
485
  bulkExport: string;
486
486
  bulkNoChanges: string;
487
487
  bulkCappedNote: string;
488
+ bulkAppliedNote: string;
488
489
  searchPlaceholder: string;
489
490
  allCollections: string;
490
491
  allScores: string;
package/dist/index.d.ts CHANGED
@@ -485,6 +485,7 @@ interface DashboardTranslations {
485
485
  bulkExport: string;
486
486
  bulkNoChanges: string;
487
487
  bulkCappedNote: string;
488
+ bulkAppliedNote: string;
488
489
  searchPlaceholder: string;
489
490
  allCollections: string;
490
491
  allScores: string;
package/dist/index.js CHANGED
@@ -1687,8 +1687,8 @@ async function buildAuditCache(payload, collections, globals, seoConfig, reqLoca
1687
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
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));
1690
+ const rawDepth = parseInt(process.env.SEO_AUDIT_DEPTH ?? "0", 10);
1691
+ const DEPTH = Number.isNaN(rawDepth) ? 0 : Math.min(2, Math.max(0, rawDepth));
1692
1692
  const allResults = [];
1693
1693
  let capped = false;
1694
1694
  collectionsLoop:
@@ -1718,10 +1718,11 @@ async function buildAuditCache(payload, collections, globals, seoConfig, reqLoca
1718
1718
  `[seo] audit: skipped ${collectionSlug}/${doc.id}: ${e instanceof Error ? e.message : "error"}`
1719
1719
  );
1720
1720
  }
1721
+ await new Promise((resolve) => setImmediate(resolve));
1721
1722
  }
1722
1723
  hasMore = result.hasNextPage;
1723
1724
  page++;
1724
- await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY_MS));
1725
+ if (BATCH_DELAY_MS > 0) await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY_MS));
1725
1726
  }
1726
1727
  } catch {
1727
1728
  }
@@ -2363,7 +2364,7 @@ function isAdmin(user) {
2363
2364
  if (!user) return false;
2364
2365
  if (user.role === "admin") return true;
2365
2366
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
2366
- return false;
2367
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
2367
2368
  }
2368
2369
  function createSettingsHandler() {
2369
2370
  return async (req) => {
@@ -2524,7 +2525,7 @@ function isAdmin2(user) {
2524
2525
  if (!user) return false;
2525
2526
  if (user.role === "admin") return true;
2526
2527
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
2527
- return false;
2528
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
2528
2529
  }
2529
2530
  function createRedirectHandler(redirectsCollection) {
2530
2531
  return async (req) => {
@@ -2619,7 +2620,7 @@ function isAdmin3(user) {
2619
2620
  if (!user) return false;
2620
2621
  if (user.role === "admin") return true;
2621
2622
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
2622
- return false;
2623
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
2623
2624
  }
2624
2625
  function createRedirectsHandler(redirectsCollection) {
2625
2626
  return async (req) => {
@@ -3194,7 +3195,7 @@ function isGscAdmin(user) {
3194
3195
  if (!user) return false;
3195
3196
  if (user.role === "admin") return true;
3196
3197
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
3197
- return false;
3198
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
3198
3199
  }
3199
3200
  function resolveGscSiteUrl(seoConfig) {
3200
3201
  return (seoConfig?.siteUrl || process.env.NEXT_PUBLIC_SERVER_URL || process.env.PAYLOAD_PUBLIC_SERVER_URL || void 0)?.replace(/\/$/, "");
@@ -3273,7 +3274,7 @@ function isAdmin4(user) {
3273
3274
  if (!user) return false;
3274
3275
  if (user.role === "admin") return true;
3275
3276
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
3276
- return false;
3277
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
3277
3278
  }
3278
3279
  function resolveImageUrl(media, siteUrl) {
3279
3280
  const raw = typeof media.url === "string" && media.url || (typeof media.filename === "string" ? `/media/${media.filename}` : "");
@@ -3597,7 +3598,7 @@ function isAdmin5(user) {
3597
3598
  if (!user) return false;
3598
3599
  if (user.role === "admin") return true;
3599
3600
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
3600
- return false;
3601
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
3601
3602
  }
3602
3603
  function createAiOptimizeBulkHandler(targetCollections, seoConfig, localeMapping) {
3603
3604
  return async (req) => {
@@ -4348,7 +4349,7 @@ function isAdmin6(user) {
4348
4349
  if (!user) return false;
4349
4350
  if (user.role === "admin") return true;
4350
4351
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
4351
- return false;
4352
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
4352
4353
  }
4353
4354
  function createPerformanceHandler() {
4354
4355
  return async (req) => {
@@ -6167,7 +6168,7 @@ function isAdmin7(user) {
6167
6168
  if (!user) return false;
6168
6169
  if (user.role === "admin") return true;
6169
6170
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
6170
- return false;
6171
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
6171
6172
  }
6172
6173
  function createRobotsHandler(targetCollections) {
6173
6174
  return async (req) => {
@@ -7531,7 +7532,7 @@ function isAdmin8(user) {
7531
7532
  if (!user) return false;
7532
7533
  if (user.role === "admin") return true;
7533
7534
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
7534
- return false;
7535
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
7535
7536
  }
7536
7537
  function createSeoHealthHandler(basePath, seoConfig) {
7537
7538
  return async (req) => {
@@ -7603,7 +7604,7 @@ function isAdmin9(user) {
7603
7604
  if (!user) return false;
7604
7605
  if (user.role === "admin") return true;
7605
7606
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
7606
- return false;
7607
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
7607
7608
  }
7608
7609
  function docToUrl(slug, siteUrl) {
7609
7610
  const base = siteUrl.replace(/\/$/, "");
@@ -7745,7 +7746,7 @@ function isAdmin10(user) {
7745
7746
  if (!user) return false;
7746
7747
  if (user.role === "admin") return true;
7747
7748
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
7748
- return false;
7749
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
7749
7750
  }
7750
7751
  function createSeoLogsHandler(seoLogsSecret) {
7751
7752
  const postLimiter = createRateLimiter(30, 6e4);
@@ -8084,7 +8085,7 @@ function isAdmin11(user) {
8084
8085
  if (!user) return false;
8085
8086
  if (user.role === "admin") return true;
8086
8087
  if (Array.isArray(user.roles) && user.roles.includes("admin")) return true;
8087
- return false;
8088
+ return typeof user.role !== "string" && !Array.isArray(user.roles);
8088
8089
  }
8089
8090
  function getAlertConfig() {
8090
8091
  return {
@@ -9334,6 +9335,7 @@ var fr = {
9334
9335
  bulkExport: "Exporter CSV",
9335
9336
  bulkNoChanges: "Aucune correction n\xE9cessaire sur la s\xE9lection.",
9336
9337
  bulkCappedNote: "limite atteinte (affine la s\xE9lection)",
9338
+ bulkAppliedNote: "\u2713 Corrections appliqu\xE9es. Rafra\xEEchis pour recalculer les scores (une seule fois, apr\xE8s tes lots).",
9337
9339
  searchPlaceholder: "Rechercher (titre, slug, keyword)...",
9338
9340
  allCollections: "Toutes les collections",
9339
9341
  allScores: "Tous les scores",
@@ -9938,6 +9940,7 @@ var en = {
9938
9940
  bulkExport: "Export CSV",
9939
9941
  bulkNoChanges: "No corrections needed on the selection.",
9940
9942
  bulkCappedNote: "limit reached (narrow the selection)",
9943
+ bulkAppliedNote: "\u2713 Corrections applied. Refresh to recompute scores (once, after your batches).",
9941
9944
  searchPlaceholder: "Search (title, slug, keyword)...",
9942
9945
  allCollections: "All collections",
9943
9946
  allScores: "All scores",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@consilioweb/payload-seo-analyzer",
3
- "version": "1.17.1",
3
+ "version": "1.17.3",
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",