strapi-plugin-bulk-updater 1.3.3 → 1.3.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.
@@ -688,6 +688,149 @@ const csvController = ({ strapi: strapi2 }) => ({
688
688
  }
689
689
  }
690
690
  });
691
+ const FIELDS_TO_IGNORE = [
692
+ "createdAt",
693
+ "updatedAt",
694
+ "publishedAt",
695
+ "createdBy",
696
+ "updatedBy",
697
+ "strapi_stage",
698
+ "strapi_assignee"
699
+ ];
700
+ function buildHistoryPopulate(attributes, allComponents, depth2 = 0) {
701
+ if (depth2 > 5) return void 0;
702
+ const populate2 = {};
703
+ for (const [key, def] of Object.entries(attributes || {})) {
704
+ if (def.type === "component" && def.component) {
705
+ const comp = allComponents[def.component];
706
+ if (comp?.attributes) {
707
+ const subPopulate = buildHistoryPopulate(comp.attributes, allComponents, depth2 + 1);
708
+ if (subPopulate && Object.keys(subPopulate).length > 0) {
709
+ populate2[key] = {
710
+ populate: subPopulate
711
+ };
712
+ } else {
713
+ populate2[key] = true;
714
+ }
715
+ } else {
716
+ populate2[key] = true;
717
+ }
718
+ } else if (def.type === "dynamiczone") {
719
+ populate2[key] = true;
720
+ } else if (def.type === "relation" || def.type === "media") {
721
+ populate2[key] = true;
722
+ }
723
+ }
724
+ return Object.keys(populate2).length > 0 ? populate2 : void 0;
725
+ }
726
+ let cachedAdminUserId = null;
727
+ async function recordContentHistoryVersion(strapi2, options) {
728
+ const { uid, documentId, userId, statusOverride } = options;
729
+ if (!uid || !uid.startsWith("api::") || !documentId) {
730
+ return;
731
+ }
732
+ try {
733
+ const historyQuery = strapi2.db?.query?.("plugin::content-manager.history-version");
734
+ if (!historyQuery) {
735
+ return;
736
+ }
737
+ const model = strapi2.getModel?.(uid);
738
+ if (!model) {
739
+ return;
740
+ }
741
+ let entry = null;
742
+ try {
743
+ entry = await strapi2.db.query(uid).findOne({
744
+ where: { documentId },
745
+ populate: true
746
+ });
747
+ } catch {
748
+ try {
749
+ const populateOption = buildHistoryPopulate(model.attributes || {}, strapi2.components || {});
750
+ entry = await strapi2.documents(uid).findOne({
751
+ documentId,
752
+ ...populateOption ? { populate: populateOption } : {}
753
+ });
754
+ } catch {
755
+ entry = null;
756
+ }
757
+ }
758
+ if (!entry) {
759
+ return;
760
+ }
761
+ const attributesSchema = model.attributes || {};
762
+ const sanitizedSchema = Object.fromEntries(
763
+ Object.entries(attributesSchema).filter(([k]) => !FIELDS_TO_IGNORE.includes(k))
764
+ );
765
+ const sanitizedData = Object.fromEntries(
766
+ Object.entries(entry).filter(([k]) => !FIELDS_TO_IGNORE.includes(k) && k !== "id")
767
+ );
768
+ let status2 = statusOverride || "published";
769
+ if (!statusOverride) {
770
+ const hasDraftAndPublish = Boolean(model.options?.draftAndPublish);
771
+ if (hasDraftAndPublish) {
772
+ try {
773
+ const docMetaService = strapi2.plugin("content-manager")?.service("document-metadata");
774
+ if (docMetaService) {
775
+ const meta = await docMetaService.getMetadata(uid, entry);
776
+ status2 = docMetaService.getStatus(entry, meta.availableStatus);
777
+ } else {
778
+ status2 = entry.publishedAt ? "published" : "draft";
779
+ }
780
+ } catch {
781
+ status2 = entry.publishedAt ? "published" : "draft";
782
+ }
783
+ } else {
784
+ status2 = "published";
785
+ }
786
+ }
787
+ let authorId = userId;
788
+ if (!authorId) {
789
+ authorId = strapi2.requestContext?.get?.()?.state?.user?.id || null;
790
+ }
791
+ let numericUserId = authorId ? Number(authorId) : null;
792
+ if (!numericUserId || isNaN(numericUserId)) {
793
+ if (cachedAdminUserId) {
794
+ numericUserId = cachedAdminUserId;
795
+ } else {
796
+ try {
797
+ const firstAdmin = await strapi2.db?.query?.("admin::user")?.findOne?.({ select: ["id"] });
798
+ if (firstAdmin?.id) {
799
+ cachedAdminUserId = Number(firstAdmin.id);
800
+ numericUserId = cachedAdminUserId;
801
+ }
802
+ } catch {
803
+ }
804
+ }
805
+ }
806
+ await historyQuery.create({
807
+ data: {
808
+ contentType: uid,
809
+ relatedDocumentId: documentId,
810
+ locale: entry.locale || null,
811
+ status: status2,
812
+ data: sanitizedData,
813
+ schema: sanitizedSchema,
814
+ createdAt: /* @__PURE__ */ new Date(),
815
+ ...numericUserId && !isNaN(numericUserId) ? { createdBy: numericUserId } : {}
816
+ }
817
+ });
818
+ } catch (err) {
819
+ strapi2.log?.warn?.(`[bulk-updater] Non-blocking Content History notice for ${uid}/${documentId}: ${err?.message}`);
820
+ }
821
+ }
822
+ async function recordContentHistoryVersionsBatch(strapi2, items) {
823
+ if (!items || items.length === 0) return;
824
+ const BATCH_SIZE = 10;
825
+ for (let i = 0; i < items.length; i += BATCH_SIZE) {
826
+ const slice = items.slice(i, i + BATCH_SIZE);
827
+ await Promise.all(slice.map((item) => recordContentHistoryVersion(strapi2, item)));
828
+ }
829
+ }
830
+ const contentHistoryService = {
831
+ recordContentHistoryVersion,
832
+ recordContentHistoryVersionsBatch
833
+ };
691
834
  const queryCache = /* @__PURE__ */ new Map();
692
835
  const modelsCache = /* @__PURE__ */ new Map();
693
836
  const MAX_QUERY_CACHE_SIZE = 500;
@@ -1064,6 +1207,12 @@ async function executeBatchInternal(strapi2, {
1064
1207
  }
1065
1208
  }
1066
1209
  invalidateCollectionCache(target.uid);
1210
+ await recordContentHistoryVersion(strapi2, {
1211
+ uid: target.uid,
1212
+ documentId: target.documentId,
1213
+ userId: currentUser?.id,
1214
+ statusOverride: publishOnApproval && isDraftAndPublishComp ? "published" : void 0
1215
+ });
1067
1216
  return {
1068
1217
  uid: target.uid,
1069
1218
  collectionName: displayName,
@@ -1149,6 +1298,12 @@ async function executeBatchInternal(strapi2, {
1149
1298
  if (attrDef.target) {
1150
1299
  invalidateCollectionCache(attrDef.target);
1151
1300
  }
1301
+ await recordContentHistoryVersion(strapi2, {
1302
+ uid: target.uid,
1303
+ documentId: target.documentId,
1304
+ userId: currentUser?.id,
1305
+ statusOverride: publishOnApproval && isDraftAndPublishRel ? "published" : void 0
1306
+ });
1152
1307
  return {
1153
1308
  uid: target.uid,
1154
1309
  collectionName: displayName,
@@ -1182,6 +1337,12 @@ async function executeBatchInternal(strapi2, {
1182
1337
  strapi2.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);
1183
1338
  }
1184
1339
  }
1340
+ await recordContentHistoryVersion(strapi2, {
1341
+ uid: target.uid,
1342
+ documentId: target.documentId,
1343
+ userId: currentUser?.id,
1344
+ statusOverride: publishOnApproval && isDraftAndPublishScalar ? "published" : void 0
1345
+ });
1185
1346
  return {
1186
1347
  uid: target.uid,
1187
1348
  collectionName: displayName,
@@ -1352,6 +1513,12 @@ async function executePublishBatchInternal(strapi2, {
1352
1513
  documentId: target.documentId
1353
1514
  });
1354
1515
  invalidateCollectionCache(target.uid);
1516
+ await recordContentHistoryVersion(strapi2, {
1517
+ uid: target.uid,
1518
+ documentId: target.documentId,
1519
+ userId: currentUser?.id,
1520
+ statusOverride: "published"
1521
+ });
1355
1522
  return {
1356
1523
  uid: target.uid,
1357
1524
  collectionName: displayName,
@@ -3207,7 +3374,7 @@ const auditService = ({ strapi: strapi2 }) => ({
3207
3374
  /**
3208
3375
  * Helper to revert diff items back to original values
3209
3376
  */
3210
- async revertDiffItems(diffs) {
3377
+ async revertDiffItems(diffs, userId) {
3211
3378
  let revertedCount = 0;
3212
3379
  const rollbackDetails = [];
3213
3380
  for (const item of diffs) {
@@ -3265,6 +3432,15 @@ const auditService = ({ strapi: strapi2 }) => ({
3265
3432
  } catch {
3266
3433
  }
3267
3434
  }
3435
+ try {
3436
+ await recordContentHistoryVersion(strapi2, {
3437
+ uid: item.uid,
3438
+ documentId: item.documentId,
3439
+ userId,
3440
+ statusOverride: ct?.options?.draftAndPublish ? "published" : void 0
3441
+ });
3442
+ } catch {
3443
+ }
3268
3444
  try {
3269
3445
  const bulkService = strapi2.plugin("bulk-updater").service("bulkUpdater");
3270
3446
  if (bulkService?.invalidateCache) {
@@ -3315,7 +3491,7 @@ const auditService = ({ strapi: strapi2 }) => ({
3315
3491
  throw new Error(`Batch "${batchId}" has already been rolled back.`);
3316
3492
  }
3317
3493
  const diffs2 = Array.isArray(record2.diffs) ? record2.diffs : [];
3318
- const { revertedCount: revertedCount2, rollbackDetails: rollbackDetails2 } = await this.revertDiffItems(diffs2);
3494
+ const { revertedCount: revertedCount2, rollbackDetails: rollbackDetails2 } = await this.revertDiffItems(diffs2, currentUser?.id);
3319
3495
  record2.isRolledBack = true;
3320
3496
  record2.rolledBackAt = (/* @__PURE__ */ new Date()).toISOString();
3321
3497
  record2.rolledBackBy = currentUser?.email || "Admin";
@@ -3363,7 +3539,7 @@ const auditService = ({ strapi: strapi2 }) => ({
3363
3539
  throw new Error(`Batch "${batchId}" has already been rolled back.`);
3364
3540
  }
3365
3541
  const diffs = typeof record[f.diffs] === "string" ? JSON.parse(record[f.diffs]) : record[f.diffs] || [];
3366
- const { revertedCount, rollbackDetails } = await this.revertDiffItems(diffs);
3542
+ const { revertedCount, rollbackDetails } = await this.revertDiffItems(diffs, currentUser?.id);
3367
3543
  const updateData = {};
3368
3544
  if (f.isRolledBack) updateData[f.isRolledBack] = true;
3369
3545
  if (f.rolledBackAt) updateData[f.rolledBackAt] = (/* @__PURE__ */ new Date()).toISOString();
@@ -3639,77 +3815,93 @@ function escapeCsvValue(val) {
3639
3815
  }
3640
3816
  return str2;
3641
3817
  }
3642
- function parseCsv(csvText) {
3818
+ function parseCsvRows(csvText) {
3643
3819
  if (!csvText) return [];
3644
- let cleanText = csvText;
3645
- if (cleanText.charCodeAt(0) === 65279) {
3646
- cleanText = cleanText.slice(1);
3820
+ let text = csvText;
3821
+ if (text.charCodeAt(0) === 65279) {
3822
+ text = text.slice(1);
3647
3823
  }
3648
- const lines = [];
3649
- let current = "";
3824
+ const rows = [];
3825
+ let currentRow = [];
3826
+ let currentCell = "";
3650
3827
  let inQuotes = false;
3651
- for (let i = 0; i < cleanText.length; i++) {
3652
- const char = cleanText[i];
3653
- const nextChar = cleanText[i + 1];
3654
- if (char === '"') {
3655
- if (inQuotes && nextChar === '"') {
3656
- current += '"';
3657
- i++;
3828
+ let cellIsQuoted = false;
3829
+ for (let i = 0; i < text.length; i++) {
3830
+ const char = text[i];
3831
+ const nextChar = text[i + 1];
3832
+ if (inQuotes) {
3833
+ if (char === '"') {
3834
+ if (nextChar === '"') {
3835
+ currentCell += '"';
3836
+ i++;
3837
+ } else {
3838
+ inQuotes = false;
3839
+ }
3658
3840
  } else {
3659
- inQuotes = !inQuotes;
3660
- }
3661
- } else if ((char === "\r" || char === "\n") && !inQuotes) {
3662
- if (char === "\r" && nextChar === "\n") {
3663
- i++;
3841
+ currentCell += char;
3664
3842
  }
3665
- if (current.trim().length > 0) {
3666
- lines.push(current);
3667
- }
3668
- current = "";
3669
3843
  } else {
3670
- current += char;
3671
- }
3672
- }
3673
- if (current.trim().length > 0) {
3674
- lines.push(current);
3675
- }
3676
- if (lines.length < 1) return [];
3677
- function splitLine(line) {
3678
- const fields2 = [];
3679
- let field = "";
3680
- let inQ = false;
3681
- for (let i = 0; i < line.length; i++) {
3682
- const c = line[i];
3683
- const nc = line[i + 1];
3684
- if (c === '"') {
3685
- if (inQ && nc === '"') {
3686
- field += '"';
3844
+ if (char === '"' && !cellIsQuoted && currentCell.trim() === "") {
3845
+ inQuotes = true;
3846
+ cellIsQuoted = true;
3847
+ currentCell = "";
3848
+ } else if (char === ",") {
3849
+ currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());
3850
+ currentCell = "";
3851
+ cellIsQuoted = false;
3852
+ } else if (char === "\r") {
3853
+ if (nextChar === "\n") {
3687
3854
  i++;
3688
- } else {
3689
- inQ = !inQ;
3690
3855
  }
3691
- } else if (c === "," && !inQ) {
3692
- fields2.push(field);
3693
- field = "";
3856
+ currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());
3857
+ if (currentRow.length > 1 || currentRow.length === 1 && currentRow[0] !== "") {
3858
+ rows.push(currentRow);
3859
+ }
3860
+ currentRow = [];
3861
+ currentCell = "";
3862
+ cellIsQuoted = false;
3863
+ } else if (char === "\n") {
3864
+ currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());
3865
+ if (currentRow.length > 1 || currentRow.length === 1 && currentRow[0] !== "") {
3866
+ rows.push(currentRow);
3867
+ }
3868
+ currentRow = [];
3869
+ currentCell = "";
3870
+ cellIsQuoted = false;
3694
3871
  } else {
3695
- field += c;
3872
+ if (!(cellIsQuoted && !inQuotes && (char === " " || char === " "))) {
3873
+ currentCell += char;
3874
+ }
3696
3875
  }
3697
3876
  }
3698
- fields2.push(field);
3699
- return fields2.map((f) => f.trim());
3700
3877
  }
3701
- const headers = splitLine(lines[0]);
3702
- const rows = [];
3703
- for (let i = 1; i < lines.length; i++) {
3704
- const values = splitLine(lines[i]);
3705
- const rowObj = {};
3706
- headers.forEach((h, index2) => {
3707
- rowObj[h] = values[index2] !== void 0 ? values[index2] : "";
3708
- });
3709
- rows.push(rowObj);
3878
+ if (currentCell !== "" || cellIsQuoted || currentRow.length > 0) {
3879
+ currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());
3880
+ if (currentRow.length > 1 || currentRow.length === 1 && currentRow[0] !== "") {
3881
+ rows.push(currentRow);
3882
+ }
3710
3883
  }
3711
3884
  return rows;
3712
3885
  }
3886
+ function parseCsv(csvText) {
3887
+ const rows = parseCsvRows(csvText);
3888
+ if (rows.length < 2) return [];
3889
+ const headers = rows[0].map((h) => h.trim());
3890
+ const records = [];
3891
+ for (let i = 1; i < rows.length; i++) {
3892
+ const row = rows[i];
3893
+ const record = {};
3894
+ headers.forEach((h, idx) => {
3895
+ let val = row[idx] !== void 0 ? row[idx] : "";
3896
+ if (typeof val === "string" && /^'[=+@-]/.test(val)) {
3897
+ val = val.substring(1);
3898
+ }
3899
+ record[h] = val;
3900
+ });
3901
+ records.push(record);
3902
+ }
3903
+ return records;
3904
+ }
3713
3905
  function discoverExportFields(ct, allComponents, maxDepth = 4) {
3714
3906
  const fields2 = [{ key: "documentId", label: "documentId", type: "string" }];
3715
3907
  const excluded = ["createdBy", "updatedBy", "localizations"];
@@ -4203,6 +4395,15 @@ const csvService = ({ strapi: strapi2 }) => ({
4203
4395
  strapi2.log.warn(`[bulk-updater] Auto-publish failed for ${docId}:`, pubErr);
4204
4396
  }
4205
4397
  }
4398
+ try {
4399
+ await recordContentHistoryVersion(strapi2, {
4400
+ uid,
4401
+ documentId: docId,
4402
+ userId: user?.id,
4403
+ statusOverride: publish && ct.options?.draftAndPublish ? "published" : void 0
4404
+ });
4405
+ } catch {
4406
+ }
4206
4407
  stats.updated++;
4207
4408
  stats.diffs.push({
4208
4409
  uid,
@@ -4238,6 +4439,15 @@ const csvService = ({ strapi: strapi2 }) => ({
4238
4439
  strapi2.log.warn(`[bulk-updater] Auto-publish failed for ${docId}:`, pubErr);
4239
4440
  }
4240
4441
  }
4442
+ try {
4443
+ await recordContentHistoryVersion(strapi2, {
4444
+ uid,
4445
+ documentId: docId,
4446
+ userId: user?.id,
4447
+ statusOverride: publish && ct.options?.draftAndPublish ? "published" : void 0
4448
+ });
4449
+ } catch {
4450
+ }
4241
4451
  stats.updated++;
4242
4452
  stats.diffs.push({
4243
4453
  uid,
@@ -4264,6 +4474,15 @@ const csvService = ({ strapi: strapi2 }) => ({
4264
4474
  strapi2.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);
4265
4475
  }
4266
4476
  }
4477
+ try {
4478
+ await recordContentHistoryVersion(strapi2, {
4479
+ uid,
4480
+ documentId: newDocId,
4481
+ userId: user?.id,
4482
+ statusOverride: publish && ct.options?.draftAndPublish ? "published" : void 0
4483
+ });
4484
+ } catch {
4485
+ }
4267
4486
  stats.created++;
4268
4487
  if (!docId) {
4269
4488
  stats.newWithoutDocId++;
@@ -4302,6 +4521,15 @@ const csvService = ({ strapi: strapi2 }) => ({
4302
4521
  strapi2.log.warn(`[bulk-updater] Auto-publish failed for ${docId}:`, pubErr);
4303
4522
  }
4304
4523
  }
4524
+ try {
4525
+ await recordContentHistoryVersion(strapi2, {
4526
+ uid,
4527
+ documentId: docId,
4528
+ userId: user?.id,
4529
+ statusOverride: publish && ct.options?.draftAndPublish ? "published" : void 0
4530
+ });
4531
+ } catch {
4532
+ }
4305
4533
  stats.updated++;
4306
4534
  stats.diffs.push({
4307
4535
  uid,
@@ -4328,6 +4556,15 @@ const csvService = ({ strapi: strapi2 }) => ({
4328
4556
  strapi2.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);
4329
4557
  }
4330
4558
  }
4559
+ try {
4560
+ await recordContentHistoryVersion(strapi2, {
4561
+ uid,
4562
+ documentId: newDocId,
4563
+ userId: user?.id,
4564
+ statusOverride: publish && ct.options?.draftAndPublish ? "published" : void 0
4565
+ });
4566
+ } catch {
4567
+ }
4331
4568
  stats.created++;
4332
4569
  if (!docId) {
4333
4570
  stats.newWithoutDocId++;
@@ -33808,8 +34045,8 @@ const index = {
33808
34045
  },
33809
34046
  bootstrap({ strapi: strapi2 }) {
33810
34047
  strapi2.documents.use(async (context, next) => {
34048
+ const params = context.params;
33811
34049
  if (["create", "update"].includes(context.action)) {
33812
- const params = context.params;
33813
34050
  const data = params?.data;
33814
34051
  if (data && typeof data === "object") {
33815
34052
  let scanDataTree = function(obj) {
@@ -33909,8 +34146,113 @@ const index = {
33909
34146
  }
33910
34147
  }
33911
34148
  }
33912
- return next();
34149
+ const result = await next();
34150
+ return result;
34151
+ });
34152
+ strapi2.server.use(async (ctx, next) => {
34153
+ if (!ctx.path.startsWith("/content-manager/history-versions")) {
34154
+ await next();
34155
+ return;
34156
+ }
34157
+ await next();
34158
+ if (ctx.status === 404 || ctx.status === 405) {
34159
+ if (ctx.method === "GET" && ctx.path === "/content-manager/history-versions") {
34160
+ const { contentType, documentId, locale: locale2, page = 1, pageSize = 20 } = ctx.query;
34161
+ if (!contentType) return;
34162
+ const historyQuery = strapi2.db?.query?.("plugin::content-manager.history-version");
34163
+ if (!historyQuery) return;
34164
+ const pageNum = Math.max(1, parseInt(page, 10) || 1);
34165
+ const limit = Math.min(100, Math.max(1, parseInt(pageSize, 10) || 20));
34166
+ const whereClause = {
34167
+ contentType,
34168
+ ...documentId ? { relatedDocumentId: documentId } : {},
34169
+ ...locale2 ? { locale: locale2 } : {}
34170
+ };
34171
+ const [results, total] = await Promise.all([
34172
+ historyQuery.findMany({
34173
+ where: whereClause,
34174
+ populate: ["createdBy"],
34175
+ orderBy: { createdAt: "desc" },
34176
+ limit,
34177
+ offset: (pageNum - 1) * limit
34178
+ }),
34179
+ historyQuery.count({ where: whereClause })
34180
+ ]);
34181
+ const sanitizedResults = (results || []).map((ver) => ({
34182
+ ...ver,
34183
+ createdBy: ver.createdBy ? {
34184
+ id: ver.createdBy.id,
34185
+ firstname: ver.createdBy.firstname,
34186
+ lastname: ver.createdBy.lastname,
34187
+ username: ver.createdBy.username,
34188
+ email: ver.createdBy.email
34189
+ } : void 0,
34190
+ meta: {
34191
+ unknownAttributes: { added: {}, removed: {} }
34192
+ }
34193
+ }));
34194
+ ctx.status = 200;
34195
+ ctx.body = {
34196
+ data: sanitizedResults,
34197
+ meta: {
34198
+ pagination: {
34199
+ page: pageNum,
34200
+ pageSize: limit,
34201
+ pageCount: Math.ceil(total / limit) || 1,
34202
+ total
34203
+ }
34204
+ }
34205
+ };
34206
+ } else if (ctx.method === "PUT" && ctx.path.endsWith("/restore")) {
34207
+ const match = ctx.path.match(/\/content-manager\/history-versions\/([^/]+)\/restore/);
34208
+ const versionId = match?.[1];
34209
+ if (!versionId) return;
34210
+ const historyQuery = strapi2.db?.query?.("plugin::content-manager.history-version");
34211
+ const version = await historyQuery?.findOne?.({ where: { id: versionId } });
34212
+ if (!version) {
34213
+ ctx.status = 404;
34214
+ ctx.body = { error: "Version not found" };
34215
+ return;
34216
+ }
34217
+ const restored = await strapi2.documents(version.contentType).update({
34218
+ documentId: version.relatedDocumentId,
34219
+ locale: version.locale || void 0,
34220
+ data: version.data
34221
+ });
34222
+ await recordContentHistoryVersion(strapi2, {
34223
+ uid: version.contentType,
34224
+ documentId: version.relatedDocumentId,
34225
+ statusOverride: version.status || "published"
34226
+ });
34227
+ ctx.status = 200;
34228
+ ctx.body = {
34229
+ data: {
34230
+ documentId: restored?.documentId || version.relatedDocumentId
34231
+ }
34232
+ };
34233
+ }
34234
+ }
33913
34235
  });
34236
+ try {
34237
+ const knex = strapi2.db?.connection;
34238
+ if (knex) {
34239
+ if (knex.client?.config?.client === "sqlite3" || knex.client?.dialect === "sqlite3") {
34240
+ knex.raw("PRAGMA busy_timeout = 10000;").catch(() => {
34241
+ });
34242
+ }
34243
+ knex.schema.hasTable("strapi_history_versions").then((hasTable) => {
34244
+ if (hasTable) {
34245
+ knex.raw(`
34246
+ CREATE INDEX IF NOT EXISTS idx_history_versions_lookup
34247
+ ON strapi_history_versions (content_type, related_document_id, created_at)
34248
+ `).catch(() => {
34249
+ });
34250
+ }
34251
+ }).catch(() => {
34252
+ });
34253
+ }
34254
+ } catch {
34255
+ }
33914
34256
  },
33915
34257
  routes,
33916
34258
  contentTypes,
@@ -33924,7 +34266,8 @@ const index = {
33924
34266
  bulkUpdater: bulkUpdaterService,
33925
34267
  audit: auditService,
33926
34268
  validationRules: validationRulesService,
33927
- csv: csvService
34269
+ csv: csvService,
34270
+ contentHistory: contentHistoryService
33928
34271
  }
33929
34272
  };
33930
34273
  module.exports = index;