@strapi/content-manager 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.edc24aaa3bb5a90fa5fd4fee208167dd4e2e38d4

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.
Files changed (174) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
  3. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
  4. package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
  5. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
  6. package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js → ComponentConfigurationPage-5ukroXAh.js} +3 -3
  7. package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js.map → ComponentConfigurationPage-5ukroXAh.js.map} +1 -1
  8. package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs → ComponentConfigurationPage-BAgyHiMm.mjs} +3 -3
  9. package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs.map → ComponentConfigurationPage-BAgyHiMm.mjs.map} +1 -1
  10. package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
  11. package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
  12. package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
  13. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
  14. package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs → EditConfigurationPage-DmoXawIh.mjs} +3 -3
  15. package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs.map → EditConfigurationPage-DmoXawIh.mjs.map} +1 -1
  16. package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js → EditConfigurationPage-Xp7lun0f.js} +3 -3
  17. package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js.map → EditConfigurationPage-Xp7lun0f.js.map} +1 -1
  18. package/dist/_chunks/{EditViewPage-DDS6H9HO.mjs → EditViewPage-BLsjc5F-.mjs} +47 -47
  19. package/dist/_chunks/EditViewPage-BLsjc5F-.mjs.map +1 -0
  20. package/dist/_chunks/{EditViewPage-DvNpQkam.js → EditViewPage-C-ukDOB7.js} +46 -48
  21. package/dist/_chunks/EditViewPage-C-ukDOB7.js.map +1 -0
  22. package/dist/_chunks/{Field-DmVKIAOo.js → Field-Bfph5SOd.js} +953 -782
  23. package/dist/_chunks/Field-Bfph5SOd.js.map +1 -0
  24. package/dist/_chunks/{Field-6gvGdPBV.mjs → Field-Cs7duwWd.mjs} +901 -729
  25. package/dist/_chunks/Field-Cs7duwWd.mjs.map +1 -0
  26. package/dist/_chunks/{Form-CPZC9vWa.js → Form-CPYqIWDG.js} +39 -38
  27. package/dist/_chunks/Form-CPYqIWDG.js.map +1 -0
  28. package/dist/_chunks/{Form-DW6K1IH-.mjs → Form-Dg_GS5TQ.mjs} +39 -37
  29. package/dist/_chunks/Form-Dg_GS5TQ.mjs.map +1 -0
  30. package/dist/_chunks/{History-DeAPlvtv.js → History-DNQkXANT.js} +149 -56
  31. package/dist/_chunks/History-DNQkXANT.js.map +1 -0
  32. package/dist/_chunks/{History-Dmr9fmUA.mjs → History-wrnHqf09.mjs} +148 -54
  33. package/dist/_chunks/History-wrnHqf09.mjs.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-DPCwW5Vr.js → ListConfigurationPage-CUQxfpjT.js} +58 -59
  35. package/dist/_chunks/ListConfigurationPage-CUQxfpjT.js.map +1 -0
  36. package/dist/_chunks/{ListConfigurationPage-DhwvYcNv.mjs → ListConfigurationPage-DScmJVkW.mjs} +54 -54
  37. package/dist/_chunks/ListConfigurationPage-DScmJVkW.mjs.map +1 -0
  38. package/dist/_chunks/{ListViewPage-5ySZ-VUs.js → ListViewPage-BsLiH2-2.js} +92 -108
  39. package/dist/_chunks/ListViewPage-BsLiH2-2.js.map +1 -0
  40. package/dist/_chunks/{ListViewPage-BtAwuYLE.mjs → ListViewPage-C4IvrMgY.mjs} +87 -103
  41. package/dist/_chunks/ListViewPage-C4IvrMgY.mjs.map +1 -0
  42. package/dist/_chunks/{NoContentTypePage-DOC_yWOf.js → NoContentTypePage-BZ-PnGAf.js} +3 -3
  43. package/dist/_chunks/NoContentTypePage-BZ-PnGAf.js.map +1 -0
  44. package/dist/_chunks/{NoContentTypePage-DSPxnxxp.mjs → NoContentTypePage-Djg8nPlj.mjs} +3 -3
  45. package/dist/_chunks/NoContentTypePage-Djg8nPlj.mjs.map +1 -0
  46. package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs → NoPermissionsPage-DSP7R-hv.mjs} +2 -2
  47. package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs.map → NoPermissionsPage-DSP7R-hv.mjs.map} +1 -1
  48. package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js → NoPermissionsPage-_lUqjGW3.js} +2 -2
  49. package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js.map → NoPermissionsPage-_lUqjGW3.js.map} +1 -1
  50. package/dist/_chunks/{Relations-J8cscLlR.mjs → Relations-BZr8tL0R.mjs} +66 -56
  51. package/dist/_chunks/Relations-BZr8tL0R.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-CgWtgnPe.js → Relations-CtELXYIK.js} +70 -61
  53. package/dist/_chunks/Relations-CtELXYIK.js.map +1 -0
  54. package/dist/_chunks/{en-MBPul9Su.mjs → en-BrCTWlZv.mjs} +11 -4
  55. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-BrCTWlZv.mjs.map} +1 -1
  56. package/dist/_chunks/{en-C-V1_90f.js → en-uOUIxfcQ.js} +11 -4
  57. package/dist/_chunks/{en-C-V1_90f.js.map → en-uOUIxfcQ.js.map} +1 -1
  58. package/dist/_chunks/{index-C6AH2hEl.js → index-OerGjbAN.js} +1588 -837
  59. package/dist/_chunks/index-OerGjbAN.js.map +1 -0
  60. package/dist/_chunks/{index-CwRRo1V9.mjs → index-c_5DdJi-.mjs} +1610 -858
  61. package/dist/_chunks/index-c_5DdJi-.mjs.map +1 -0
  62. package/dist/_chunks/{layout-B_SXLhqf.js → layout-Ci7qHlFb.js} +30 -27
  63. package/dist/_chunks/layout-Ci7qHlFb.js.map +1 -0
  64. package/dist/_chunks/{layout-jIDzX0Fp.mjs → layout-oPBiO7RY.mjs} +29 -24
  65. package/dist/_chunks/layout-oPBiO7RY.mjs.map +1 -0
  66. package/dist/_chunks/{relations-CuvIgCqI.mjs → relations-BIdWFjdq.mjs} +2 -2
  67. package/dist/_chunks/{relations-CuvIgCqI.mjs.map → relations-BIdWFjdq.mjs.map} +1 -1
  68. package/dist/_chunks/{relations-iBMa_OFG.js → relations-COBpStiF.js} +2 -2
  69. package/dist/_chunks/{relations-iBMa_OFG.js.map → relations-COBpStiF.js.map} +1 -1
  70. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
  71. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
  72. package/dist/_chunks/usePrev-B9w_-eYc.js +15 -0
  73. package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
  74. package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
  75. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +1 -0
  76. package/dist/admin/index.js +2 -1
  77. package/dist/admin/index.js.map +1 -1
  78. package/dist/admin/index.mjs +5 -4
  79. package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
  80. package/dist/admin/src/content-manager.d.ts +3 -3
  81. package/dist/admin/src/exports.d.ts +1 -0
  82. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  83. package/dist/admin/src/history/index.d.ts +3 -0
  84. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  85. package/dist/admin/src/hooks/useDocument.d.ts +5 -8
  86. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  87. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  88. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  89. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  90. package/dist/admin/src/index.d.ts +1 -0
  91. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +11 -4
  92. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  93. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  95. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  96. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  97. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +30 -18
  98. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  99. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  100. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  101. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +59 -52
  102. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  103. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  104. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  105. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  106. package/dist/admin/src/services/api.d.ts +2 -3
  107. package/dist/admin/src/services/components.d.ts +2 -2
  108. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  109. package/dist/admin/src/services/documents.d.ts +29 -17
  110. package/dist/admin/src/services/init.d.ts +2 -2
  111. package/dist/admin/src/services/relations.d.ts +3 -3
  112. package/dist/admin/src/services/uid.d.ts +3 -3
  113. package/dist/admin/src/utils/api.d.ts +4 -18
  114. package/dist/admin/src/utils/validation.d.ts +1 -6
  115. package/dist/server/index.js +309 -218
  116. package/dist/server/index.js.map +1 -1
  117. package/dist/server/index.mjs +317 -226
  118. package/dist/server/index.mjs.map +1 -1
  119. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  120. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  121. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  122. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  123. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  124. package/dist/server/src/controllers/validation/dimensions.d.ts +11 -0
  125. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  126. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  127. package/dist/server/src/history/services/history.d.ts.map +1 -1
  128. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  129. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  130. package/dist/server/src/index.d.ts +18 -39
  131. package/dist/server/src/index.d.ts.map +1 -1
  132. package/dist/server/src/services/document-manager.d.ts +13 -12
  133. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  134. package/dist/server/src/services/document-metadata.d.ts +8 -29
  135. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  136. package/dist/server/src/services/index.d.ts +18 -39
  137. package/dist/server/src/services/index.d.ts.map +1 -1
  138. package/dist/server/src/services/utils/populate.d.ts +8 -1
  139. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  140. package/dist/shared/contracts/collection-types.d.ts +14 -6
  141. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  142. package/dist/shared/contracts/relations.d.ts +2 -2
  143. package/dist/shared/contracts/relations.d.ts.map +1 -1
  144. package/package.json +13 -14
  145. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  146. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  147. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  148. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  149. package/dist/_chunks/EditViewPage-DDS6H9HO.mjs.map +0 -1
  150. package/dist/_chunks/EditViewPage-DvNpQkam.js.map +0 -1
  151. package/dist/_chunks/Field-6gvGdPBV.mjs.map +0 -1
  152. package/dist/_chunks/Field-DmVKIAOo.js.map +0 -1
  153. package/dist/_chunks/Form-CPZC9vWa.js.map +0 -1
  154. package/dist/_chunks/Form-DW6K1IH-.mjs.map +0 -1
  155. package/dist/_chunks/History-DeAPlvtv.js.map +0 -1
  156. package/dist/_chunks/History-Dmr9fmUA.mjs.map +0 -1
  157. package/dist/_chunks/ListConfigurationPage-DPCwW5Vr.js.map +0 -1
  158. package/dist/_chunks/ListConfigurationPage-DhwvYcNv.mjs.map +0 -1
  159. package/dist/_chunks/ListViewPage-5ySZ-VUs.js.map +0 -1
  160. package/dist/_chunks/ListViewPage-BtAwuYLE.mjs.map +0 -1
  161. package/dist/_chunks/NoContentTypePage-DOC_yWOf.js.map +0 -1
  162. package/dist/_chunks/NoContentTypePage-DSPxnxxp.mjs.map +0 -1
  163. package/dist/_chunks/Relations-CgWtgnPe.js.map +0 -1
  164. package/dist/_chunks/Relations-J8cscLlR.mjs.map +0 -1
  165. package/dist/_chunks/index-C6AH2hEl.js.map +0 -1
  166. package/dist/_chunks/index-CwRRo1V9.mjs.map +0 -1
  167. package/dist/_chunks/layout-B_SXLhqf.js.map +0 -1
  168. package/dist/_chunks/layout-jIDzX0Fp.mjs.map +0 -1
  169. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  170. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  171. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  172. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  173. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  174. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
@@ -1,5 +1,5 @@
1
- import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1, sanitize } from "@strapi/utils";
2
- import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy, castArray } from "lodash/fp";
1
+ import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1, traverseEntity, pagination } from "@strapi/utils";
2
+ import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, isNil as isNil$1, getOr, propEq, merge, groupBy, castArray } from "lodash/fp";
3
3
  import "@strapi/types";
4
4
  import * as yup from "yup";
5
5
  import { scheduleJob } from "node-schedule";
@@ -54,7 +54,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
54
54
  return ctx.forbidden();
55
55
  }
56
56
  const query = await permissionChecker2.sanitizeQuery(ctx.query);
57
- const { results, pagination } = await getService(strapi2, "history").findVersionsPage({
57
+ const { results, pagination: pagination2 } = await getService(strapi2, "history").findVersionsPage({
58
58
  query: {
59
59
  ...query,
60
60
  ...getValidPagination({ page: query.page, pageSize: query.pageSize })
@@ -73,7 +73,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
73
73
  );
74
74
  return {
75
75
  data: sanitizedResults,
76
- meta: { pagination }
76
+ meta: { pagination: pagination2 }
77
77
  };
78
78
  },
79
79
  async restoreVersion(ctx) {
@@ -206,6 +206,10 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
206
206
  return attributes.reduce((acc, [attributeName, attribute]) => {
207
207
  switch (attribute.type) {
208
208
  case "relation": {
209
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
210
+ if (isMorphRelation) {
211
+ break;
212
+ }
209
213
  const isVisible2 = contentTypes$1.isVisibleAttribute(model, attributeName);
210
214
  if (isVisible2) {
211
215
  acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
@@ -309,7 +313,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
309
313
  },
310
314
  async findVersionsPage(params) {
311
315
  const locale = params.query.locale || await serviceUtils.getDefaultLocale();
312
- const [{ results, pagination }, localeDictionary] = await Promise.all([
316
+ const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
313
317
  query.findPage({
314
318
  ...params.query,
315
319
  where: {
@@ -408,7 +412,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
408
412
  );
409
413
  return {
410
414
  results: formattedResults,
411
- pagination
415
+ pagination: pagination2
412
416
  };
413
417
  },
414
418
  async restoreVersion(versionId) {
@@ -469,8 +473,6 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
469
473
  deleteExpiredJob: null,
470
474
  isInitialized: false
471
475
  };
472
- const query = strapi2.db.query(HISTORY_VERSION_UID);
473
- const historyService = getService(strapi2, "history");
474
476
  const serviceUtils = createServiceUtils({ strapi: strapi2 });
475
477
  return {
476
478
  async bootstrap() {
@@ -481,7 +483,10 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
481
483
  if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
482
484
  return next();
483
485
  }
484
- if (context.action !== "create" && context.action !== "update" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
486
+ if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
487
+ return next();
488
+ }
489
+ if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
485
490
  return next();
486
491
  }
487
492
  const contentTypeUid = context.contentType.uid;
@@ -489,9 +494,18 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
489
494
  return next();
490
495
  }
491
496
  const result = await next();
492
- const documentContext = context.action === "create" ? { documentId: result.documentId, locale: context.params?.locale } : { documentId: context.params.documentId, locale: context.params?.locale };
497
+ const documentContext = {
498
+ documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
499
+ locale: context.params?.locale
500
+ };
493
501
  const defaultLocale = await serviceUtils.getDefaultLocale();
494
502
  const locale = documentContext.locale || defaultLocale;
503
+ if (Array.isArray(locale)) {
504
+ strapi2.log.warn(
505
+ "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
506
+ );
507
+ return next();
508
+ }
495
509
  const document = await strapi2.documents(contentTypeUid).findOne({
496
510
  documentId: documentContext.documentId,
497
511
  locale,
@@ -514,7 +528,7 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
514
528
  }, {});
515
529
  await strapi2.db.transaction(async ({ onCommit }) => {
516
530
  onCommit(() => {
517
- historyService.createVersion({
531
+ getService(strapi2, "history").createVersion({
518
532
  contentType: contentTypeUid,
519
533
  data: omit(FIELDS_TO_IGNORE, document),
520
534
  schema: omit(FIELDS_TO_IGNORE, attributesSchema),
@@ -527,11 +541,10 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
527
541
  });
528
542
  return result;
529
543
  });
530
- const retentionDays = serviceUtils.getRetentionDays();
531
544
  state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
532
- const retentionDaysInMilliseconds = retentionDays * 24 * 60 * 60 * 1e3;
545
+ const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
533
546
  const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
534
- query.deleteMany({
547
+ strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
535
548
  where: {
536
549
  created_at: {
537
550
  $lt: expirationDate.toISOString()
@@ -1452,7 +1465,7 @@ const { PaginationError, ValidationError } = errors;
1452
1465
  const TYPES = ["singleType", "collectionType"];
1453
1466
  const kindSchema = yup$1.string().oneOf(TYPES).nullable();
1454
1467
  const bulkActionInputSchema = yup$1.object({
1455
- ids: yup$1.array().of(yup$1.strapiID()).min(1).required()
1468
+ documentIds: yup$1.array().of(yup$1.strapiID()).min(1).required()
1456
1469
  }).required();
1457
1470
  const generateUIDInputSchema = yup$1.object({
1458
1471
  contentTypeUID: yup$1.string().required(),
@@ -1551,15 +1564,49 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
1551
1564
  }
1552
1565
  }, body);
1553
1566
  };
1554
- const getDocumentLocaleAndStatus = (request) => {
1555
- const { locale, status, ...rest } = request || {};
1556
- if (!isNil$1(locale) && typeof locale !== "string") {
1557
- throw new errors.ValidationError(`Invalid locale: ${locale}`);
1558
- }
1559
- if (!isNil$1(status) && !["draft", "published"].includes(status)) {
1560
- throw new errors.ValidationError(`Invalid status: ${status}`);
1567
+ const singleLocaleSchema = yup$1.string().nullable();
1568
+ const multipleLocaleSchema = yup$1.lazy(
1569
+ (value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
1570
+ );
1571
+ const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
1572
+ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
1573
+ const { allowMultipleLocales } = opts;
1574
+ const { locale, status: providedStatus, ...rest } = request || {};
1575
+ const defaultStatus = contentTypes$1.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
1576
+ const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
1577
+ const schema = yup$1.object().shape({
1578
+ locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
1579
+ status: statusSchema
1580
+ });
1581
+ try {
1582
+ await validateYupSchema(schema, { strict: true, abortEarly: false })(request);
1583
+ return { locale, status, ...rest };
1584
+ } catch (error) {
1585
+ throw new errors.ValidationError(`Validation error: ${error.message}`);
1561
1586
  }
1562
- return { locale, status, ...rest };
1587
+ };
1588
+ const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
1589
+ const documentMetadata2 = getService$1("document-metadata");
1590
+ const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
1591
+ let {
1592
+ meta: { availableLocales, availableStatus }
1593
+ } = serviceOutput;
1594
+ const metadataSanitizer = permissionChecker2.sanitizeOutput;
1595
+ availableLocales = await async.map(
1596
+ availableLocales,
1597
+ async (localeDocument) => metadataSanitizer(localeDocument)
1598
+ );
1599
+ availableStatus = await async.map(
1600
+ availableStatus,
1601
+ async (statusDocument) => metadataSanitizer(statusDocument)
1602
+ );
1603
+ return {
1604
+ ...serviceOutput,
1605
+ meta: {
1606
+ availableLocales,
1607
+ availableStatus
1608
+ }
1609
+ };
1563
1610
  };
1564
1611
  const createDocument = async (ctx, opts) => {
1565
1612
  const { userAbility, user } = ctx.state;
@@ -1574,7 +1621,7 @@ const createDocument = async (ctx, opts) => {
1574
1621
  const setCreator = setCreatorFields({ user });
1575
1622
  const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
1576
1623
  const sanitizedBody = await sanitizeFn(body);
1577
- const { locale, status = "draft" } = getDocumentLocaleAndStatus(body);
1624
+ const { locale, status } = await getDocumentLocaleAndStatus(body, model);
1578
1625
  return documentManager2.create(model, {
1579
1626
  data: sanitizedBody,
1580
1627
  locale,
@@ -1593,7 +1640,7 @@ const updateDocument = async (ctx, opts) => {
1593
1640
  }
1594
1641
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1595
1642
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1596
- const { locale } = getDocumentLocaleAndStatus(body);
1643
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1597
1644
  const [documentVersion, documentExists] = await Promise.all([
1598
1645
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1599
1646
  documentManager2.exists(model, id)
@@ -1631,8 +1678,8 @@ const collectionTypes = {
1631
1678
  }
1632
1679
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1633
1680
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1634
- const { locale, status } = getDocumentLocaleAndStatus(query);
1635
- const { results: documents, pagination } = await documentManager2.findPage(
1681
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
1682
+ const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
1636
1683
  { ...permissionQuery, populate, locale, status },
1637
1684
  model
1638
1685
  );
@@ -1653,21 +1700,20 @@ const collectionTypes = {
1653
1700
  );
1654
1701
  ctx.body = {
1655
1702
  results,
1656
- pagination
1703
+ pagination: pagination2
1657
1704
  };
1658
1705
  },
1659
1706
  async findOne(ctx) {
1660
1707
  const { userAbility } = ctx.state;
1661
1708
  const { model, id } = ctx.params;
1662
1709
  const documentManager2 = getService$1("document-manager");
1663
- const documentMetadata2 = getService$1("document-metadata");
1664
1710
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1665
1711
  if (permissionChecker2.cannot.read()) {
1666
1712
  return ctx.forbidden();
1667
1713
  }
1668
1714
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1669
1715
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1670
- const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
1716
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
1671
1717
  const version = await documentManager2.findOne(id, model, {
1672
1718
  populate,
1673
1719
  locale,
@@ -1678,8 +1724,10 @@ const collectionTypes = {
1678
1724
  if (!exists) {
1679
1725
  return ctx.notFound();
1680
1726
  }
1681
- const { meta } = await documentMetadata2.formatDocumentWithMetadata(
1727
+ const { meta } = await formatDocumentWithMetadata(
1728
+ permissionChecker2,
1682
1729
  model,
1730
+ // @ts-expect-error TODO: fix
1683
1731
  { id, locale, publishedAt: null },
1684
1732
  { availableLocales: true, availableStatus: false }
1685
1733
  );
@@ -1690,12 +1738,11 @@ const collectionTypes = {
1690
1738
  return ctx.forbidden();
1691
1739
  }
1692
1740
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
1693
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
1741
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
1694
1742
  },
1695
1743
  async create(ctx) {
1696
1744
  const { userAbility } = ctx.state;
1697
1745
  const { model } = ctx.params;
1698
- const documentMetadata2 = getService$1("document-metadata");
1699
1746
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1700
1747
  const [totalEntries, document] = await Promise.all([
1701
1748
  strapi.db.query(model).count(),
@@ -1703,7 +1750,7 @@ const collectionTypes = {
1703
1750
  ]);
1704
1751
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
1705
1752
  ctx.status = 201;
1706
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument, {
1753
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
1707
1754
  // Empty metadata as it's not relevant for a new document
1708
1755
  availableLocales: false,
1709
1756
  availableStatus: false
@@ -1717,25 +1764,23 @@ const collectionTypes = {
1717
1764
  async update(ctx) {
1718
1765
  const { userAbility } = ctx.state;
1719
1766
  const { model } = ctx.params;
1720
- const documentMetadata2 = getService$1("document-metadata");
1721
1767
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1722
1768
  const updatedVersion = await updateDocument(ctx);
1723
1769
  const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
1724
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedVersion);
1770
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
1725
1771
  },
1726
1772
  async clone(ctx) {
1727
1773
  const { userAbility, user } = ctx.state;
1728
1774
  const { model, sourceId: id } = ctx.params;
1729
1775
  const { body } = ctx.request;
1730
1776
  const documentManager2 = getService$1("document-manager");
1731
- const documentMetadata2 = getService$1("document-metadata");
1732
1777
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1733
1778
  if (permissionChecker2.cannot.create()) {
1734
1779
  return ctx.forbidden();
1735
1780
  }
1736
1781
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1737
1782
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1738
- const { locale } = getDocumentLocaleAndStatus(body);
1783
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1739
1784
  const document = await documentManager2.findOne(id, model, {
1740
1785
  populate,
1741
1786
  locale,
@@ -1751,7 +1796,7 @@ const collectionTypes = {
1751
1796
  const sanitizedBody = await sanitizeFn(body);
1752
1797
  const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
1753
1798
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
1754
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument, {
1799
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
1755
1800
  // Empty metadata as it's not relevant for a new document
1756
1801
  availableLocales: false,
1757
1802
  availableStatus: false
@@ -1780,7 +1825,7 @@ const collectionTypes = {
1780
1825
  }
1781
1826
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1782
1827
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1783
- const { locale } = getDocumentLocaleAndStatus(ctx.query);
1828
+ const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
1784
1829
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1785
1830
  if (documentLocales.length === 0) {
1786
1831
  return ctx.notFound();
@@ -1802,7 +1847,6 @@ const collectionTypes = {
1802
1847
  const { id, model } = ctx.params;
1803
1848
  const { body } = ctx.request;
1804
1849
  const documentManager2 = getService$1("document-manager");
1805
- const documentMetadata2 = getService$1("document-metadata");
1806
1850
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1807
1851
  if (permissionChecker2.cannot.publish()) {
1808
1852
  return ctx.forbidden();
@@ -1814,21 +1858,25 @@ const collectionTypes = {
1814
1858
  if (permissionChecker2.cannot.publish(document)) {
1815
1859
  throw new errors.ForbiddenError();
1816
1860
  }
1817
- const { locale } = getDocumentLocaleAndStatus(body);
1818
- return documentManager2.publish(document.documentId, model, {
1861
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1862
+ const publishResult = await documentManager2.publish(document.documentId, model, {
1819
1863
  locale
1820
1864
  // TODO: Allow setting creator fields on publish
1821
1865
  // data: setCreatorFields({ user, isEdition: true })({}),
1822
1866
  });
1867
+ if (!publishResult || publishResult.length === 0) {
1868
+ throw new errors.NotFoundError("Document not found or already published.");
1869
+ }
1870
+ return publishResult[0];
1823
1871
  });
1824
1872
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
1825
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
1873
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
1826
1874
  },
1827
1875
  async bulkPublish(ctx) {
1828
1876
  const { userAbility } = ctx.state;
1829
1877
  const { model } = ctx.params;
1830
1878
  const { body } = ctx.request;
1831
- const { ids } = body;
1879
+ const { documentIds } = body;
1832
1880
  await validateBulkActionInput(body);
1833
1881
  const documentManager2 = getService$1("document-manager");
1834
1882
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
@@ -1837,8 +1885,13 @@ const collectionTypes = {
1837
1885
  }
1838
1886
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1839
1887
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1840
- const entityPromises = ids.map((id) => documentManager2.findOne(id, model, { populate }));
1841
- const entities = await Promise.all(entityPromises);
1888
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
1889
+ allowMultipleLocales: true
1890
+ });
1891
+ const entityPromises = documentIds.map(
1892
+ (documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
1893
+ );
1894
+ const entities = (await Promise.all(entityPromises)).flat();
1842
1895
  for (const entity of entities) {
1843
1896
  if (!entity) {
1844
1897
  return ctx.notFound();
@@ -1847,24 +1900,25 @@ const collectionTypes = {
1847
1900
  return ctx.forbidden();
1848
1901
  }
1849
1902
  }
1850
- const { count } = await documentManager2.publishMany(entities, model);
1903
+ const count = await documentManager2.publishMany(model, documentIds, locale);
1851
1904
  ctx.body = { count };
1852
1905
  },
1853
1906
  async bulkUnpublish(ctx) {
1854
1907
  const { userAbility } = ctx.state;
1855
1908
  const { model } = ctx.params;
1856
1909
  const { body } = ctx.request;
1857
- const { ids } = body;
1910
+ const { documentIds } = body;
1858
1911
  await validateBulkActionInput(body);
1859
1912
  const documentManager2 = getService$1("document-manager");
1860
1913
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1861
1914
  if (permissionChecker2.cannot.unpublish()) {
1862
1915
  return ctx.forbidden();
1863
1916
  }
1864
- const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1865
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1866
- const entityPromises = ids.map((id) => documentManager2.findOne(id, model, { populate }));
1867
- const entities = await Promise.all(entityPromises);
1917
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1918
+ const entityPromises = documentIds.map(
1919
+ (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1920
+ );
1921
+ const entities = (await Promise.all(entityPromises)).flat();
1868
1922
  for (const entity of entities) {
1869
1923
  if (!entity) {
1870
1924
  return ctx.notFound();
@@ -1873,7 +1927,8 @@ const collectionTypes = {
1873
1927
  return ctx.forbidden();
1874
1928
  }
1875
1929
  }
1876
- const { count } = await documentManager2.unpublishMany(entities, model);
1930
+ const entitiesIds = entities.map((document) => document.documentId);
1931
+ const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
1877
1932
  ctx.body = { count };
1878
1933
  },
1879
1934
  async unpublish(ctx) {
@@ -1883,7 +1938,6 @@ const collectionTypes = {
1883
1938
  body: { discardDraft, ...body }
1884
1939
  } = ctx.request;
1885
1940
  const documentManager2 = getService$1("document-manager");
1886
- const documentMetadata2 = getService$1("document-metadata");
1887
1941
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1888
1942
  if (permissionChecker2.cannot.unpublish()) {
1889
1943
  return ctx.forbidden();
@@ -1893,7 +1947,7 @@ const collectionTypes = {
1893
1947
  }
1894
1948
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1895
1949
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1896
- const { locale } = getDocumentLocaleAndStatus(body);
1950
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1897
1951
  const document = await documentManager2.findOne(id, model, {
1898
1952
  populate,
1899
1953
  locale,
@@ -1915,7 +1969,7 @@ const collectionTypes = {
1915
1969
  ctx.body = await async.pipe(
1916
1970
  (document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
1917
1971
  permissionChecker2.sanitizeOutput,
1918
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
1972
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
1919
1973
  )(document);
1920
1974
  });
1921
1975
  },
@@ -1924,14 +1978,13 @@ const collectionTypes = {
1924
1978
  const { id, model } = ctx.params;
1925
1979
  const { body } = ctx.request;
1926
1980
  const documentManager2 = getService$1("document-manager");
1927
- const documentMetadata2 = getService$1("document-metadata");
1928
1981
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1929
1982
  if (permissionChecker2.cannot.discard()) {
1930
1983
  return ctx.forbidden();
1931
1984
  }
1932
1985
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
1933
1986
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1934
- const { locale } = getDocumentLocaleAndStatus(body);
1987
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1935
1988
  const document = await documentManager2.findOne(id, model, {
1936
1989
  populate,
1937
1990
  locale,
@@ -1946,14 +1999,14 @@ const collectionTypes = {
1946
1999
  ctx.body = await async.pipe(
1947
2000
  (document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
1948
2001
  permissionChecker2.sanitizeOutput,
1949
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2002
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
1950
2003
  )(document);
1951
2004
  },
1952
2005
  async bulkDelete(ctx) {
1953
2006
  const { userAbility } = ctx.state;
1954
2007
  const { model } = ctx.params;
1955
2008
  const { query, body } = ctx.request;
1956
- const { ids } = body;
2009
+ const { documentIds } = body;
1957
2010
  await validateBulkActionInput(body);
1958
2011
  const documentManager2 = getService$1("document-manager");
1959
2012
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
@@ -1961,14 +2014,22 @@ const collectionTypes = {
1961
2014
  return ctx.forbidden();
1962
2015
  }
1963
2016
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
1964
- const idsWhereClause = { id: { $in: ids } };
1965
- const params = {
1966
- ...permissionQuery,
1967
- filters: {
1968
- $and: [idsWhereClause].concat(permissionQuery.filters || [])
2017
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2018
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2019
+ const documentLocales = await documentManager2.findLocales(documentIds, model, {
2020
+ populate,
2021
+ locale
2022
+ });
2023
+ if (documentLocales.length === 0) {
2024
+ return ctx.notFound();
2025
+ }
2026
+ for (const document of documentLocales) {
2027
+ if (permissionChecker2.cannot.delete(document)) {
2028
+ return ctx.forbidden();
1969
2029
  }
1970
- };
1971
- const { count } = await documentManager2.deleteMany(params, model);
2030
+ }
2031
+ const localeDocumentsIds = documentLocales.map((document) => document.documentId);
2032
+ const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
1972
2033
  ctx.body = { count };
1973
2034
  },
1974
2035
  async countDraftRelations(ctx) {
@@ -1981,7 +2042,7 @@ const collectionTypes = {
1981
2042
  }
1982
2043
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1983
2044
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1984
- const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
2045
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
1985
2046
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
1986
2047
  if (!entity) {
1987
2048
  return ctx.notFound();
@@ -1996,7 +2057,7 @@ const collectionTypes = {
1996
2057
  },
1997
2058
  async countManyEntriesDraftRelations(ctx) {
1998
2059
  const { userAbility } = ctx.state;
1999
- const ids = ctx.request.query.ids;
2060
+ const ids = ctx.request.query.documentIds;
2000
2061
  const locale = ctx.request.query.locale;
2001
2062
  const { model } = ctx.params;
2002
2063
  const documentManager2 = getService$1("document-manager");
@@ -2004,16 +2065,16 @@ const collectionTypes = {
2004
2065
  if (permissionChecker2.cannot.read()) {
2005
2066
  return ctx.forbidden();
2006
2067
  }
2007
- const entities = await documentManager2.findMany(
2068
+ const documents = await documentManager2.findMany(
2008
2069
  {
2009
2070
  filters: {
2010
- id: ids
2071
+ documentId: ids
2011
2072
  },
2012
2073
  locale
2013
2074
  },
2014
2075
  model
2015
2076
  );
2016
- if (!entities) {
2077
+ if (!documents) {
2017
2078
  return ctx.notFound();
2018
2079
  }
2019
2080
  const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
@@ -2509,7 +2570,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
2509
2570
  throw new errors.ForbiddenError();
2510
2571
  }
2511
2572
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2512
- const { locale } = getDocumentLocaleAndStatus(body);
2573
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2513
2574
  const [documentVersion, otherDocumentVersion] = await Promise.all([
2514
2575
  findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2515
2576
  // Find the first document to check if it exists
@@ -2546,12 +2607,11 @@ const singleTypes = {
2546
2607
  const { model } = ctx.params;
2547
2608
  const { query = {} } = ctx.request;
2548
2609
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2549
- const documentMetadata2 = getService$1("document-metadata");
2550
2610
  if (permissionChecker2.cannot.read()) {
2551
2611
  return ctx.forbidden();
2552
2612
  }
2553
2613
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2554
- const { locale, status } = getDocumentLocaleAndStatus(query);
2614
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
2555
2615
  const version = await findDocument(permissionQuery, model, { locale, status });
2556
2616
  if (!version) {
2557
2617
  if (permissionChecker2.cannot.create()) {
@@ -2561,8 +2621,10 @@ const singleTypes = {
2561
2621
  if (!document) {
2562
2622
  return ctx.notFound();
2563
2623
  }
2564
- const { meta } = await documentMetadata2.formatDocumentWithMetadata(
2624
+ const { meta } = await formatDocumentWithMetadata(
2625
+ permissionChecker2,
2565
2626
  model,
2627
+ // @ts-expect-error - fix types
2566
2628
  { id: document.documentId, locale, publishedAt: null },
2567
2629
  { availableLocales: true, availableStatus: false }
2568
2630
  );
@@ -2573,16 +2635,15 @@ const singleTypes = {
2573
2635
  return ctx.forbidden();
2574
2636
  }
2575
2637
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
2576
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2638
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
2577
2639
  },
2578
2640
  async createOrUpdate(ctx) {
2579
2641
  const { userAbility } = ctx.state;
2580
2642
  const { model } = ctx.params;
2581
- const documentMetadata2 = getService$1("document-metadata");
2582
2643
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2583
2644
  const document = await createOrUpdateDocument(ctx);
2584
2645
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
2585
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2646
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
2586
2647
  },
2587
2648
  async delete(ctx) {
2588
2649
  const { userAbility } = ctx.state;
@@ -2595,7 +2656,7 @@ const singleTypes = {
2595
2656
  }
2596
2657
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2597
2658
  const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2598
- const { locale } = getDocumentLocaleAndStatus(query);
2659
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2599
2660
  const documentLocales = await documentManager2.findLocales(void 0, model, {
2600
2661
  populate,
2601
2662
  locale
@@ -2618,7 +2679,6 @@ const singleTypes = {
2618
2679
  const { model } = ctx.params;
2619
2680
  const { query = {} } = ctx.request;
2620
2681
  const documentManager2 = getService$1("document-manager");
2621
- const documentMetadata2 = getService$1("document-metadata");
2622
2682
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2623
2683
  if (permissionChecker2.cannot.publish()) {
2624
2684
  return ctx.forbidden();
@@ -2633,11 +2693,12 @@ const singleTypes = {
2633
2693
  if (permissionChecker2.cannot.publish(document)) {
2634
2694
  throw new errors.ForbiddenError();
2635
2695
  }
2636
- const { locale } = getDocumentLocaleAndStatus(document);
2637
- return documentManager2.publish(document.documentId, model, { locale });
2696
+ const { locale } = await getDocumentLocaleAndStatus(document, model);
2697
+ const publishResult = await documentManager2.publish(document.documentId, model, { locale });
2698
+ return publishResult.at(0);
2638
2699
  });
2639
2700
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
2640
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2701
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
2641
2702
  },
2642
2703
  async unpublish(ctx) {
2643
2704
  const { userAbility } = ctx.state;
@@ -2647,7 +2708,6 @@ const singleTypes = {
2647
2708
  query = {}
2648
2709
  } = ctx.request;
2649
2710
  const documentManager2 = getService$1("document-manager");
2650
- const documentMetadata2 = getService$1("document-metadata");
2651
2711
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2652
2712
  if (permissionChecker2.cannot.unpublish()) {
2653
2713
  return ctx.forbidden();
@@ -2656,7 +2716,7 @@ const singleTypes = {
2656
2716
  return ctx.forbidden();
2657
2717
  }
2658
2718
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2659
- const { locale } = getDocumentLocaleAndStatus(body);
2719
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2660
2720
  const document = await findDocument(sanitizedQuery, model, { locale });
2661
2721
  if (!document) {
2662
2722
  return ctx.notFound();
@@ -2674,7 +2734,7 @@ const singleTypes = {
2674
2734
  ctx.body = await async.pipe(
2675
2735
  (document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
2676
2736
  permissionChecker2.sanitizeOutput,
2677
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2737
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
2678
2738
  )(document);
2679
2739
  });
2680
2740
  },
@@ -2683,13 +2743,12 @@ const singleTypes = {
2683
2743
  const { model } = ctx.params;
2684
2744
  const { body, query = {} } = ctx.request;
2685
2745
  const documentManager2 = getService$1("document-manager");
2686
- const documentMetadata2 = getService$1("document-metadata");
2687
2746
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2688
2747
  if (permissionChecker2.cannot.discard()) {
2689
2748
  return ctx.forbidden();
2690
2749
  }
2691
2750
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2692
- const { locale } = getDocumentLocaleAndStatus(body);
2751
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2693
2752
  const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2694
2753
  if (!document) {
2695
2754
  return ctx.notFound();
@@ -2700,7 +2759,7 @@ const singleTypes = {
2700
2759
  ctx.body = await async.pipe(
2701
2760
  (document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
2702
2761
  permissionChecker2.sanitizeOutput,
2703
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2762
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
2704
2763
  )(document);
2705
2764
  },
2706
2765
  async countDraftRelations(ctx) {
@@ -2709,7 +2768,7 @@ const singleTypes = {
2709
2768
  const { query } = ctx.request;
2710
2769
  const documentManager2 = getService$1("document-manager");
2711
2770
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2712
- const { locale } = getDocumentLocaleAndStatus(query);
2771
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2713
2772
  if (permissionChecker2.cannot.read()) {
2714
2773
  return ctx.forbidden();
2715
2774
  }
@@ -2730,7 +2789,7 @@ const uid$1 = {
2730
2789
  async generateUID(ctx) {
2731
2790
  const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2732
2791
  const { query = {} } = ctx.request;
2733
- const { locale } = getDocumentLocaleAndStatus(query);
2792
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2734
2793
  await validateUIDField(contentTypeUID, field);
2735
2794
  const uidService = getService$1("uid");
2736
2795
  ctx.body = {
@@ -2742,7 +2801,7 @@ const uid$1 = {
2742
2801
  ctx.request.body
2743
2802
  );
2744
2803
  const { query = {} } = ctx.request;
2745
- const { locale } = getDocumentLocaleAndStatus(query);
2804
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2746
2805
  await validateUIDField(contentTypeUID, field);
2747
2806
  const uidService = getService$1("uid");
2748
2807
  const isAvailable = await uidService.checkUIDAvailability({
@@ -3533,7 +3592,7 @@ const permission = ({ strapi: strapi2 }) => ({
3533
3592
  await strapi2.service("admin::permission").actionProvider.registerMany(actions);
3534
3593
  }
3535
3594
  });
3536
- const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils.contentTypes;
3595
+ const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils.contentTypes;
3537
3596
  const { isAnyToMany } = strapiUtils.relations;
3538
3597
  const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils.contentTypes.constants;
3539
3598
  const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
@@ -3624,6 +3683,42 @@ const getDeepPopulate = (uid2, {
3624
3683
  {}
3625
3684
  );
3626
3685
  };
3686
+ const getValidatableFieldsPopulate = (uid2, {
3687
+ initialPopulate = {},
3688
+ countMany = false,
3689
+ countOne = false,
3690
+ maxLevel = Infinity
3691
+ } = {}, level = 1) => {
3692
+ if (level > maxLevel) {
3693
+ return {};
3694
+ }
3695
+ const model = strapi.getModel(uid2);
3696
+ return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
3697
+ if (!getDoesAttributeRequireValidation(attribute)) {
3698
+ return populateAcc;
3699
+ }
3700
+ if (isScalarAttribute(attribute)) {
3701
+ return merge(populateAcc, {
3702
+ [attributeName]: true
3703
+ });
3704
+ }
3705
+ return merge(
3706
+ populateAcc,
3707
+ getPopulateFor(
3708
+ attributeName,
3709
+ model,
3710
+ {
3711
+ // @ts-expect-error - improve types
3712
+ initialPopulate: initialPopulate?.[attributeName],
3713
+ countMany,
3714
+ countOne,
3715
+ maxLevel
3716
+ },
3717
+ level
3718
+ )
3719
+ );
3720
+ }, {});
3721
+ };
3627
3722
  const getDeepPopulateDraftCount = (uid2) => {
3628
3723
  const model = strapi.getModel(uid2);
3629
3724
  let hasRelations = false;
@@ -3631,6 +3726,10 @@ const getDeepPopulateDraftCount = (uid2) => {
3631
3726
  const attribute = model.attributes[attributeName];
3632
3727
  switch (attribute.type) {
3633
3728
  case "relation": {
3729
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
3730
+ if (isMorphRelation) {
3731
+ break;
3732
+ }
3634
3733
  if (isVisibleAttribute$1(model, attributeName)) {
3635
3734
  populateAcc[attributeName] = {
3636
3735
  count: true,
@@ -3645,22 +3744,24 @@ const getDeepPopulateDraftCount = (uid2) => {
3645
3744
  attribute.component
3646
3745
  );
3647
3746
  if (childHasRelations) {
3648
- populateAcc[attributeName] = { populate: populate2 };
3747
+ populateAcc[attributeName] = {
3748
+ populate: populate2
3749
+ };
3649
3750
  hasRelations = true;
3650
3751
  }
3651
3752
  break;
3652
3753
  }
3653
3754
  case "dynamiczone": {
3654
- const dzPopulate = (attribute.components || []).reduce((acc, componentUID) => {
3655
- const { populate: populate2, hasRelations: childHasRelations } = getDeepPopulateDraftCount(componentUID);
3656
- if (childHasRelations) {
3755
+ const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
3756
+ const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
3757
+ if (componentHasRelations) {
3657
3758
  hasRelations = true;
3658
- return merge(acc, populate2);
3759
+ return { ...acc, [componentUID]: { populate: componentPopulate } };
3659
3760
  }
3660
3761
  return acc;
3661
3762
  }, {});
3662
- if (!isEmpty(dzPopulate)) {
3663
- populateAcc[attributeName] = { populate: dzPopulate };
3763
+ if (!isEmpty(dzPopulateFragment)) {
3764
+ populateAcc[attributeName] = { on: dzPopulateFragment };
3664
3765
  }
3665
3766
  break;
3666
3767
  }
@@ -3852,41 +3953,70 @@ const AVAILABLE_STATUS_FIELDS = [
3852
3953
  "updatedBy",
3853
3954
  "status"
3854
3955
  ];
3855
- const AVAILABLE_LOCALES_FIELDS = ["id", "locale", "updatedAt", "createdAt", "status"];
3956
+ const AVAILABLE_LOCALES_FIELDS = [
3957
+ "id",
3958
+ "locale",
3959
+ "updatedAt",
3960
+ "createdAt",
3961
+ "status",
3962
+ "publishedAt",
3963
+ "documentId"
3964
+ ];
3856
3965
  const CONTENT_MANAGER_STATUS = {
3857
3966
  PUBLISHED: "published",
3858
3967
  DRAFT: "draft",
3859
3968
  MODIFIED: "modified"
3860
3969
  };
3861
- const areDatesEqual = (date1, date2, threshold) => {
3862
- if (!date1 || !date2) {
3970
+ const getIsVersionLatestModification = (version, otherVersion) => {
3971
+ if (!version || !version.updatedAt) {
3863
3972
  return false;
3864
3973
  }
3865
- const time1 = new Date(date1).getTime();
3866
- const time2 = new Date(date2).getTime();
3867
- const difference2 = Math.abs(time1 - time2);
3868
- return difference2 <= threshold;
3974
+ const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
3975
+ const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
3976
+ return versionUpdatedAt > otherUpdatedAt;
3869
3977
  };
3870
3978
  const documentMetadata = ({ strapi: strapi2 }) => ({
3871
3979
  /**
3872
3980
  * Returns available locales of a document for the current status
3873
3981
  */
3874
- getAvailableLocales(uid2, version, allVersions) {
3982
+ async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
3875
3983
  const versionsByLocale = groupBy("locale", allVersions);
3876
3984
  delete versionsByLocale[version.locale];
3877
- return Object.values(versionsByLocale).map((localeVersions) => {
3878
- if (!contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2))) {
3879
- return pick(AVAILABLE_LOCALES_FIELDS, localeVersions[0]);
3985
+ const model = strapi2.getModel(uid2);
3986
+ const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
3987
+ const traversalFunction = async (localeVersion) => traverseEntity(
3988
+ ({ key }, { remove }) => {
3989
+ if (keysToKeep.includes(key)) {
3990
+ return;
3991
+ }
3992
+ remove(key);
3993
+ },
3994
+ { schema: model, getModel: strapi2.getModel.bind(strapi2) },
3995
+ // @ts-expect-error fix types DocumentVersion incompatible with Data
3996
+ localeVersion
3997
+ );
3998
+ const mappingResult = await async.map(
3999
+ Object.values(versionsByLocale),
4000
+ async (localeVersions) => {
4001
+ const mappedLocaleVersions = await async.map(
4002
+ localeVersions,
4003
+ traversalFunction
4004
+ );
4005
+ if (!contentTypes$1.hasDraftAndPublish(model)) {
4006
+ return mappedLocaleVersions[0];
4007
+ }
4008
+ const draftVersion = mappedLocaleVersions.find((v) => v.publishedAt === null);
4009
+ const otherVersions = mappedLocaleVersions.filter((v) => v.id !== draftVersion?.id);
4010
+ if (!draftVersion) {
4011
+ return;
4012
+ }
4013
+ return {
4014
+ ...draftVersion,
4015
+ status: this.getStatus(draftVersion, otherVersions)
4016
+ };
3880
4017
  }
3881
- const draftVersion = localeVersions.find((v) => v.publishedAt === null);
3882
- const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
3883
- if (!draftVersion)
3884
- return;
3885
- return {
3886
- ...pick(AVAILABLE_LOCALES_FIELDS, draftVersion),
3887
- status: this.getStatus(draftVersion, otherVersions)
3888
- };
3889
- }).filter(Boolean);
4018
+ );
4019
+ return mappingResult.filter(Boolean);
3890
4020
  },
3891
4021
  /**
3892
4022
  * Returns available status of a document for the current locale
@@ -3924,26 +4054,37 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3924
4054
  });
3925
4055
  },
3926
4056
  getStatus(version, otherDocumentStatuses) {
3927
- const isDraft = version.publishedAt === null;
3928
- if (!otherDocumentStatuses?.length) {
3929
- return isDraft ? CONTENT_MANAGER_STATUS.DRAFT : CONTENT_MANAGER_STATUS.PUBLISHED;
4057
+ let draftVersion;
4058
+ let publishedVersion;
4059
+ if (version.publishedAt) {
4060
+ publishedVersion = version;
4061
+ } else {
4062
+ draftVersion = version;
3930
4063
  }
3931
- if (isDraft) {
3932
- const publishedVersion = otherDocumentStatuses?.find((d) => d.publishedAt !== null);
3933
- if (!publishedVersion) {
3934
- return CONTENT_MANAGER_STATUS.DRAFT;
3935
- }
4064
+ const otherVersion = otherDocumentStatuses?.at(0);
4065
+ if (otherVersion?.publishedAt) {
4066
+ publishedVersion = otherVersion;
4067
+ } else if (otherVersion) {
4068
+ draftVersion = otherVersion;
3936
4069
  }
3937
- if (areDatesEqual(version.updatedAt, otherDocumentStatuses.at(0)?.updatedAt, 500)) {
4070
+ if (!draftVersion)
3938
4071
  return CONTENT_MANAGER_STATUS.PUBLISHED;
3939
- }
3940
- return CONTENT_MANAGER_STATUS.MODIFIED;
4072
+ if (!publishedVersion)
4073
+ return CONTENT_MANAGER_STATUS.DRAFT;
4074
+ const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
4075
+ return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
3941
4076
  },
4077
+ // TODO is it necessary to return metadata on every page of the CM
4078
+ // We could refactor this so the locales are only loaded when they're
4079
+ // needed. e.g. in the bulk locale action modal.
3942
4080
  async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
4081
+ const populate = getValidatableFieldsPopulate(uid2);
3943
4082
  const versions = await strapi2.db.query(uid2).findMany({
3944
4083
  where: { documentId: version.documentId },
3945
- select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
3946
4084
  populate: {
4085
+ // Populate only fields that require validation for bulk locale actions
4086
+ ...populate,
4087
+ // NOTE: creator fields are selected in this way to avoid exposing sensitive data
3947
4088
  createdBy: {
3948
4089
  select: ["id", "firstname", "lastname", "email"]
3949
4090
  },
@@ -3952,7 +4093,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3952
4093
  }
3953
4094
  }
3954
4095
  });
3955
- const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
4096
+ const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions, Object.keys(populate)) : [];
3956
4097
  const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
3957
4098
  return {
3958
4099
  availableLocales: availableLocalesResult,
@@ -3965,8 +4106,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3965
4106
  * - Available status of the document for the current locale
3966
4107
  */
3967
4108
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
3968
- if (!document)
4109
+ if (!document) {
3969
4110
  return document;
4111
+ }
3970
4112
  const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
3971
4113
  if (!hasDraftAndPublish) {
3972
4114
  opts.availableStatus = false;
@@ -4016,26 +4158,9 @@ const sumDraftCounts = (entity, uid2) => {
4016
4158
  }, 0);
4017
4159
  };
4018
4160
  const { ApplicationError } = errors;
4019
- const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
4020
4161
  const { PUBLISHED_AT_ATTRIBUTE } = contentTypes$1.constants;
4021
4162
  const omitPublishedAtField = omit(PUBLISHED_AT_ATTRIBUTE);
4022
4163
  const omitIdField = omit("id");
4023
- const emitEvent = async (uid2, event, document) => {
4024
- const modelDef = strapi.getModel(uid2);
4025
- const sanitizedDocument = await sanitize.sanitizers.defaultSanitizeOutput(
4026
- {
4027
- schema: modelDef,
4028
- getModel(uid22) {
4029
- return strapi.getModel(uid22);
4030
- }
4031
- },
4032
- document
4033
- );
4034
- strapi.eventHub.emit(event, {
4035
- model: modelDef.modelName,
4036
- entry: sanitizedDocument
4037
- });
4038
- };
4039
4164
  const documentManager = ({ strapi: strapi2 }) => {
4040
4165
  return {
4041
4166
  async findOne(id, uid2, opts = {}) {
@@ -4054,6 +4179,9 @@ const documentManager = ({ strapi: strapi2 }) => {
4054
4179
  } else if (opts.locale && opts.locale !== "*") {
4055
4180
  where.locale = opts.locale;
4056
4181
  }
4182
+ if (typeof opts.isPublished === "boolean") {
4183
+ where.publishedAt = { $notNull: opts.isPublished };
4184
+ }
4057
4185
  return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
4058
4186
  },
4059
4187
  async findMany(opts, uid2) {
@@ -4061,20 +4189,16 @@ const documentManager = ({ strapi: strapi2 }) => {
4061
4189
  return strapi2.documents(uid2).findMany(params);
4062
4190
  },
4063
4191
  async findPage(opts, uid2) {
4064
- const page = Number(opts?.page) || 1;
4065
- const pageSize = Number(opts?.pageSize) || 10;
4192
+ const params = pagination.withDefaultPagination(opts || {}, {
4193
+ maxLimit: 1e3
4194
+ });
4066
4195
  const [documents, total = 0] = await Promise.all([
4067
- strapi2.documents(uid2).findMany(opts),
4068
- strapi2.documents(uid2).count(opts)
4196
+ strapi2.documents(uid2).findMany(params),
4197
+ strapi2.documents(uid2).count(params)
4069
4198
  ]);
4070
4199
  return {
4071
4200
  results: documents,
4072
- pagination: {
4073
- page,
4074
- pageSize,
4075
- pageCount: Math.ceil(total / pageSize),
4076
- total
4077
- }
4201
+ pagination: pagination.transformPagedPaginationInfo(params, total)
4078
4202
  };
4079
4203
  },
4080
4204
  async create(uid2, opts = {}) {
@@ -4091,10 +4215,7 @@ const documentManager = ({ strapi: strapi2 }) => {
4091
4215
  async clone(id, body, uid2) {
4092
4216
  const populate = await buildDeepPopulate(uid2);
4093
4217
  const params = {
4094
- data: {
4095
- ...omitIdField(body),
4096
- [PUBLISHED_AT_ATTRIBUTE]: null
4097
- },
4218
+ data: omitIdField(body),
4098
4219
  populate
4099
4220
  };
4100
4221
  return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
@@ -4120,70 +4241,36 @@ const documentManager = ({ strapi: strapi2 }) => {
4120
4241
  return {};
4121
4242
  },
4122
4243
  // FIXME: handle relations
4123
- async deleteMany(opts, uid2) {
4124
- const docs = await strapi2.documents(uid2).findMany(opts);
4125
- for (const doc of docs) {
4126
- await strapi2.documents(uid2).delete({ documentId: doc.documentId });
4127
- }
4128
- return { count: docs.length };
4244
+ async deleteMany(documentIds, uid2, opts = {}) {
4245
+ const deletedEntries = await strapi2.db.transaction(async () => {
4246
+ return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
4247
+ });
4248
+ return { count: deletedEntries.length };
4129
4249
  },
4130
4250
  async publish(id, uid2, opts = {}) {
4131
4251
  const populate = await buildDeepPopulate(uid2);
4132
4252
  const params = { ...opts, populate };
4133
- return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries.at(0));
4253
+ return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
4134
4254
  },
4135
- async publishMany(entities, uid2) {
4136
- if (!entities.length) {
4137
- return null;
4138
- }
4139
- await Promise.all(
4140
- entities.map((document) => {
4141
- return strapi2.entityValidator.validateEntityCreation(
4142
- strapi2.getModel(uid2),
4143
- document,
4144
- void 0,
4145
- // @ts-expect-error - FIXME: entity here is unnecessary
4146
- document
4147
- );
4148
- })
4149
- );
4150
- const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
4151
- const filters = { id: { $in: entitiesToPublish } };
4152
- const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
4153
- const populate = await buildDeepPopulate(uid2);
4154
- const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
4155
- where: filters,
4156
- data
4157
- });
4158
- const publishedEntities = await strapi2.db.query(uid2).findMany({
4159
- where: filters,
4160
- populate
4255
+ async publishMany(uid2, documentIds, locale) {
4256
+ return strapi2.db.transaction(async () => {
4257
+ const results = await Promise.all(
4258
+ documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
4259
+ );
4260
+ const publishedEntitiesCount = results.flat().filter(Boolean).length;
4261
+ return publishedEntitiesCount;
4161
4262
  });
4162
- await Promise.all(
4163
- publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
4164
- );
4165
- return publishedEntitiesCount;
4166
4263
  },
4167
- async unpublishMany(documents, uid2) {
4168
- if (!documents.length) {
4169
- return null;
4170
- }
4171
- const entitiesToUnpublish = documents.filter((doc) => doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
4172
- const filters = { id: { $in: entitiesToUnpublish } };
4173
- const data = { [PUBLISHED_AT_ATTRIBUTE]: null };
4174
- const populate = await buildDeepPopulate(uid2);
4175
- const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
4176
- where: filters,
4177
- data
4178
- });
4179
- const unpublishedEntities = await strapi2.db.query(uid2).findMany({
4180
- where: filters,
4181
- populate
4264
+ async unpublishMany(documentIds, uid2, opts = {}) {
4265
+ const unpublishedEntries = await strapi2.db.transaction(async () => {
4266
+ return Promise.all(
4267
+ documentIds.map(
4268
+ (id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
4269
+ )
4270
+ );
4182
4271
  });
4183
- await Promise.all(
4184
- unpublishedEntities.map((doc) => emitEvent(uid2, ENTRY_UNPUBLISH, doc))
4185
- );
4186
- return unpublishedEntitiesCount;
4272
+ const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
4273
+ return { count: unpublishedEntitiesCount };
4187
4274
  },
4188
4275
  async unpublish(id, uid2, opts = {}) {
4189
4276
  const populate = await buildDeepPopulate(uid2);
@@ -4208,16 +4295,20 @@ const documentManager = ({ strapi: strapi2 }) => {
4208
4295
  }
4209
4296
  return sumDraftCounts(document, uid2);
4210
4297
  },
4211
- async countManyEntriesDraftRelations(ids, uid2, locale) {
4298
+ async countManyEntriesDraftRelations(documentIds, uid2, locale) {
4212
4299
  const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
4213
4300
  if (!hasRelations) {
4214
4301
  return 0;
4215
4302
  }
4303
+ let localeFilter = {};
4304
+ if (locale) {
4305
+ localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
4306
+ }
4216
4307
  const entities = await strapi2.db.query(uid2).findMany({
4217
4308
  populate,
4218
4309
  where: {
4219
- id: { $in: ids },
4220
- ...locale ? { locale } : {}
4310
+ documentId: { $in: documentIds },
4311
+ ...localeFilter
4221
4312
  }
4222
4313
  });
4223
4314
  const totalNumberDraftRelations = entities.reduce(