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