strapi-plugin-bulk-updater 1.5.4 → 1.5.5

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.
@@ -5141,7 +5141,14 @@ const LIFECYCLE_STATUS_WORDS = /* @__PURE__ */ new Set([
5141
5141
  "published",
5142
5142
  "modified",
5143
5143
  "supported",
5144
- "ignored"
5144
+ "ignored",
5145
+ "editing",
5146
+ "in review",
5147
+ "in_review",
5148
+ "ready to publish",
5149
+ "ready_to_publish",
5150
+ "null",
5151
+ "undefined"
5145
5152
  ]);
5146
5153
  function isValidDocId(val) {
5147
5154
  if (!val || typeof val !== "string") return false;
@@ -5177,17 +5184,82 @@ function extractDocId(row) {
5177
5184
  }
5178
5185
  function extractLocale(row) {
5179
5186
  if (!row || typeof row !== "object") return void 0;
5180
- const candidates = [row.locale, row.Locale, row["locale"], row["Locale"]];
5187
+ const candidates = [
5188
+ row.locale,
5189
+ row.Locale,
5190
+ row["locale"],
5191
+ row["Locale"],
5192
+ row.strapi_locale,
5193
+ row["strapi_locale"]
5194
+ ];
5181
5195
  for (const c of candidates) {
5182
5196
  if (c !== void 0 && c !== null) {
5183
5197
  const str = String(c).trim();
5184
- if (str && str.toLowerCase() !== "null" && str.toLowerCase() !== "undefined") {
5198
+ if (str && str.toLowerCase() !== "null" && str.toLowerCase() !== "undefined" && str.toLowerCase() !== "[null]" && str.toLowerCase() !== '""') {
5185
5199
  return str;
5186
5200
  }
5187
5201
  }
5188
5202
  }
5189
5203
  return void 0;
5190
5204
  }
5205
+ function getEffectiveLocale(ct, rowLocale) {
5206
+ if (!ct?.pluginOptions?.i18n?.localized) {
5207
+ return void 0;
5208
+ }
5209
+ if (!rowLocale) {
5210
+ return void 0;
5211
+ }
5212
+ const trimmed = rowLocale.trim();
5213
+ if (!trimmed || trimmed.toLowerCase() === "null" || trimmed.toLowerCase() === "undefined" || trimmed.toLowerCase() === "[null]" || trimmed.toLowerCase() === '""') {
5214
+ return void 0;
5215
+ }
5216
+ return trimmed;
5217
+ }
5218
+ function isRowInEditingStage(row) {
5219
+ if (!row || typeof row !== "object") return false;
5220
+ const candidates = [
5221
+ row.strapi_stage,
5222
+ row["strapi_stage"],
5223
+ row.strapiStage,
5224
+ row["Strapi Stage"],
5225
+ row["strapi-stage"],
5226
+ row.stage,
5227
+ row.Stage,
5228
+ row.status,
5229
+ row.Status
5230
+ ];
5231
+ for (const c of candidates) {
5232
+ if (c !== void 0 && c !== null) {
5233
+ let stageName = "";
5234
+ if (typeof c === "object") {
5235
+ stageName = String(c.name || c.title || c.status || c.documentId || c.id || "").trim();
5236
+ } else if (typeof c === "string") {
5237
+ const trimmed = c.trim();
5238
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
5239
+ try {
5240
+ const parsed = JSON.parse(trimmed);
5241
+ if (typeof parsed === "object" && parsed !== null) {
5242
+ stageName = String(parsed.name || parsed.title || parsed.status || parsed.documentId || parsed.id || "").trim();
5243
+ }
5244
+ } catch {
5245
+ }
5246
+ }
5247
+ if (!stageName) {
5248
+ stageName = trimmed;
5249
+ }
5250
+ } else {
5251
+ stageName = String(c).trim();
5252
+ }
5253
+ if (stageName) {
5254
+ const s = stageName.toLowerCase();
5255
+ if (s === "editing" || s === "in review" || s === "in_review" || s === "pending review" || s === "pending_review") {
5256
+ return true;
5257
+ }
5258
+ }
5259
+ }
5260
+ }
5261
+ return false;
5262
+ }
5191
5263
  function extractDetailedErrorMessage(err) {
5192
5264
  if (!err) return "Error processing row";
5193
5265
  const detailsErrors = err.details?.errors || err.error?.details?.errors;
@@ -5322,19 +5394,26 @@ function getNestedExportValue(entry, path) {
5322
5394
  }
5323
5395
  }
5324
5396
  if (current === null || current === void 0) return "";
5397
+ if (Array.isArray(current) && current.length > 0 && current[0]?.type && Array.isArray(current[0]?.children)) {
5398
+ return JSON.stringify(current);
5399
+ }
5325
5400
  if (typeof current === "object" && current.url) {
5326
5401
  return current.url;
5327
5402
  }
5328
5403
  if (typeof current === "object" && !Array.isArray(current)) {
5329
- if (current.documentId || current.name || current.title) {
5330
- return current.name || current.title || current.documentId;
5404
+ if (current.name && (current.locale === null || !current.documentId)) {
5405
+ return current.name;
5406
+ }
5407
+ if (current.documentId || current.id || current.name || current.title) {
5408
+ return current.documentId || current.id || current.name || current.title;
5331
5409
  }
5332
5410
  }
5333
5411
  if (Array.isArray(current)) {
5334
5412
  return current.map((item) => {
5335
5413
  if (!item) return "";
5336
5414
  if (typeof item === "object") {
5337
- return item.name || item.title || item.documentId || JSON.stringify(item);
5415
+ if (item.url) return item.url;
5416
+ return item.documentId || item.id || item.name || item.title || JSON.stringify(item);
5338
5417
  }
5339
5418
  return String(item);
5340
5419
  }).filter(Boolean).join("; ");
@@ -5362,24 +5441,42 @@ const SYSTEM_FIELD_KEYS = /* @__PURE__ */ new Set([
5362
5441
  "updatedby",
5363
5442
  "localizations",
5364
5443
  "locale",
5365
- "status"
5444
+ "status",
5445
+ "strapistage",
5446
+ "strapi_stage",
5447
+ "strapiassignee",
5448
+ "strapi_assignee",
5449
+ "strapistatus",
5450
+ "strapi_status"
5366
5451
  ]);
5367
5452
  async function findExistingDocument(strapi, uid, targetDocId, docLocale) {
5368
5453
  if (!targetDocId) return null;
5454
+ const ct = strapi.contentTypes[uid];
5455
+ const effectiveLocale = getEffectiveLocale(ct, docLocale);
5369
5456
  try {
5370
5457
  const queryArgs = { documentId: targetDocId };
5371
- if (docLocale) queryArgs.locale = docLocale;
5458
+ if (effectiveLocale) queryArgs.locale = effectiveLocale;
5372
5459
  const found = await strapi.documents(uid).findOne(queryArgs);
5373
5460
  if (found) return found;
5374
5461
  } catch {
5375
5462
  }
5463
+ if (ct?.pluginOptions?.i18n?.localized && !effectiveLocale) {
5464
+ try {
5465
+ const list = await strapi.documents(uid).findMany({
5466
+ filters: { documentId: targetDocId },
5467
+ limit: 1
5468
+ });
5469
+ if (list && list.length > 0) return list[0];
5470
+ } catch {
5471
+ }
5472
+ }
5376
5473
  if (/^\d+$/.test(targetDocId)) {
5377
5474
  try {
5378
5475
  const queryArgs = {
5379
5476
  filters: { id: parseInt(targetDocId, 10) },
5380
5477
  limit: 1
5381
5478
  };
5382
- if (docLocale) queryArgs.locale = docLocale;
5479
+ if (effectiveLocale) queryArgs.locale = effectiveLocale;
5383
5480
  const list = await strapi.documents(uid).findMany(queryArgs);
5384
5481
  if (list && list.length > 0) return list[0];
5385
5482
  } catch {
@@ -5404,12 +5501,129 @@ function deepMergeComponent(existingVal, newVal) {
5404
5501
  }
5405
5502
  return merged;
5406
5503
  }
5504
+ function parseNumberValue(rawVal, isInteger) {
5505
+ const cleanStr = String(rawVal).replace(/[$€£,\s]/g, "");
5506
+ if (isInteger) {
5507
+ const n = parseInt(cleanStr, 10);
5508
+ return isNaN(n) ? null : n;
5509
+ } else {
5510
+ const f = parseFloat(cleanStr);
5511
+ return isNaN(f) ? null : f;
5512
+ }
5513
+ }
5514
+ function parseBooleanValue(rawVal) {
5515
+ const s = String(rawVal).trim().toLowerCase();
5516
+ return s === "true" || s === "1" || s === "yes" || s === "y" || s === "on";
5517
+ }
5518
+ function parseBlocksValue(rawVal) {
5519
+ try {
5520
+ const parsed = JSON.parse(rawVal);
5521
+ if (Array.isArray(parsed)) {
5522
+ return parsed;
5523
+ }
5524
+ } catch {
5525
+ }
5526
+ const trimmed = String(rawVal).trim();
5527
+ if (!trimmed) return [];
5528
+ return [{ type: "paragraph", children: [{ type: "text", text: trimmed }] }];
5529
+ }
5530
+ function parseEnumValue(rawVal, allowedValues) {
5531
+ const trimmed = String(rawVal).trim();
5532
+ if (Array.isArray(allowedValues) && allowedValues.length > 0) {
5533
+ const match = allowedValues.find((v) => v.toLowerCase() === trimmed.toLowerCase());
5534
+ if (match) return match;
5535
+ }
5536
+ return trimmed;
5537
+ }
5538
+ function parseRelationValue(rawVal, relationType) {
5539
+ const isToMany = relationType ? relationType.toLowerCase().endsWith("many") : false;
5540
+ if (rawVal === null || rawVal === void 0) return isToMany ? [] : null;
5541
+ let parsed = rawVal;
5542
+ if (typeof rawVal === "string") {
5543
+ const trimmed = rawVal.trim();
5544
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
5545
+ try {
5546
+ parsed = JSON.parse(trimmed);
5547
+ } catch {
5548
+ }
5549
+ }
5550
+ }
5551
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
5552
+ if (parsed.name && (parsed.locale === null || LIFECYCLE_STATUS_WORDS.has(String(parsed.name).trim().toLowerCase()))) {
5553
+ return isToMany ? [] : null;
5554
+ }
5555
+ const docId = parsed.documentId || parsed.id || null;
5556
+ if (docId && isValidDocId(String(docId).trim())) {
5557
+ const validStr = String(docId).trim();
5558
+ return isToMany ? [validStr] : validStr;
5559
+ }
5560
+ return isToMany ? [] : null;
5561
+ }
5562
+ if (Array.isArray(parsed)) {
5563
+ const ids = parsed.map((item) => {
5564
+ if (typeof item === "object" && item !== null) {
5565
+ if (item.name && (item.locale === null || LIFECYCLE_STATUS_WORDS.has(String(item.name).trim().toLowerCase()))) {
5566
+ return null;
5567
+ }
5568
+ const id = item.documentId || item.id;
5569
+ return id && isValidDocId(String(id).trim()) ? String(id).trim() : null;
5570
+ }
5571
+ return isValidDocId(String(item).trim()) ? String(item).trim() : null;
5572
+ }).filter(Boolean);
5573
+ return isToMany ? ids : ids[0] || null;
5574
+ }
5575
+ if (typeof rawVal === "string") {
5576
+ if (rawVal.includes(";") || rawVal.includes(",")) {
5577
+ const parts = rawVal.split(/[;,]/).map((s) => s.trim()).filter((p) => isValidDocId(p));
5578
+ return isToMany ? parts : parts[0] || null;
5579
+ }
5580
+ const trimmed = rawVal.trim();
5581
+ if (isValidDocId(trimmed)) {
5582
+ return isToMany ? [trimmed] : trimmed;
5583
+ }
5584
+ }
5585
+ return isToMany ? [] : null;
5586
+ }
5587
+ function parseMediaValue(rawVal, isMultiple = false) {
5588
+ const trimmed = String(rawVal).trim();
5589
+ if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
5590
+ try {
5591
+ const parsed = JSON.parse(trimmed);
5592
+ if (Array.isArray(parsed)) {
5593
+ const ids = parsed.map((item) => typeof item === "object" && item !== null ? item.id || item.documentId : item).filter(Boolean);
5594
+ return isMultiple ? ids : ids[0] || null;
5595
+ }
5596
+ if (typeof parsed === "number") {
5597
+ return isMultiple ? [parsed] : parsed;
5598
+ }
5599
+ if (typeof parsed === "object" && parsed !== null) {
5600
+ const id = parsed.id || parsed.documentId || parsed;
5601
+ return isMultiple ? [id] : id;
5602
+ }
5603
+ } catch {
5604
+ }
5605
+ }
5606
+ if (rawVal.includes(";") || rawVal.includes(",")) {
5607
+ const parts = rawVal.split(/[;,]/).map((s) => s.trim()).filter(Boolean).map((s) => /^\d+$/.test(s) ? parseInt(s, 10) : s);
5608
+ return isMultiple ? parts : parts[0] || null;
5609
+ }
5610
+ if (/^\d+$/.test(trimmed)) {
5611
+ const numId = parseInt(trimmed, 10);
5612
+ return isMultiple ? [numId] : numId;
5613
+ }
5614
+ if (isValidDocId(trimmed)) {
5615
+ return isMultiple ? [trimmed] : trimmed;
5616
+ }
5617
+ return isMultiple ? [] : null;
5618
+ }
5407
5619
  function parseRowToPayload(strapi, attrs, row) {
5408
5620
  const payload = {};
5409
5621
  for (const [key, rawVal] of Object.entries(row)) {
5410
5622
  const normalizedKey = key.toLowerCase().replace(/[\s_-]/g, "");
5411
5623
  if (SYSTEM_FIELD_KEYS.has(normalizedKey)) continue;
5412
5624
  if (key.includes(".")) {
5625
+ const topPart = key.split(".")[0].toLowerCase().replace(/[\s_-]/g, "");
5626
+ if (SYSTEM_FIELD_KEYS.has(topPart)) continue;
5413
5627
  const parts = key.split(".");
5414
5628
  let currentAttrs = attrs;
5415
5629
  let currentTarget = payload;
@@ -5428,17 +5642,31 @@ function parseRowToPayload(strapi, attrs, row) {
5428
5642
  break;
5429
5643
  }
5430
5644
  if (rawVal === "" || rawVal === null || rawVal === void 0) {
5431
- if (leafDef.type !== "dynamiczone" && !(leafDef.type === "component" && leafDef.repeatable) && leafDef.type !== "relation") {
5645
+ if (leafDef.type !== "dynamiczone" && !(leafDef.type === "component" && leafDef.repeatable) && leafDef.type !== "relation" && leafDef.type !== "password") {
5432
5646
  currentTarget[part] = null;
5433
5647
  }
5434
5648
  } else if (leafDef.type === "integer" || leafDef.type === "biginteger") {
5435
- const parsedInt = parseInt(rawVal, 10);
5436
- currentTarget[part] = isNaN(parsedInt) ? null : parsedInt;
5649
+ currentTarget[part] = parseNumberValue(rawVal, true);
5437
5650
  } else if (leafDef.type === "float" || leafDef.type === "decimal") {
5438
- const parsedFloat = parseFloat(rawVal);
5439
- currentTarget[part] = isNaN(parsedFloat) ? null : parsedFloat;
5651
+ currentTarget[part] = parseNumberValue(rawVal, false);
5440
5652
  } else if (leafDef.type === "boolean") {
5441
- currentTarget[part] = rawVal.toLowerCase() === "true" || rawVal === "1";
5653
+ currentTarget[part] = parseBooleanValue(rawVal);
5654
+ } else if (leafDef.type === "blocks") {
5655
+ currentTarget[part] = parseBlocksValue(rawVal);
5656
+ } else if (leafDef.type === "enumeration") {
5657
+ currentTarget[part] = parseEnumValue(rawVal, leafDef.enum);
5658
+ } else if (leafDef.type === "relation") {
5659
+ currentTarget[part] = parseRelationValue(rawVal, leafDef.relation);
5660
+ } else if (leafDef.type === "media") {
5661
+ currentTarget[part] = parseMediaValue(rawVal, Boolean(leafDef.multiple));
5662
+ } else if (leafDef.type === "date" || leafDef.type === "time" || leafDef.type === "datetime" || leafDef.type === "timestamp") {
5663
+ currentTarget[part] = String(rawVal).trim() || null;
5664
+ } else if (leafDef.type === "email" || leafDef.type === "uid") {
5665
+ currentTarget[part] = String(rawVal).trim();
5666
+ } else if (leafDef.type === "password") {
5667
+ if (String(rawVal).trim()) {
5668
+ currentTarget[part] = String(rawVal).trim();
5669
+ }
5442
5670
  } else if (leafDef.type === "json") {
5443
5671
  try {
5444
5672
  currentTarget[part] = JSON.parse(rawVal);
@@ -5453,19 +5681,6 @@ function parseRowToPayload(strapi, attrs, row) {
5453
5681
  }
5454
5682
  } catch {
5455
5683
  }
5456
- } else if (leafDef.type === "relation") {
5457
- try {
5458
- const parsed = JSON.parse(rawVal);
5459
- if (Array.isArray(parsed) || typeof parsed === "object" && parsed !== null) {
5460
- currentTarget[part] = parsed;
5461
- } else if (isValidDocId(rawVal)) {
5462
- currentTarget[part] = rawVal;
5463
- }
5464
- } catch {
5465
- if (isValidDocId(rawVal)) {
5466
- currentTarget[part] = rawVal;
5467
- }
5468
- }
5469
5684
  } else {
5470
5685
  currentTarget[part] = rawVal;
5471
5686
  }
@@ -5504,27 +5719,53 @@ function parseRowToPayload(strapi, attrs, row) {
5504
5719
  }
5505
5720
  }
5506
5721
  if (!attrDef) continue;
5722
+ if (attrDef?.target?.includes("review-workflow") || attrDef?.target === "admin::review-workflow-stage") {
5723
+ continue;
5724
+ }
5507
5725
  if (rawVal === "" || rawVal === null || rawVal === void 0) {
5508
- if (attrDef.type !== "dynamiczone" && !(attrDef.type === "component" && attrDef.repeatable)) {
5726
+ if (attrDef.type !== "dynamiczone" && !(attrDef.type === "component" && attrDef.repeatable) && attrDef.type !== "relation" && attrDef.type !== "password") {
5509
5727
  payload[key] = null;
5510
5728
  }
5511
5729
  continue;
5512
5730
  }
5513
5731
  switch (attrDef.type) {
5514
5732
  case "integer":
5515
- case "biginteger": {
5516
- const parsedInt = parseInt(rawVal, 10);
5517
- payload[key] = isNaN(parsedInt) ? null : parsedInt;
5733
+ case "biginteger":
5734
+ payload[key] = parseNumberValue(rawVal, true);
5518
5735
  break;
5519
- }
5520
5736
  case "float":
5521
- case "decimal": {
5522
- const parsedFloat = parseFloat(rawVal);
5523
- payload[key] = isNaN(parsedFloat) ? null : parsedFloat;
5737
+ case "decimal":
5738
+ payload[key] = parseNumberValue(rawVal, false);
5524
5739
  break;
5525
- }
5526
5740
  case "boolean":
5527
- payload[key] = rawVal.toLowerCase() === "true" || rawVal === "1";
5741
+ payload[key] = parseBooleanValue(rawVal);
5742
+ break;
5743
+ case "blocks":
5744
+ payload[key] = parseBlocksValue(rawVal);
5745
+ break;
5746
+ case "enumeration":
5747
+ payload[key] = parseEnumValue(rawVal, attrDef.enum);
5748
+ break;
5749
+ case "relation":
5750
+ payload[key] = parseRelationValue(rawVal, attrDef.relation);
5751
+ break;
5752
+ case "media":
5753
+ payload[key] = parseMediaValue(rawVal, Boolean(attrDef.multiple));
5754
+ break;
5755
+ case "date":
5756
+ case "time":
5757
+ case "datetime":
5758
+ case "timestamp":
5759
+ payload[key] = String(rawVal).trim() || null;
5760
+ break;
5761
+ case "email":
5762
+ case "uid":
5763
+ payload[key] = String(rawVal).trim();
5764
+ break;
5765
+ case "password":
5766
+ if (String(rawVal).trim()) {
5767
+ payload[key] = String(rawVal).trim();
5768
+ }
5528
5769
  break;
5529
5770
  case "json":
5530
5771
  try {
@@ -5563,39 +5804,6 @@ function parseRowToPayload(strapi, attrs, row) {
5563
5804
  }
5564
5805
  break;
5565
5806
  }
5566
- case "relation": {
5567
- try {
5568
- const parsed = JSON.parse(rawVal);
5569
- if (Array.isArray(parsed) || typeof parsed === "object" && parsed !== null) {
5570
- payload[key] = parsed;
5571
- break;
5572
- }
5573
- } catch {
5574
- }
5575
- if (isValidDocId(rawVal)) {
5576
- payload[key] = rawVal;
5577
- } else if (rawVal.includes(";") || rawVal.includes(",")) {
5578
- const parts = rawVal.split(/[;,]/).map((s) => s.trim()).filter(Boolean);
5579
- if (parts.length > 0 && parts.every((p) => isValidDocId(p))) {
5580
- payload[key] = parts;
5581
- }
5582
- }
5583
- break;
5584
- }
5585
- case "media": {
5586
- if (/^\d+$/.test(rawVal.trim())) {
5587
- payload[key] = parseInt(rawVal.trim(), 10);
5588
- } else {
5589
- try {
5590
- const parsed = JSON.parse(rawVal);
5591
- if (typeof parsed === "number" || typeof parsed === "object") {
5592
- payload[key] = parsed;
5593
- }
5594
- } catch {
5595
- }
5596
- }
5597
- break;
5598
- }
5599
5807
  default:
5600
5808
  payload[key] = rawVal;
5601
5809
  }
@@ -5632,10 +5840,12 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5632
5840
  const row = rows[i];
5633
5841
  let docId = extractDocId(row);
5634
5842
  const rowLocale = extractLocale(row);
5843
+ const effectiveLocale = getEffectiveLocale(ct, rowLocale);
5844
+ const isEditing = isRowInEditingStage(row);
5635
5845
  if (ct.kind === "singleType" && !docId) {
5636
5846
  try {
5637
5847
  const findSingleArgs = {};
5638
- if (rowLocale) findSingleArgs.locale = rowLocale;
5848
+ if (effectiveLocale) findSingleArgs.locale = effectiveLocale;
5639
5849
  const singleDoc = await strapi.documents(uid).findFirst(findSingleArgs);
5640
5850
  if (singleDoc?.documentId) {
5641
5851
  docId = singleDoc.documentId;
@@ -5654,7 +5864,7 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5654
5864
  });
5655
5865
  continue;
5656
5866
  }
5657
- const existing = await findExistingDocument(strapi, uid, docId, rowLocale);
5867
+ const existing = await findExistingDocument(strapi, uid, docId, effectiveLocale);
5658
5868
  if (!existing) {
5659
5869
  stats.skipped++;
5660
5870
  stats.errors.push({
@@ -5690,14 +5900,14 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5690
5900
  documentId: resolvedDocId,
5691
5901
  data: mergedPayload
5692
5902
  };
5693
- if (rowLocale) updateArgs.locale = rowLocale;
5903
+ if (effectiveLocale) updateArgs.locale = effectiveLocale;
5694
5904
  await strapi.documents(uid).update(updateArgs);
5695
- const isApproved = isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== "modified";
5696
- const shouldPublish = isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : isApproved);
5905
+ const isApproved = !isEditing && isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== "modified";
5906
+ const shouldPublish = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : isApproved);
5697
5907
  if (shouldPublish) {
5698
5908
  try {
5699
5909
  const pubArgs = { documentId: resolvedDocId };
5700
- if (rowLocale) pubArgs.locale = rowLocale;
5910
+ if (effectiveLocale) pubArgs.locale = effectiveLocale;
5701
5911
  await strapi.documents(uid).publish(pubArgs);
5702
5912
  } catch (pubErr) {
5703
5913
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);
@@ -5708,7 +5918,7 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5708
5918
  uid,
5709
5919
  documentId: resolvedDocId,
5710
5920
  userId: user?.id,
5711
- statusOverride: shouldPublish ? "published" : isDraftAndPublish ? "draft" : void 0
5921
+ statusOverride: shouldPublish ? "published" : isDraftAndPublish ? existing?.publishedAt ? "modified" : "draft" : void 0
5712
5922
  });
5713
5923
  } catch {
5714
5924
  }
@@ -5731,7 +5941,7 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5731
5941
  } else if (mode === "create_or_override") {
5732
5942
  let existing = null;
5733
5943
  if (docId) {
5734
- existing = await findExistingDocument(strapi, uid, docId, rowLocale);
5944
+ existing = await findExistingDocument(strapi, uid, docId, effectiveLocale);
5735
5945
  }
5736
5946
  if (existing) {
5737
5947
  const resolvedDocId = existing.documentId || docId;
@@ -5745,14 +5955,14 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5745
5955
  documentId: resolvedDocId,
5746
5956
  data: mergedPayload
5747
5957
  };
5748
- if (rowLocale) updateArgs.locale = rowLocale;
5958
+ if (effectiveLocale) updateArgs.locale = effectiveLocale;
5749
5959
  await strapi.documents(uid).update(updateArgs);
5750
- const isApproved = isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== "modified";
5751
- const shouldPublish = isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : isApproved);
5960
+ const isApproved = !isEditing && isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== "modified";
5961
+ const shouldPublish = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : isApproved);
5752
5962
  if (shouldPublish) {
5753
5963
  try {
5754
5964
  const pubArgs = { documentId: resolvedDocId };
5755
- if (rowLocale) pubArgs.locale = rowLocale;
5965
+ if (effectiveLocale) pubArgs.locale = effectiveLocale;
5756
5966
  await strapi.documents(uid).publish(pubArgs);
5757
5967
  } catch (pubErr) {
5758
5968
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);
@@ -5763,7 +5973,7 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5763
5973
  uid,
5764
5974
  documentId: resolvedDocId,
5765
5975
  userId: user?.id,
5766
- statusOverride: shouldPublish ? "published" : isDraftAndPublish ? "draft" : void 0
5976
+ statusOverride: shouldPublish ? "published" : isDraftAndPublish ? existing?.publishedAt ? "modified" : "draft" : void 0
5767
5977
  });
5768
5978
  } catch {
5769
5979
  }
@@ -5786,14 +5996,14 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5786
5996
  continue;
5787
5997
  }
5788
5998
  const createArgs = { data: payload };
5789
- if (rowLocale) createArgs.locale = rowLocale;
5999
+ if (effectiveLocale) createArgs.locale = effectiveLocale;
5790
6000
  const created = await strapi.documents(uid).create(createArgs);
5791
6001
  const newDocId = created?.documentId || docId;
5792
- const shouldPublishNew = isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : false);
6002
+ const shouldPublishNew = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : false);
5793
6003
  if (shouldPublishNew && newDocId) {
5794
6004
  try {
5795
6005
  const pubArgs = { documentId: newDocId };
5796
- if (rowLocale) pubArgs.locale = rowLocale;
6006
+ if (effectiveLocale) pubArgs.locale = effectiveLocale;
5797
6007
  await strapi.documents(uid).publish(pubArgs);
5798
6008
  } catch (pubErr) {
5799
6009
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);
@@ -5828,7 +6038,7 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5828
6038
  } else {
5829
6039
  let existing = null;
5830
6040
  if (docId) {
5831
- existing = await findExistingDocument(strapi, uid, docId, rowLocale);
6041
+ existing = await findExistingDocument(strapi, uid, docId, effectiveLocale);
5832
6042
  }
5833
6043
  if (existing) {
5834
6044
  const resolvedDocId = existing.documentId || docId;
@@ -5842,14 +6052,14 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5842
6052
  documentId: resolvedDocId,
5843
6053
  data: mergedPayload
5844
6054
  };
5845
- if (rowLocale) updateArgs.locale = rowLocale;
6055
+ if (effectiveLocale) updateArgs.locale = effectiveLocale;
5846
6056
  await strapi.documents(uid).update(updateArgs);
5847
- const isApproved = isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== "modified";
5848
- const shouldPublish = isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : isApproved);
6057
+ const isApproved = !isEditing && isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== "modified";
6058
+ const shouldPublish = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : isApproved);
5849
6059
  if (shouldPublish) {
5850
6060
  try {
5851
6061
  const pubArgs = { documentId: resolvedDocId };
5852
- if (rowLocale) pubArgs.locale = rowLocale;
6062
+ if (effectiveLocale) pubArgs.locale = effectiveLocale;
5853
6063
  await strapi.documents(uid).publish(pubArgs);
5854
6064
  } catch (pubErr) {
5855
6065
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);
@@ -5860,7 +6070,7 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5860
6070
  uid,
5861
6071
  documentId: resolvedDocId,
5862
6072
  userId: user?.id,
5863
- statusOverride: shouldPublish ? "published" : isDraftAndPublish ? "draft" : void 0
6073
+ statusOverride: shouldPublish ? "published" : isDraftAndPublish ? existing?.publishedAt ? "modified" : "draft" : void 0
5864
6074
  });
5865
6075
  } catch {
5866
6076
  }
@@ -5883,14 +6093,14 @@ async function processCsvRows(strapi, ct, uid, rows, startRowNumber, options) {
5883
6093
  continue;
5884
6094
  }
5885
6095
  const createArgs = { data: payload };
5886
- if (rowLocale) createArgs.locale = rowLocale;
6096
+ if (effectiveLocale) createArgs.locale = effectiveLocale;
5887
6097
  const created = await strapi.documents(uid).create(createArgs);
5888
6098
  const newDocId = created?.documentId || docId;
5889
- const shouldPublishNew = isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : false);
6099
+ const shouldPublishNew = !isEditing && isDraftAndPublish && Boolean(publish) && (publishStrategy === "all" || options.unreviewedConsent ? true : false);
5890
6100
  if (shouldPublishNew && newDocId) {
5891
6101
  try {
5892
6102
  const pubArgs = { documentId: newDocId };
5893
- if (rowLocale) pubArgs.locale = rowLocale;
6103
+ if (effectiveLocale) pubArgs.locale = effectiveLocale;
5894
6104
  await strapi.documents(uid).publish(pubArgs);
5895
6105
  } catch (pubErr) {
5896
6106
  strapi.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);
@@ -6485,17 +6695,19 @@ const csvService = ({ strapi }) => ({
6485
6695
  const row = rows[i];
6486
6696
  const docId = extractDocId(row);
6487
6697
  const rowLocale = extractLocale(row);
6698
+ const effectiveLocale = getEffectiveLocale(ct, rowLocale);
6699
+ const isEditing = isRowInEditingStage(row);
6488
6700
  let rowHasError = false;
6489
6701
  let existing = null;
6490
6702
  if (docId) {
6491
- existing = await findExistingDocument(strapi, uid, docId, rowLocale);
6703
+ existing = await findExistingDocument(strapi, uid, docId, effectiveLocale);
6492
6704
  }
6493
6705
  if (existing && isDraftAndPublish) {
6494
6706
  lifecycleStats.totalChecked++;
6495
- const isApproved = Boolean(existing.publishedAt) && existing.status !== "modified";
6707
+ const isApproved = !isEditing && Boolean(existing.publishedAt) && existing.status !== "modified";
6496
6708
  if (isApproved) {
6497
6709
  lifecycleStats.published++;
6498
- } else if (existing.status === "modified") {
6710
+ } else if (existing.status === "modified" || existing.publishedAt && isEditing) {
6499
6711
  lifecycleStats.modified++;
6500
6712
  lifecycleStats.unreviewedCount++;
6501
6713
  } else {
@@ -6651,10 +6863,11 @@ const csvService = ({ strapi }) => ({
6651
6863
  const row = rows[i];
6652
6864
  let docId = extractDocId(row);
6653
6865
  const rowLocale = extractLocale(row);
6866
+ const effectiveLocale = getEffectiveLocale(ct, rowLocale);
6654
6867
  if (ct.kind === "singleType" && !docId) {
6655
6868
  try {
6656
6869
  const findSingleArgs = {};
6657
- if (rowLocale) findSingleArgs.locale = rowLocale;
6870
+ if (effectiveLocale) findSingleArgs.locale = effectiveLocale;
6658
6871
  const singleDoc = await strapi.documents(uid).findFirst(findSingleArgs);
6659
6872
  if (singleDoc?.documentId) {
6660
6873
  docId = singleDoc.documentId;
@@ -6664,7 +6877,7 @@ const csvService = ({ strapi }) => ({
6664
6877
  }
6665
6878
  let existing = null;
6666
6879
  if (docId) {
6667
- existing = await findExistingDocument(strapi, uid, docId, rowLocale);
6880
+ existing = await findExistingDocument(strapi, uid, docId, effectiveLocale);
6668
6881
  }
6669
6882
  if (mode === "update" && (!docId || !existing)) {
6670
6883
  skippedCount++;