strapi-plugin-bulk-updater 1.5.5 → 1.5.6

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.
@@ -993,6 +993,88 @@ function formatEntryRecord(entry) {
993
993
  }
994
994
  return formatted;
995
995
  }
996
+ function extractStageName(val) {
997
+ if (val === void 0 || val === null) return "";
998
+ if (typeof val === "object") {
999
+ const candidateProps = [
1000
+ "strapi_stage",
1001
+ "strapi_stage.name",
1002
+ "strapiStage",
1003
+ "Strapi Stage",
1004
+ "strapi-stage",
1005
+ "stage",
1006
+ "Stage",
1007
+ "review_stage"
1008
+ ];
1009
+ for (const prop of candidateProps) {
1010
+ if (val[prop] !== void 0 && val[prop] !== null) {
1011
+ const fromProp = extractStageName(val[prop]);
1012
+ if (fromProp) return fromProp;
1013
+ }
1014
+ }
1015
+ return String(val.name || val.title || val.status || val.label || "").trim();
1016
+ }
1017
+ if (typeof val === "string") {
1018
+ const trimmed = val.trim();
1019
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
1020
+ try {
1021
+ const parsed = JSON.parse(trimmed);
1022
+ if (parsed && typeof parsed === "object") {
1023
+ const fromParsed = String(parsed.name || parsed.title || parsed.status || parsed.label || "").trim();
1024
+ if (fromParsed) return fromParsed;
1025
+ }
1026
+ } catch {
1027
+ }
1028
+ }
1029
+ return trimmed;
1030
+ }
1031
+ return String(val).trim();
1032
+ }
1033
+ function isStageApproved(stageVal) {
1034
+ const name = extractStageName(stageVal);
1035
+ return name.toLowerCase() === "approved";
1036
+ }
1037
+ function isStageEditingOrPending(stageVal) {
1038
+ const name = extractStageName(stageVal).toLowerCase();
1039
+ return name === "editing" || name === "in review" || name === "in_review" || name === "pending review" || name === "pending_review";
1040
+ }
1041
+ function inspectPreUpdateStatus(entry) {
1042
+ if (!entry || typeof entry !== "object") {
1043
+ return { hadPublishedVersion: false, isModified: false };
1044
+ }
1045
+ const isModified = entry.status === "modified";
1046
+ const isPublished = entry.status === "published" || Boolean(entry.publishedAt);
1047
+ const hadPublishedVersion = isModified || isPublished;
1048
+ return { hadPublishedVersion, isModified };
1049
+ }
1050
+ function determineShouldPublish({
1051
+ isDraftAndPublish,
1052
+ hadPublishedVersion,
1053
+ isModified = false,
1054
+ stageValue,
1055
+ publish = true,
1056
+ publishStrategy = "safe",
1057
+ unreviewedConsent = false
1058
+ }) {
1059
+ if (!isDraftAndPublish || !publish) {
1060
+ return false;
1061
+ }
1062
+ if (!hadPublishedVersion) {
1063
+ return false;
1064
+ }
1065
+ const isApproved = isStageApproved(stageValue);
1066
+ const isEditingOrPending = isStageEditingOrPending(stageValue);
1067
+ if (isApproved) {
1068
+ return true;
1069
+ }
1070
+ if (isEditingOrPending) {
1071
+ return false;
1072
+ }
1073
+ if (publishStrategy === "all" || unreviewedConsent) {
1074
+ return true;
1075
+ }
1076
+ return hadPublishedVersion && !isModified;
1077
+ }
996
1078
  async function populateDocumentLifecycleStatus(strapi, uid, entries) {
997
1079
  if (!entries || !Array.isArray(entries) || entries.length === 0) {
998
1080
  return entries;
@@ -1636,9 +1718,14 @@ async function executeBatchInternal(strapi, {
1636
1718
  const getDocumentDeduplicated = (uid, documentId) => {
1637
1719
  const loaderKey = `${uid}@@@${documentId}`;
1638
1720
  if (!documentLoader.has(loaderKey)) {
1721
+ const ct = strapi.contentTypes[uid];
1722
+ const findOneArgs = { documentId };
1723
+ if (ct?.attributes?.strapi_stage) {
1724
+ findOneArgs.populate = ["strapi_stage"];
1725
+ }
1639
1726
  documentLoader.set(
1640
1727
  loaderKey,
1641
- strapi.documents(uid).findOne({ documentId })
1728
+ strapi.documents(uid).findOne(findOneArgs)
1642
1729
  );
1643
1730
  }
1644
1731
  return documentLoader.get(loaderKey);
@@ -1696,13 +1783,24 @@ async function executeBatchInternal(strapi, {
1696
1783
  }
1697
1784
  });
1698
1785
  const isDraftAndPublishComp = Boolean(contentType?.options?.draftAndPublish);
1699
- const isApprovedComp = isDraftAndPublishComp && Boolean(currentEntry?.publishedAt) && currentEntry?.status !== "modified";
1700
- const shouldPublishComp = isDraftAndPublishComp && Boolean(publishOnApproval) && (publishStrategy === "all" ? true : isApprovedComp);
1786
+ const { hadPublishedVersion: hadPubComp, isModified: isModComp } = inspectPreUpdateStatus(currentEntry);
1787
+ const targetStageComp = attribute.toLowerCase() === "strapi_stage" || attribute.toLowerCase() === "stage" ? value : currentEntry?.strapi_stage ?? currentEntry?.stage ?? target?.strapi_stage ?? target?.stage;
1788
+ const shouldPublishComp = determineShouldPublish({
1789
+ isDraftAndPublish: isDraftAndPublishComp,
1790
+ hadPublishedVersion: hadPubComp,
1791
+ isModified: isModComp,
1792
+ stageValue: targetStageComp,
1793
+ publish: Boolean(publishOnApproval),
1794
+ publishStrategy,
1795
+ unreviewedConsent
1796
+ });
1701
1797
  if (shouldPublishComp) {
1702
1798
  try {
1703
- await strapi.documents(target.uid).publish({
1704
- documentId: target.documentId
1705
- });
1799
+ const pubArgs = { documentId: target.documentId };
1800
+ if (target.locale || currentEntry?.locale) {
1801
+ pubArgs.locale = target.locale || currentEntry?.locale;
1802
+ }
1803
+ await strapi.documents(target.uid).publish(pubArgs);
1706
1804
  } catch (publishErr) {
1707
1805
  strapi.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);
1708
1806
  }
@@ -1712,7 +1810,7 @@ async function executeBatchInternal(strapi, {
1712
1810
  uid: target.uid,
1713
1811
  documentId: target.documentId,
1714
1812
  userId: currentUser?.id,
1715
- statusOverride: shouldPublishComp ? "published" : isDraftAndPublishComp ? "draft" : void 0
1813
+ statusOverride: shouldPublishComp ? "published" : isDraftAndPublishComp ? hadPubComp ? "modified" : "draft" : void 0
1716
1814
  });
1717
1815
  const dzDiffs = isRootDz && affectedMatches.length > 0 ? affectedMatches.map((m) => ({
1718
1816
  index: m.index,
@@ -1795,13 +1893,24 @@ async function executeBatchInternal(strapi, {
1795
1893
  }
1796
1894
  });
1797
1895
  const isDraftAndPublishRel = Boolean(contentType?.options?.draftAndPublish);
1798
- const isApprovedRel = isDraftAndPublishRel && Boolean(currentEntry?.publishedAt) && currentEntry?.status !== "modified";
1799
- const shouldPublishRel = isDraftAndPublishRel && Boolean(publishOnApproval) && (publishStrategy === "all" ? true : isApprovedRel);
1896
+ const { hadPublishedVersion: hadPubRel, isModified: isModRel } = inspectPreUpdateStatus(currentEntry);
1897
+ const targetStageRel = attribute.toLowerCase() === "strapi_stage" || attribute.toLowerCase() === "stage" ? value : currentEntry?.strapi_stage ?? currentEntry?.stage ?? target?.strapi_stage ?? target?.stage;
1898
+ const shouldPublishRel = determineShouldPublish({
1899
+ isDraftAndPublish: isDraftAndPublishRel,
1900
+ hadPublishedVersion: hadPubRel,
1901
+ isModified: isModRel,
1902
+ stageValue: targetStageRel,
1903
+ publish: Boolean(publishOnApproval),
1904
+ publishStrategy,
1905
+ unreviewedConsent
1906
+ });
1800
1907
  if (shouldPublishRel) {
1801
1908
  try {
1802
- await strapi.documents(target.uid).publish({
1803
- documentId: target.documentId
1804
- });
1909
+ const pubArgs = { documentId: target.documentId };
1910
+ if (target.locale || currentEntry?.locale) {
1911
+ pubArgs.locale = target.locale || currentEntry?.locale;
1912
+ }
1913
+ await strapi.documents(target.uid).publish(pubArgs);
1805
1914
  } catch (publishErr) {
1806
1915
  strapi.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);
1807
1916
  }
@@ -1814,7 +1923,7 @@ async function executeBatchInternal(strapi, {
1814
1923
  uid: target.uid,
1815
1924
  documentId: target.documentId,
1816
1925
  userId: currentUser?.id,
1817
- statusOverride: shouldPublishRel ? "published" : isDraftAndPublishRel ? "draft" : void 0
1926
+ statusOverride: shouldPublishRel ? "published" : isDraftAndPublishRel ? hadPubRel ? "modified" : "draft" : void 0
1818
1927
  });
1819
1928
  return {
1820
1929
  uid: target.uid,
@@ -1840,13 +1949,24 @@ async function executeBatchInternal(strapi, {
1840
1949
  }
1841
1950
  });
1842
1951
  const isDraftAndPublishScalar = Boolean(contentType?.options?.draftAndPublish);
1843
- const isApprovedScalar = isDraftAndPublishScalar && Boolean(currentEntry?.publishedAt) && currentEntry?.status !== "modified";
1844
- const shouldPublishScalar = isDraftAndPublishScalar && Boolean(publishOnApproval) && (publishStrategy === "all" ? true : isApprovedScalar);
1952
+ const { hadPublishedVersion: hadPubScalar, isModified: isModScalar } = inspectPreUpdateStatus(currentEntry);
1953
+ const targetStageScalar = attribute.toLowerCase() === "strapi_stage" || attribute.toLowerCase() === "stage" ? value : currentEntry?.strapi_stage ?? currentEntry?.stage ?? target?.strapi_stage ?? target?.stage;
1954
+ const shouldPublishScalar = determineShouldPublish({
1955
+ isDraftAndPublish: isDraftAndPublishScalar,
1956
+ hadPublishedVersion: hadPubScalar,
1957
+ isModified: isModScalar,
1958
+ stageValue: targetStageScalar,
1959
+ publish: Boolean(publishOnApproval),
1960
+ publishStrategy,
1961
+ unreviewedConsent
1962
+ });
1845
1963
  if (shouldPublishScalar) {
1846
1964
  try {
1847
- await strapi.documents(target.uid).publish({
1848
- documentId: target.documentId
1849
- });
1965
+ const pubArgs = { documentId: target.documentId };
1966
+ if (target.locale || currentEntry?.locale) {
1967
+ pubArgs.locale = target.locale || currentEntry?.locale;
1968
+ }
1969
+ await strapi.documents(target.uid).publish(pubArgs);
1850
1970
  } catch (publishErr) {
1851
1971
  strapi.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);
1852
1972
  }
@@ -1855,7 +1975,7 @@ async function executeBatchInternal(strapi, {
1855
1975
  uid: target.uid,
1856
1976
  documentId: target.documentId,
1857
1977
  userId: currentUser?.id,
1858
- statusOverride: shouldPublishScalar ? "published" : isDraftAndPublishScalar ? "draft" : void 0
1978
+ statusOverride: shouldPublishScalar ? "published" : isDraftAndPublishScalar ? hadPubScalar ? "modified" : "draft" : void 0
1859
1979
  });
1860
1980
  return {
1861
1981
  uid: target.uid,
@@ -5263,6 +5383,10 @@ function isRowInEditingStage(row) {
5263
5383
  }
5264
5384
  return false;
5265
5385
  }
5386
+ function isRowInApprovedStage(row) {
5387
+ if (!row || typeof row !== "object") return false;
5388
+ return isStageApproved(row);
5389
+ }
5266
5390
  function extractDetailedErrorMessage(err) {
5267
5391
  if (!err) return "Error processing row";
5268
5392
  const detailsErrors = err.details?.errors || err.error?.details?.errors;
@@ -5459,6 +5583,7 @@ async function findExistingDocument(strapi, uid, targetDocId, docLocale) {
5459
5583
  try {
5460
5584
  const queryArgs = { documentId: targetDocId };
5461
5585
  if (effectiveLocale) queryArgs.locale = effectiveLocale;
5586
+ if (ct?.attributes?.strapi_stage) queryArgs.populate = ["strapi_stage"];
5462
5587
  const found = await strapi.documents(uid).findOne(queryArgs);
5463
5588
  if (found) return found;
5464
5589
  } catch {
@@ -5905,8 +6030,17 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5905
6030
  };
5906
6031
  if (effectiveLocale) updateArgs.locale = effectiveLocale;
5907
6032
  await strapi.documents(uid).update(updateArgs);
5908
- const isApproved = !isEditing && isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== "modified";
5909
- const shouldPublish = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : isApproved);
6033
+ const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing);
6034
+ const stageVal = row.strapi_stage ?? row["strapi_stage"] ?? row.stage ?? existing?.strapi_stage;
6035
+ const shouldPublish = determineShouldPublish({
6036
+ isDraftAndPublish,
6037
+ hadPublishedVersion,
6038
+ isModified,
6039
+ stageValue: stageVal,
6040
+ publish: Boolean(publish),
6041
+ publishStrategy,
6042
+ unreviewedConsent: options.unreviewedConsent
6043
+ });
5910
6044
  if (shouldPublish) {
5911
6045
  try {
5912
6046
  const pubArgs = { documentId: resolvedDocId };
@@ -5921,7 +6055,7 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5921
6055
  uid,
5922
6056
  documentId: resolvedDocId,
5923
6057
  userId: user?.id,
5924
- statusOverride: shouldPublish ? "published" : isDraftAndPublish ? existing?.publishedAt ? "modified" : "draft" : void 0
6058
+ statusOverride: shouldPublish ? "published" : isDraftAndPublish ? hadPublishedVersion ? "modified" : "draft" : void 0
5925
6059
  });
5926
6060
  } catch {
5927
6061
  }
@@ -5960,8 +6094,17 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5960
6094
  };
5961
6095
  if (effectiveLocale) updateArgs.locale = effectiveLocale;
5962
6096
  await strapi.documents(uid).update(updateArgs);
5963
- const isApproved = !isEditing && isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== "modified";
5964
- const shouldPublish = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : isApproved);
6097
+ const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing);
6098
+ const stageVal = row.strapi_stage ?? row["strapi_stage"] ?? row.stage ?? existing?.strapi_stage;
6099
+ const shouldPublish = determineShouldPublish({
6100
+ isDraftAndPublish,
6101
+ hadPublishedVersion,
6102
+ isModified,
6103
+ stageValue: stageVal,
6104
+ publish: Boolean(publish),
6105
+ publishStrategy,
6106
+ unreviewedConsent: options.unreviewedConsent
6107
+ });
5965
6108
  if (shouldPublish) {
5966
6109
  try {
5967
6110
  const pubArgs = { documentId: resolvedDocId };
@@ -5976,7 +6119,7 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5976
6119
  uid,
5977
6120
  documentId: resolvedDocId,
5978
6121
  userId: user?.id,
5979
- statusOverride: shouldPublish ? "published" : isDraftAndPublish ? existing?.publishedAt ? "modified" : "draft" : void 0
6122
+ statusOverride: shouldPublish ? "published" : isDraftAndPublish ? hadPublishedVersion ? "modified" : "draft" : void 0
5980
6123
  });
5981
6124
  } catch {
5982
6125
  }
@@ -6002,7 +6145,8 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6002
6145
  if (effectiveLocale) createArgs.locale = effectiveLocale;
6003
6146
  const created = await strapi.documents(uid).create(createArgs);
6004
6147
  const newDocId = created?.documentId || docId;
6005
- const shouldPublishNew = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : false);
6148
+ const isApprovedStage = isRowInApprovedStage(row);
6149
+ const shouldPublishNew = !isEditing && !isApprovedStage && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : false);
6006
6150
  if (shouldPublishNew && newDocId) {
6007
6151
  try {
6008
6152
  const pubArgs = { documentId: newDocId };
@@ -6057,8 +6201,17 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6057
6201
  };
6058
6202
  if (effectiveLocale) updateArgs.locale = effectiveLocale;
6059
6203
  await strapi.documents(uid).update(updateArgs);
6060
- const isApproved = !isEditing && isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== "modified";
6061
- const shouldPublish = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : isApproved);
6204
+ const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing);
6205
+ const stageVal = row.strapi_stage ?? row["strapi_stage"] ?? row.stage ?? existing?.strapi_stage;
6206
+ const shouldPublish = determineShouldPublish({
6207
+ isDraftAndPublish,
6208
+ hadPublishedVersion,
6209
+ isModified,
6210
+ stageValue: stageVal,
6211
+ publish: Boolean(publish),
6212
+ publishStrategy,
6213
+ unreviewedConsent: options.unreviewedConsent
6214
+ });
6062
6215
  if (shouldPublish) {
6063
6216
  try {
6064
6217
  const pubArgs = { documentId: resolvedDocId };
@@ -6073,7 +6226,7 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6073
6226
  uid,
6074
6227
  documentId: resolvedDocId,
6075
6228
  userId: user?.id,
6076
- statusOverride: shouldPublish ? "published" : isDraftAndPublish ? existing?.publishedAt ? "modified" : "draft" : void 0
6229
+ statusOverride: shouldPublish ? "published" : isDraftAndPublish ? hadPublishedVersion ? "modified" : "draft" : void 0
6077
6230
  });
6078
6231
  } catch {
6079
6232
  }
@@ -6099,7 +6252,8 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
6099
6252
  if (effectiveLocale) createArgs.locale = effectiveLocale;
6100
6253
  const created = await strapi.documents(uid).create(createArgs);
6101
6254
  const newDocId = created?.documentId || docId;
6102
- const shouldPublishNew = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : false);
6255
+ const isApprovedStage = isRowInApprovedStage(row);
6256
+ const shouldPublishNew = !isEditing && !isApprovedStage && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : false);
6103
6257
  if (shouldPublishNew && newDocId) {
6104
6258
  try {
6105
6259
  const pubArgs = { documentId: newDocId };
@@ -6699,7 +6853,7 @@ const csvService = ({ strapi }) => ({
6699
6853
  const docId = extractDocId(row);
6700
6854
  const rowLocale = extractLocale(row);
6701
6855
  const effectiveLocale = getEffectiveLocale(ct, rowLocale);
6702
- const isEditing = isRowInEditingStage(row);
6856
+ isRowInEditingStage(row);
6703
6857
  let rowHasError = false;
6704
6858
  let existing = null;
6705
6859
  if (docId) {
@@ -6707,15 +6861,27 @@ const csvService = ({ strapi }) => ({
6707
6861
  }
6708
6862
  if (existing && isDraftAndPublish) {
6709
6863
  lifecycleStats.totalChecked++;
6710
- const isApproved = !isEditing && Boolean(existing.publishedAt) && existing.status !== "modified";
6711
- if (isApproved) {
6864
+ const { hadPublishedVersion, isModified } = inspectPreUpdateStatus(existing);
6865
+ const stageVal = row.strapi_stage ?? row["strapi_stage"] ?? row.stage ?? existing?.strapi_stage;
6866
+ const willPublish = determineShouldPublish({
6867
+ isDraftAndPublish,
6868
+ hadPublishedVersion,
6869
+ isModified,
6870
+ stageValue: stageVal,
6871
+ publish: true,
6872
+ publishStrategy: options.publishStrategy || "safe",
6873
+ unreviewedConsent: options.unreviewedConsent
6874
+ });
6875
+ if (willPublish) {
6712
6876
  lifecycleStats.published++;
6713
- } else if (existing.status === "modified" || existing.publishedAt && isEditing) {
6877
+ } else if (hadPublishedVersion && (isModified || isRowInEditingStage(row))) {
6714
6878
  lifecycleStats.modified++;
6715
6879
  lifecycleStats.unreviewedCount++;
6716
- } else {
6880
+ } else if (!hadPublishedVersion) {
6717
6881
  lifecycleStats.draft++;
6718
6882
  lifecycleStats.unreviewedCount++;
6883
+ } else {
6884
+ lifecycleStats.published++;
6719
6885
  }
6720
6886
  }
6721
6887
  if (mode === "update") {