strapi-plugin-bulk-updater 1.5.2 → 1.5.4

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.
@@ -362,10 +362,10 @@ const bulkUpdaterController = ({ strapi }) => ({
362
362
  ctx.set("ETag", data.etag);
363
363
  ctx.set("Cache-Control", "private, no-cache");
364
364
  }
365
- ctx.body = { success: true, ...data };
365
+ ctx.body = { success: true, status: "success", ...data };
366
366
  } catch (err) {
367
367
  ctx.status = 500;
368
- ctx.body = { success: false, error: err.message };
368
+ ctx.body = { success: false, status: "error", error: err.message };
369
369
  }
370
370
  },
371
371
  async getRelationOptions(ctx) {
@@ -967,6 +967,7 @@ function formatEntryRecord(entry) {
967
967
  const formatted = {
968
968
  id: entry.id,
969
969
  documentId: entry.documentId,
970
+ status: entry.status !== void 0 ? entry.status : void 0,
970
971
  ...entry
971
972
  };
972
973
  if (entry.updatedAt !== void 0 && formatted.updated_at === void 0) {
@@ -989,6 +990,119 @@ function formatEntryRecord(entry) {
989
990
  }
990
991
  return formatted;
991
992
  }
993
+ async function populateDocumentLifecycleStatus(strapi, uid, entries) {
994
+ if (!entries || !Array.isArray(entries) || entries.length === 0) {
995
+ return entries;
996
+ }
997
+ const contentType = strapi?.contentTypes?.[uid];
998
+ if (!contentType) {
999
+ return entries;
1000
+ }
1001
+ const hasDraftAndPublish = Boolean(contentType.options?.draftAndPublish);
1002
+ if (!hasDraftAndPublish) {
1003
+ for (const entry of entries) {
1004
+ if (entry && typeof entry === "object") {
1005
+ entry.status = "published";
1006
+ }
1007
+ }
1008
+ return entries;
1009
+ }
1010
+ const hasSlugInSchema = Boolean(contentType.attributes?.slug);
1011
+ const docIds = [];
1012
+ const slugs = [];
1013
+ for (const entry of entries) {
1014
+ if (!entry || typeof entry !== "object") continue;
1015
+ if (entry.documentId) {
1016
+ docIds.push(String(entry.documentId));
1017
+ } else if (hasSlugInSchema && entry.slug) {
1018
+ slugs.push(String(entry.slug));
1019
+ } else {
1020
+ entry.status = "unknown";
1021
+ }
1022
+ }
1023
+ if (docIds.length === 0 && slugs.length === 0) {
1024
+ return entries;
1025
+ }
1026
+ let filterClause;
1027
+ if (docIds.length > 0 && slugs.length > 0) {
1028
+ filterClause = {
1029
+ $or: [
1030
+ { documentId: { $in: docIds } },
1031
+ { slug: { $in: slugs } }
1032
+ ]
1033
+ };
1034
+ } else if (docIds.length > 0) {
1035
+ filterClause = { documentId: { $in: docIds } };
1036
+ } else {
1037
+ filterClause = { slug: { $in: slugs } };
1038
+ }
1039
+ const queryFields = ["documentId", "updatedAt", "publishedAt"];
1040
+ if (hasSlugInSchema) {
1041
+ queryFields.push("slug");
1042
+ }
1043
+ let publishedRecords = [];
1044
+ try {
1045
+ const docService = strapi?.documents?.(uid);
1046
+ if (docService?.findMany) {
1047
+ publishedRecords = await docService.findMany({
1048
+ status: "published",
1049
+ filters: filterClause,
1050
+ fields: queryFields,
1051
+ limit: Math.max(entries.length, 100)
1052
+ });
1053
+ }
1054
+ } catch (err) {
1055
+ strapi?.log?.warn?.(`[bulk-updater] Failed to fetch published status for ${uid}: ${err?.message || err}`);
1056
+ for (const entry of entries) {
1057
+ if (entry && typeof entry === "object" && entry.status !== "unknown") {
1058
+ entry.status = "unknown";
1059
+ }
1060
+ }
1061
+ return entries;
1062
+ }
1063
+ const publishedByDocId = /* @__PURE__ */ new Map();
1064
+ const publishedBySlug = /* @__PURE__ */ new Map();
1065
+ for (const pub of publishedRecords || []) {
1066
+ if (pub?.documentId) {
1067
+ publishedByDocId.set(String(pub.documentId), pub);
1068
+ }
1069
+ if (pub?.slug && hasSlugInSchema) {
1070
+ publishedBySlug.set(String(pub.slug), pub);
1071
+ }
1072
+ }
1073
+ for (const entry of entries) {
1074
+ if (!entry || typeof entry !== "object") continue;
1075
+ if (entry.status === "unknown") continue;
1076
+ const pub = entry.documentId && publishedByDocId.get(String(entry.documentId)) || hasSlugInSchema && entry.slug && publishedBySlug.get(String(entry.slug));
1077
+ if (!pub) {
1078
+ entry.status = "draft";
1079
+ entry.publishedAt = null;
1080
+ entry.published_at = null;
1081
+ } else {
1082
+ entry.publishedAt = pub.publishedAt || pub.published_at || null;
1083
+ entry.published_at = entry.publishedAt;
1084
+ const draftUpdatedTime = new Date(entry.updatedAt || entry.updated_at || 0).getTime();
1085
+ const pubUpdatedTime = new Date(pub.updatedAt || pub.updated_at || 0).getTime();
1086
+ const pubPublishedTime = new Date(pub.publishedAt || pub.published_at || 0).getTime();
1087
+ const lastPublishedTime = Math.max(
1088
+ isNaN(pubUpdatedTime) ? 0 : pubUpdatedTime,
1089
+ isNaN(pubPublishedTime) ? 0 : pubPublishedTime
1090
+ );
1091
+ if (isNaN(draftUpdatedTime) || lastPublishedTime === 0) {
1092
+ if (pub.publishedAt) {
1093
+ entry.status = "published";
1094
+ } else {
1095
+ entry.status = "unknown";
1096
+ }
1097
+ } else if (draftUpdatedTime > lastPublishedTime) {
1098
+ entry.status = "modified";
1099
+ } else {
1100
+ entry.status = "published";
1101
+ }
1102
+ }
1103
+ }
1104
+ return entries;
1105
+ }
992
1106
  function resolveContentTypeField(contentType, field) {
993
1107
  if (!field) return null;
994
1108
  const attrs = contentType?.attributes || {};
@@ -2053,6 +2167,9 @@ const bulkUpdaterService = ({ strapi }) => {
2053
2167
  isRunnerRunning = false;
2054
2168
  }
2055
2169
  }, 3e4);
2170
+ if (typeof runnerInterval.unref === "function") {
2171
+ runnerInterval.unref();
2172
+ }
2056
2173
  }
2057
2174
  return {
2058
2175
  /**
@@ -2255,6 +2372,7 @@ const bulkUpdaterService = ({ strapi }) => {
2255
2372
  totalCount = 0;
2256
2373
  }
2257
2374
  const formattedEntries = (entries || []).map(formatEntryRecord);
2375
+ await populateDocumentLifecycleStatus(strapi, uid, formattedEntries);
2258
2376
  modelsCache.set(uid, {
2259
2377
  signature,
2260
2378
  totalCount,
@@ -2370,6 +2488,7 @@ const bulkUpdaterService = ({ strapi }) => {
2370
2488
  if (!colHasAttribute) {
2371
2489
  result = {
2372
2490
  uid,
2491
+ status: "success",
2373
2492
  displayName: contentType.info?.displayName || uid,
2374
2493
  isSingleType,
2375
2494
  draftAndPublish: Boolean(contentType.options?.draftAndPublish),
@@ -2511,12 +2630,15 @@ const bulkUpdaterService = ({ strapi }) => {
2511
2630
  } catch {
2512
2631
  singleDoc = null;
2513
2632
  }
2633
+ const formattedEntries = singleDoc ? [formatEntryRecord(singleDoc)] : [];
2634
+ await populateDocumentLifecycleStatus(strapi, uid, formattedEntries);
2514
2635
  result = {
2515
2636
  uid,
2637
+ status: "success",
2516
2638
  displayName: contentType.info?.displayName || uid,
2517
2639
  isSingleType: true,
2518
2640
  draftAndPublish: Boolean(contentType.options?.draftAndPublish),
2519
- entries: singleDoc ? [formatEntryRecord(singleDoc)] : [],
2641
+ entries: formattedEntries,
2520
2642
  pagination: {
2521
2643
  page: 1,
2522
2644
  pageSize: 1,
@@ -2603,12 +2725,15 @@ const bulkUpdaterService = ({ strapi }) => {
2603
2725
  const matchedEntries = (rawEntries || []).filter(passesDzFilter);
2604
2726
  const totalEntries = matchedEntries.length;
2605
2727
  const paginatedEntries = matchedEntries.slice(start, start + limit);
2728
+ const formattedEntries = paginatedEntries.map(formatEntryRecord);
2729
+ await populateDocumentLifecycleStatus(strapi, uid, formattedEntries);
2606
2730
  result = {
2607
2731
  uid,
2732
+ status: "success",
2608
2733
  displayName: contentType.info?.displayName || uid,
2609
2734
  isSingleType: false,
2610
2735
  draftAndPublish: Boolean(contentType.options?.draftAndPublish),
2611
- entries: paginatedEntries.map(formatEntryRecord),
2736
+ entries: formattedEntries,
2612
2737
  pagination: {
2613
2738
  page: currentPage,
2614
2739
  pageSize: limit,
@@ -2632,12 +2757,15 @@ const bulkUpdaterService = ({ strapi }) => {
2632
2757
  filters: Object.keys(filters).length > 0 ? filters : void 0
2633
2758
  })
2634
2759
  ]);
2760
+ const formattedEntries = (entries || []).map(formatEntryRecord);
2761
+ await populateDocumentLifecycleStatus(strapi, uid, formattedEntries);
2635
2762
  result = {
2636
2763
  uid,
2764
+ status: "success",
2637
2765
  displayName: contentType.info?.displayName || uid,
2638
2766
  isSingleType: false,
2639
2767
  draftAndPublish: Boolean(contentType.options?.draftAndPublish),
2640
- entries: (entries || []).map(formatEntryRecord),
2768
+ entries: formattedEntries,
2641
2769
  pagination: {
2642
2770
  page: currentPage,
2643
2771
  pageSize: limit,