strapi-plugin-bulk-updater 1.5.6 → 1.5.7

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.
@@ -992,16 +992,48 @@ function formatEntryRecord(entry) {
992
992
  }
993
993
  function extractStageName(val) {
994
994
  if (val === void 0 || val === null) return "";
995
+ if (typeof val === "string") {
996
+ const trimmed = val.trim();
997
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
998
+ try {
999
+ const parsed = JSON.parse(trimmed);
1000
+ if (parsed && typeof parsed === "object") {
1001
+ const fromParsed = extractStageName(parsed);
1002
+ if (fromParsed) return fromParsed;
1003
+ }
1004
+ } catch {
1005
+ }
1006
+ }
1007
+ return trimmed;
1008
+ }
1009
+ if (typeof val === "number") {
1010
+ return String(val);
1011
+ }
995
1012
  if (typeof val === "object") {
996
1013
  const candidateProps = [
997
1014
  "strapi_stage",
998
1015
  "strapi_stage.name",
1016
+ "strapi_stage[name]",
1017
+ "strapi_stage.title",
999
1018
  "strapiStage",
1000
1019
  "Strapi Stage",
1001
1020
  "strapi-stage",
1021
+ "strapi_stage_name",
1002
1022
  "stage",
1003
1023
  "Stage",
1004
- "review_stage"
1024
+ "stage.name",
1025
+ "stage[name]",
1026
+ "stage_name",
1027
+ "Stage Name",
1028
+ "review_stage",
1029
+ "review_stage.name",
1030
+ "review_stage[name]",
1031
+ "Review Stage",
1032
+ "reviewStage",
1033
+ "workflow_stage",
1034
+ "workflow_stage.name",
1035
+ "Workflow Stage",
1036
+ "workflowStage"
1005
1037
  ];
1006
1038
  for (const prop of candidateProps) {
1007
1039
  if (val[prop] !== void 0 && val[prop] !== null) {
@@ -1009,23 +1041,35 @@ function extractStageName(val) {
1009
1041
  if (fromProp) return fromProp;
1010
1042
  }
1011
1043
  }
1012
- return String(val.name || val.title || val.status || val.label || "").trim();
1013
- }
1014
- if (typeof val === "string") {
1015
- const trimmed = val.trim();
1016
- if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
1017
- try {
1018
- const parsed = JSON.parse(trimmed);
1019
- if (parsed && typeof parsed === "object") {
1020
- const fromParsed = String(parsed.name || parsed.title || parsed.status || parsed.label || "").trim();
1021
- if (fromParsed) return fromParsed;
1044
+ const keys = Object.keys(val);
1045
+ for (const k of keys) {
1046
+ const norm = k.toLowerCase().replace(/[\s_\-\.\[\]]+/g, "");
1047
+ if (norm === "strapistage" || norm === "strapistagename" || norm === "stagename" || norm === "reviewstage" || norm === "reviewstagename" || norm === "workflowstage" || norm === "workflowstagename") {
1048
+ if (val[k] !== void 0 && val[k] !== null) {
1049
+ const fromNorm = extractStageName(val[k]);
1050
+ if (fromNorm) return fromNorm;
1022
1051
  }
1023
- } catch {
1024
1052
  }
1025
1053
  }
1026
- return trimmed;
1054
+ if (val.documentId && !val.color && !val.workflow) {
1055
+ return "";
1056
+ }
1057
+ const candidateStageValues = [
1058
+ val.name,
1059
+ val.title,
1060
+ val.label,
1061
+ val.value,
1062
+ val.stageName,
1063
+ val.stage_name,
1064
+ val.status
1065
+ ];
1066
+ for (const sv of candidateStageValues) {
1067
+ if (sv !== void 0 && sv !== null && typeof sv === "string" && sv.trim()) {
1068
+ return sv.trim();
1069
+ }
1070
+ }
1027
1071
  }
1028
- return String(val).trim();
1072
+ return "";
1029
1073
  }
1030
1074
  function isStageApproved(stageVal) {
1031
1075
  const name = extractStageName(stageVal);
@@ -1035,14 +1079,33 @@ function isStageEditingOrPending(stageVal) {
1035
1079
  const name = extractStageName(stageVal).toLowerCase();
1036
1080
  return name === "editing" || name === "in review" || name === "in_review" || name === "pending review" || name === "pending_review";
1037
1081
  }
1038
- function inspectPreUpdateStatus(entry) {
1082
+ function inspectPreUpdateStatus(entry, publishedCounterpart) {
1039
1083
  if (!entry || typeof entry !== "object") {
1040
1084
  return { hadPublishedVersion: false, isModified: false };
1041
1085
  }
1042
- const isModified = entry.status === "modified";
1043
- const isPublished = entry.status === "published" || Boolean(entry.publishedAt);
1044
- const hadPublishedVersion = isModified || isPublished;
1045
- return { hadPublishedVersion, isModified };
1086
+ const status = String(entry.status || "").toLowerCase();
1087
+ if (status === "published") {
1088
+ return { hadPublishedVersion: true, isModified: false };
1089
+ }
1090
+ if (status === "modified" || status === "modified draft") {
1091
+ return { hadPublishedVersion: true, isModified: true };
1092
+ }
1093
+ if (status === "draft") {
1094
+ return { hadPublishedVersion: false, isModified: false };
1095
+ }
1096
+ if (publishedCounterpart) {
1097
+ const draftUpdatedTime = new Date(entry.updatedAt || entry.updated_at || 0).getTime();
1098
+ const pubUpdatedTime = new Date(publishedCounterpart.updatedAt || publishedCounterpart.updated_at || 0).getTime();
1099
+ const pubPublishedTime = new Date(publishedCounterpart.publishedAt || publishedCounterpart.published_at || 0).getTime();
1100
+ const lastPublishedTime = Math.max(
1101
+ isNaN(pubUpdatedTime) ? 0 : pubUpdatedTime,
1102
+ isNaN(pubPublishedTime) ? 0 : pubPublishedTime
1103
+ );
1104
+ const isModified = !isNaN(draftUpdatedTime) && lastPublishedTime > 0 && draftUpdatedTime > lastPublishedTime;
1105
+ return { hadPublishedVersion: true, isModified };
1106
+ }
1107
+ const hasPubAt = Boolean(entry.publishedAt || entry.published_at);
1108
+ return { hadPublishedVersion: hasPubAt, isModified: false };
1046
1109
  }
1047
1110
  function determineShouldPublish({
1048
1111
  isDraftAndPublish,
@@ -1715,11 +1778,8 @@ async function executeBatchInternal(strapi, {
1715
1778
  const getDocumentDeduplicated = (uid, documentId) => {
1716
1779
  const loaderKey = `${uid}@@@${documentId}`;
1717
1780
  if (!documentLoader.has(loaderKey)) {
1718
- const ct = strapi.contentTypes[uid];
1719
- const findOneArgs = { documentId };
1720
- if (ct?.attributes?.strapi_stage) {
1721
- findOneArgs.populate = ["strapi_stage"];
1722
- }
1781
+ strapi.contentTypes[uid];
1782
+ const findOneArgs = { documentId, populate: ["strapi_stage", "stage"] };
1723
1783
  documentLoader.set(
1724
1784
  loaderKey,
1725
1785
  strapi.documents(uid).findOne(findOneArgs)
@@ -1729,6 +1789,34 @@ async function executeBatchInternal(strapi, {
1729
1789
  };
1730
1790
  for (let i = 0; i < targets.length; i += CHUNK_SIZE) {
1731
1791
  const chunk = targets.slice(i, i + CHUNK_SIZE);
1792
+ const chunkByUid = /* @__PURE__ */ new Map();
1793
+ for (const t of chunk) {
1794
+ if (t.uid && t.documentId) {
1795
+ if (!chunkByUid.has(t.uid)) chunkByUid.set(t.uid, []);
1796
+ chunkByUid.get(t.uid).push(t.documentId);
1797
+ }
1798
+ }
1799
+ const publishedCounterparts = /* @__PURE__ */ new Map();
1800
+ for (const [colUid, docIds] of chunkByUid.entries()) {
1801
+ const colCt = strapi.contentTypes[colUid];
1802
+ if (colCt?.options?.draftAndPublish && docIds.length > 0) {
1803
+ try {
1804
+ const pubList = await strapi.documents(colUid).findMany({
1805
+ status: "published",
1806
+ filters: { documentId: { $in: docIds } },
1807
+ fields: ["documentId", "updatedAt", "publishedAt"],
1808
+ limit: docIds.length
1809
+ });
1810
+ for (const pub of pubList || []) {
1811
+ if (pub?.documentId) {
1812
+ publishedCounterparts.set(`${colUid}@@@${pub.documentId}`, pub);
1813
+ }
1814
+ }
1815
+ } catch (err) {
1816
+ strapi.log.warn(`[bulk-updater] Failed to pre-fetch published status for ${colUid}:`, err);
1817
+ }
1818
+ }
1819
+ }
1732
1820
  const chunkPromises = chunk.map(async (target) => {
1733
1821
  const contentType = strapi.contentTypes[target.uid];
1734
1822
  const displayName = contentType?.info?.displayName || target.uid;
@@ -1780,7 +1868,24 @@ async function executeBatchInternal(strapi, {
1780
1868
  }
1781
1869
  });
1782
1870
  const isDraftAndPublishComp = Boolean(contentType?.options?.draftAndPublish);
1783
- const { hadPublishedVersion: hadPubComp, isModified: isModComp } = inspectPreUpdateStatus(currentEntry);
1871
+ let pubRecordComp = publishedCounterparts.get(`${target.uid}@@@${target.documentId}`);
1872
+ if (!pubRecordComp && isDraftAndPublishComp && target.documentId) {
1873
+ try {
1874
+ const singlePub = await strapi.documents(target.uid).findMany({
1875
+ status: "published",
1876
+ filters: { documentId: target.documentId },
1877
+ fields: ["documentId", "updatedAt", "publishedAt"],
1878
+ limit: 1
1879
+ });
1880
+ if (singlePub && singlePub.length > 0) {
1881
+ pubRecordComp = singlePub[0];
1882
+ publishedCounterparts.set(`${target.uid}@@@${target.documentId}`, pubRecordComp);
1883
+ }
1884
+ } catch {
1885
+ }
1886
+ }
1887
+ const inspectionTargetComp = target.status || target.publishedAt ? { ...currentEntry, status: target.status, publishedAt: target.publishedAt } : currentEntry;
1888
+ const { hadPublishedVersion: hadPubComp, isModified: isModComp } = inspectPreUpdateStatus(inspectionTargetComp, pubRecordComp);
1784
1889
  const targetStageComp = attribute.toLowerCase() === "strapi_stage" || attribute.toLowerCase() === "stage" ? value : currentEntry?.strapi_stage ?? currentEntry?.stage ?? target?.strapi_stage ?? target?.stage;
1785
1890
  const shouldPublishComp = determineShouldPublish({
1786
1891
  isDraftAndPublish: isDraftAndPublishComp,
@@ -1794,8 +1899,9 @@ async function executeBatchInternal(strapi, {
1794
1899
  if (shouldPublishComp) {
1795
1900
  try {
1796
1901
  const pubArgs = { documentId: target.documentId };
1797
- if (target.locale || currentEntry?.locale) {
1798
- pubArgs.locale = target.locale || currentEntry?.locale;
1902
+ const candLoc = target.locale || currentEntry?.locale;
1903
+ if (Boolean(contentType?.pluginOptions?.i18n?.localized) && candLoc && candLoc !== "null" && candLoc !== "undefined") {
1904
+ pubArgs.locale = candLoc;
1799
1905
  }
1800
1906
  await strapi.documents(target.uid).publish(pubArgs);
1801
1907
  } catch (publishErr) {
@@ -1890,7 +1996,24 @@ async function executeBatchInternal(strapi, {
1890
1996
  }
1891
1997
  });
1892
1998
  const isDraftAndPublishRel = Boolean(contentType?.options?.draftAndPublish);
1893
- const { hadPublishedVersion: hadPubRel, isModified: isModRel } = inspectPreUpdateStatus(currentEntry);
1999
+ let pubRecordRel = publishedCounterparts.get(`${target.uid}@@@${target.documentId}`);
2000
+ if (!pubRecordRel && isDraftAndPublishRel && target.documentId) {
2001
+ try {
2002
+ const singlePub = await strapi.documents(target.uid).findMany({
2003
+ status: "published",
2004
+ filters: { documentId: target.documentId },
2005
+ fields: ["documentId", "updatedAt", "publishedAt"],
2006
+ limit: 1
2007
+ });
2008
+ if (singlePub && singlePub.length > 0) {
2009
+ pubRecordRel = singlePub[0];
2010
+ publishedCounterparts.set(`${target.uid}@@@${target.documentId}`, pubRecordRel);
2011
+ }
2012
+ } catch {
2013
+ }
2014
+ }
2015
+ const inspectionTargetRel = target.status || target.publishedAt ? { ...currentEntry, status: target.status, publishedAt: target.publishedAt } : currentEntry;
2016
+ const { hadPublishedVersion: hadPubRel, isModified: isModRel } = inspectPreUpdateStatus(inspectionTargetRel, pubRecordRel);
1894
2017
  const targetStageRel = attribute.toLowerCase() === "strapi_stage" || attribute.toLowerCase() === "stage" ? value : currentEntry?.strapi_stage ?? currentEntry?.stage ?? target?.strapi_stage ?? target?.stage;
1895
2018
  const shouldPublishRel = determineShouldPublish({
1896
2019
  isDraftAndPublish: isDraftAndPublishRel,
@@ -1904,8 +2027,9 @@ async function executeBatchInternal(strapi, {
1904
2027
  if (shouldPublishRel) {
1905
2028
  try {
1906
2029
  const pubArgs = { documentId: target.documentId };
1907
- if (target.locale || currentEntry?.locale) {
1908
- pubArgs.locale = target.locale || currentEntry?.locale;
2030
+ const candLoc = target.locale || currentEntry?.locale;
2031
+ if (Boolean(contentType?.pluginOptions?.i18n?.localized) && candLoc && candLoc !== "null" && candLoc !== "undefined") {
2032
+ pubArgs.locale = candLoc;
1909
2033
  }
1910
2034
  await strapi.documents(target.uid).publish(pubArgs);
1911
2035
  } catch (publishErr) {
@@ -1946,7 +2070,24 @@ async function executeBatchInternal(strapi, {
1946
2070
  }
1947
2071
  });
1948
2072
  const isDraftAndPublishScalar = Boolean(contentType?.options?.draftAndPublish);
1949
- const { hadPublishedVersion: hadPubScalar, isModified: isModScalar } = inspectPreUpdateStatus(currentEntry);
2073
+ let pubRecordScalar = publishedCounterparts.get(`${target.uid}@@@${target.documentId}`);
2074
+ if (!pubRecordScalar && isDraftAndPublishScalar && target.documentId) {
2075
+ try {
2076
+ const singlePub = await strapi.documents(target.uid).findMany({
2077
+ status: "published",
2078
+ filters: { documentId: target.documentId },
2079
+ fields: ["documentId", "updatedAt", "publishedAt"],
2080
+ limit: 1
2081
+ });
2082
+ if (singlePub && singlePub.length > 0) {
2083
+ pubRecordScalar = singlePub[0];
2084
+ publishedCounterparts.set(`${target.uid}@@@${target.documentId}`, pubRecordScalar);
2085
+ }
2086
+ } catch {
2087
+ }
2088
+ }
2089
+ const inspectionTargetScalar = target.status || target.publishedAt ? { ...currentEntry, status: target.status, publishedAt: target.publishedAt } : currentEntry;
2090
+ const { hadPublishedVersion: hadPubScalar, isModified: isModScalar } = inspectPreUpdateStatus(inspectionTargetScalar, pubRecordScalar);
1950
2091
  const targetStageScalar = attribute.toLowerCase() === "strapi_stage" || attribute.toLowerCase() === "stage" ? value : currentEntry?.strapi_stage ?? currentEntry?.stage ?? target?.strapi_stage ?? target?.stage;
1951
2092
  const shouldPublishScalar = determineShouldPublish({
1952
2093
  isDraftAndPublish: isDraftAndPublishScalar,
@@ -1960,8 +2101,9 @@ async function executeBatchInternal(strapi, {
1960
2101
  if (shouldPublishScalar) {
1961
2102
  try {
1962
2103
  const pubArgs = { documentId: target.documentId };
1963
- if (target.locale || currentEntry?.locale) {
1964
- pubArgs.locale = target.locale || currentEntry?.locale;
2104
+ const candLoc = target.locale || currentEntry?.locale;
2105
+ if (Boolean(contentType?.pluginOptions?.i18n?.localized) && candLoc && candLoc !== "null" && candLoc !== "undefined") {
2106
+ pubArgs.locale = candLoc;
1965
2107
  }
1966
2108
  await strapi.documents(target.uid).publish(pubArgs);
1967
2109
  } catch (publishErr) {
@@ -5335,54 +5477,30 @@ function getEffectiveLocale(ct, rowLocale) {
5335
5477
  }
5336
5478
  return trimmed;
5337
5479
  }
5338
- function isRowInEditingStage(row) {
5339
- if (!row || typeof row !== "object") return false;
5340
- const candidates = [
5341
- row.strapi_stage,
5342
- row["strapi_stage"],
5343
- row.strapiStage,
5344
- row["Strapi Stage"],
5345
- row["strapi-stage"],
5346
- row.stage,
5347
- row.Stage,
5348
- row.status,
5349
- row.Status
5350
- ];
5351
- for (const c of candidates) {
5352
- if (c !== void 0 && c !== null) {
5353
- let stageName = "";
5354
- if (typeof c === "object") {
5355
- stageName = String(c.name || c.title || c.status || c.documentId || c.id || "").trim();
5356
- } else if (typeof c === "string") {
5357
- const trimmed = c.trim();
5358
- if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
5359
- try {
5360
- const parsed = JSON.parse(trimmed);
5361
- if (typeof parsed === "object" && parsed !== null) {
5362
- stageName = String(parsed.name || parsed.title || parsed.status || parsed.documentId || parsed.id || "").trim();
5363
- }
5364
- } catch {
5365
- }
5366
- }
5367
- if (!stageName) {
5368
- stageName = trimmed;
5369
- }
5370
- } else {
5371
- stageName = String(c).trim();
5372
- }
5373
- if (stageName) {
5374
- const s = stageName.toLowerCase();
5375
- if (s === "editing" || s === "in review" || s === "in_review" || s === "pending review" || s === "pending_review") {
5376
- return true;
5377
- }
5378
- }
5480
+ function resolveStageValue(row, existing) {
5481
+ if (row && typeof row === "object") {
5482
+ const stageNameFromRow = extractStageName(row);
5483
+ if (stageNameFromRow) return stageNameFromRow;
5484
+ }
5485
+ if (existing && typeof existing === "object") {
5486
+ if (existing.strapi_stage !== void 0 && existing.strapi_stage !== null) {
5487
+ return existing.strapi_stage;
5379
5488
  }
5489
+ if (existing.stage !== void 0 && existing.stage !== null) {
5490
+ return existing.stage;
5491
+ }
5492
+ const stageNameFromExisting = extractStageName(existing);
5493
+ if (stageNameFromExisting) return stageNameFromExisting;
5380
5494
  }
5381
- return false;
5495
+ return void 0;
5382
5496
  }
5383
- function isRowInApprovedStage(row) {
5384
- if (!row || typeof row !== "object") return false;
5385
- return isStageApproved(row);
5497
+ function isRowInEditingStage(row, existing) {
5498
+ const stage = resolveStageValue(row, existing);
5499
+ return isStageEditingOrPending(stage);
5500
+ }
5501
+ function isRowInApprovedStage(row, existing) {
5502
+ const stage = resolveStageValue(row, existing);
5503
+ return isStageApproved(stage);
5386
5504
  }
5387
5505
  function extractDetailedErrorMessage(err) {
5388
5506
  if (!err) return "Error processing row";
@@ -5580,7 +5698,7 @@ async function findExistingDocument(strapi, uid, targetDocId, docLocale) {
5580
5698
  try {
5581
5699
  const queryArgs = { documentId: targetDocId };
5582
5700
  if (effectiveLocale) queryArgs.locale = effectiveLocale;
5583
- if (ct?.attributes?.strapi_stage) queryArgs.populate = ["strapi_stage"];
5701
+ queryArgs.populate = ["strapi_stage", "stage"];
5584
5702
  const found = await strapi.documents(uid).findOne(queryArgs);
5585
5703
  if (found) return found;
5586
5704
  } catch {
@@ -5960,6 +6078,25 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5960
6078
  errors: [],
5961
6079
  diffs: []
5962
6080
  };
6081
+ const docIdsInChunk = rows.map((r) => extractDocId(r)).filter(Boolean);
6082
+ const publishedCounterparts = /* @__PURE__ */ new Map();
6083
+ if (isDraftAndPublish && docIdsInChunk.length > 0) {
6084
+ try {
6085
+ const pubList = await strapi.documents(uid).findMany({
6086
+ status: "published",
6087
+ filters: { documentId: { $in: docIdsInChunk } },
6088
+ fields: ["documentId", "updatedAt", "publishedAt"],
6089
+ limit: docIdsInChunk.length
6090
+ });
6091
+ for (const pub of pubList || []) {
6092
+ if (pub?.documentId) {
6093
+ publishedCounterparts.set(String(pub.documentId), pub);
6094
+ }
6095
+ }
6096
+ } catch (err) {
6097
+ strapi.log.warn(`[csv] Failed to pre-fetch published status for CSV chunk:`, err);
6098
+ }
6099
+ }
5963
6100
  for (let i = 0; i < rows.length; i++) {
5964
6101
  const rowNumber = startRowNumber + i;
5965
6102
  const row = rows[i];
@@ -6027,8 +6164,24 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6027
6164
  };
6028
6165
  if (effectiveLocale) updateArgs.locale = effectiveLocale;
6029
6166
  await strapi.documents(uid).update(updateArgs);
6030
- const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing);
6031
- const stageVal = row.strapi_stage ?? row["strapi_stage"] ?? row.stage ?? existing?.strapi_stage;
6167
+ let pubRecord = publishedCounterparts.get(String(resolvedDocId));
6168
+ if (!pubRecord && isDraftAndPublish && resolvedDocId) {
6169
+ try {
6170
+ const singlePub = await strapi.documents(uid).findMany({
6171
+ status: "published",
6172
+ filters: { documentId: resolvedDocId },
6173
+ fields: ["documentId", "updatedAt", "publishedAt"],
6174
+ limit: 1
6175
+ });
6176
+ if (singlePub && singlePub.length > 0) {
6177
+ pubRecord = singlePub[0];
6178
+ publishedCounterparts.set(String(resolvedDocId), pubRecord);
6179
+ }
6180
+ } catch {
6181
+ }
6182
+ }
6183
+ const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing, pubRecord);
6184
+ const stageVal = resolveStageValue(row, existing);
6032
6185
  const shouldPublish = determineShouldPublish({
6033
6186
  isDraftAndPublish,
6034
6187
  hadPublishedVersion,
@@ -6041,7 +6194,10 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6041
6194
  if (shouldPublish) {
6042
6195
  try {
6043
6196
  const pubArgs = { documentId: resolvedDocId };
6044
- if (effectiveLocale) pubArgs.locale = effectiveLocale;
6197
+ const isLoc = Boolean(ct?.pluginOptions?.i18n?.localized);
6198
+ if (isLoc && effectiveLocale && effectiveLocale !== "null" && effectiveLocale !== "undefined") {
6199
+ pubArgs.locale = effectiveLocale;
6200
+ }
6045
6201
  await strapi.documents(uid).publish(pubArgs);
6046
6202
  } catch (pubErr) {
6047
6203
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);
@@ -6091,8 +6247,24 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6091
6247
  };
6092
6248
  if (effectiveLocale) updateArgs.locale = effectiveLocale;
6093
6249
  await strapi.documents(uid).update(updateArgs);
6094
- const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing);
6095
- const stageVal = row.strapi_stage ?? row["strapi_stage"] ?? row.stage ?? existing?.strapi_stage;
6250
+ let pubRecord = publishedCounterparts.get(String(resolvedDocId));
6251
+ if (!pubRecord && isDraftAndPublish && resolvedDocId) {
6252
+ try {
6253
+ const singlePub = await strapi.documents(uid).findMany({
6254
+ status: "published",
6255
+ filters: { documentId: resolvedDocId },
6256
+ fields: ["documentId", "updatedAt", "publishedAt"],
6257
+ limit: 1
6258
+ });
6259
+ if (singlePub && singlePub.length > 0) {
6260
+ pubRecord = singlePub[0];
6261
+ publishedCounterparts.set(String(resolvedDocId), pubRecord);
6262
+ }
6263
+ } catch {
6264
+ }
6265
+ }
6266
+ const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing, pubRecord);
6267
+ const stageVal = resolveStageValue(row, existing);
6096
6268
  const shouldPublish = determineShouldPublish({
6097
6269
  isDraftAndPublish,
6098
6270
  hadPublishedVersion,
@@ -6105,7 +6277,8 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6105
6277
  if (shouldPublish) {
6106
6278
  try {
6107
6279
  const pubArgs = { documentId: resolvedDocId };
6108
- if (effectiveLocale) pubArgs.locale = effectiveLocale;
6280
+ const isLoc = Boolean(ct?.pluginOptions?.i18n?.localized);
6281
+ if (isLoc && effectiveLocale && effectiveLocale !== "null" && effectiveLocale !== "undefined") pubArgs.locale = effectiveLocale;
6109
6282
  await strapi.documents(uid).publish(pubArgs);
6110
6283
  } catch (pubErr) {
6111
6284
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);
@@ -6147,7 +6320,8 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6147
6320
  if (shouldPublishNew && newDocId) {
6148
6321
  try {
6149
6322
  const pubArgs = { documentId: newDocId };
6150
- if (effectiveLocale) pubArgs.locale = effectiveLocale;
6323
+ const isLoc = Boolean(ct?.pluginOptions?.i18n?.localized);
6324
+ if (isLoc && effectiveLocale && effectiveLocale !== "null" && effectiveLocale !== "undefined") pubArgs.locale = effectiveLocale;
6151
6325
  await strapi.documents(uid).publish(pubArgs);
6152
6326
  } catch (pubErr) {
6153
6327
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);
@@ -6198,8 +6372,24 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6198
6372
  };
6199
6373
  if (effectiveLocale) updateArgs.locale = effectiveLocale;
6200
6374
  await strapi.documents(uid).update(updateArgs);
6201
- const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing);
6202
- const stageVal = row.strapi_stage ?? row["strapi_stage"] ?? row.stage ?? existing?.strapi_stage;
6375
+ let pubRecord = publishedCounterparts.get(String(resolvedDocId));
6376
+ if (!pubRecord && isDraftAndPublish && resolvedDocId) {
6377
+ try {
6378
+ const singlePub = await strapi.documents(uid).findMany({
6379
+ status: "published",
6380
+ filters: { documentId: resolvedDocId },
6381
+ fields: ["documentId", "updatedAt", "publishedAt"],
6382
+ limit: 1
6383
+ });
6384
+ if (singlePub && singlePub.length > 0) {
6385
+ pubRecord = singlePub[0];
6386
+ publishedCounterparts.set(String(resolvedDocId), pubRecord);
6387
+ }
6388
+ } catch {
6389
+ }
6390
+ }
6391
+ const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing, pubRecord);
6392
+ const stageVal = resolveStageValue(row, existing);
6203
6393
  const shouldPublish = determineShouldPublish({
6204
6394
  isDraftAndPublish,
6205
6395
  hadPublishedVersion,
@@ -6212,7 +6402,8 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6212
6402
  if (shouldPublish) {
6213
6403
  try {
6214
6404
  const pubArgs = { documentId: resolvedDocId };
6215
- if (effectiveLocale) pubArgs.locale = effectiveLocale;
6405
+ const isLoc = Boolean(ct?.pluginOptions?.i18n?.localized);
6406
+ if (isLoc && effectiveLocale && effectiveLocale !== "null" && effectiveLocale !== "undefined") pubArgs.locale = effectiveLocale;
6216
6407
  await strapi.documents(uid).publish(pubArgs);
6217
6408
  } catch (pubErr) {
6218
6409
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);
@@ -6254,7 +6445,8 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6254
6445
  if (shouldPublishNew && newDocId) {
6255
6446
  try {
6256
6447
  const pubArgs = { documentId: newDocId };
6257
- if (effectiveLocale) pubArgs.locale = effectiveLocale;
6448
+ const isLoc = Boolean(ct?.pluginOptions?.i18n?.localized);
6449
+ if (isLoc && effectiveLocale && effectiveLocale !== "null" && effectiveLocale !== "undefined") pubArgs.locale = effectiveLocale;
6258
6450
  await strapi.documents(uid).publish(pubArgs);
6259
6451
  } catch (pubErr) {
6260
6452
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);
@@ -6842,6 +7034,25 @@ const csvService = ({ strapi }) => ({
6842
7034
  draft: 0,
6843
7035
  unreviewedCount: 0
6844
7036
  };
7037
+ const docIdsInPreflight = rows.map((r) => extractDocId(r)).filter(Boolean);
7038
+ const publishedCounterparts = /* @__PURE__ */ new Map();
7039
+ if (isDraftAndPublish && docIdsInPreflight.length > 0) {
7040
+ try {
7041
+ const pubList = await strapi.documents(uid).findMany({
7042
+ status: "published",
7043
+ filters: { documentId: { $in: docIdsInPreflight } },
7044
+ fields: ["documentId", "updatedAt", "publishedAt"],
7045
+ limit: docIdsInPreflight.length
7046
+ });
7047
+ for (const pub of pubList || []) {
7048
+ if (pub?.documentId) {
7049
+ publishedCounterparts.set(String(pub.documentId), pub);
7050
+ }
7051
+ }
7052
+ } catch (err) {
7053
+ strapi.log.warn(`[csv] Failed to pre-fetch published status for CSV preflight:`, err);
7054
+ }
7055
+ }
6845
7056
  const errors2 = [];
6846
7057
  const warnings = [];
6847
7058
  for (let i = 0; i < rows.length; i++) {
@@ -6858,8 +7069,25 @@ const csvService = ({ strapi }) => ({
6858
7069
  }
6859
7070
  if (existing && isDraftAndPublish) {
6860
7071
  lifecycleStats.totalChecked++;
6861
- const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing);
6862
- const stageVal = row.strapi_stage ?? row["strapi_stage"] ?? row.stage ?? existing?.strapi_stage;
7072
+ const targetDocId = existing.documentId || docId;
7073
+ let pubRecord = publishedCounterparts.get(String(targetDocId));
7074
+ if (!pubRecord && isDraftAndPublish && targetDocId) {
7075
+ try {
7076
+ const singlePub = await strapi.documents(uid).findMany({
7077
+ status: "published",
7078
+ filters: { documentId: targetDocId },
7079
+ fields: ["documentId", "updatedAt", "publishedAt"],
7080
+ limit: 1
7081
+ });
7082
+ if (singlePub && singlePub.length > 0) {
7083
+ pubRecord = singlePub[0];
7084
+ publishedCounterparts.set(String(targetDocId), pubRecord);
7085
+ }
7086
+ } catch {
7087
+ }
7088
+ }
7089
+ const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing, pubRecord);
7090
+ const stageVal = resolveStageValue(row, existing);
6863
7091
  const willPublish = determineShouldPublish({
6864
7092
  isDraftAndPublish,
6865
7093
  hadPublishedVersion,