@strapi/content-manager 0.0.0-experimental.17b4116f461a49b8ce5386f7c8d79c511d40fb3b → 0.0.0-experimental.2a7cb5ff33df35e8ccde5ef918f9f9a4a3ee9a08

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 (170) hide show
  1. package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
  2. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
  3. package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
  4. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
  5. package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js → ComponentConfigurationPage-BvHtG7uH.js} +3 -3
  6. package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js.map → ComponentConfigurationPage-BvHtG7uH.js.map} +1 -1
  7. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs → ComponentConfigurationPage-DHNM3YBz.mjs} +3 -3
  8. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs.map → ComponentConfigurationPage-DHNM3YBz.mjs.map} +1 -1
  9. package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
  10. package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
  11. package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
  12. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
  13. package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs → EditConfigurationPage-Cp6HAEzN.mjs} +3 -3
  14. package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs.map → EditConfigurationPage-Cp6HAEzN.mjs.map} +1 -1
  15. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js → EditConfigurationPage-DOmfCEMo.js} +3 -3
  16. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js.map → EditConfigurationPage-DOmfCEMo.js.map} +1 -1
  17. package/dist/_chunks/{EditViewPage-KRG56aCq.js → EditViewPage-BqNpC6hO.js} +46 -48
  18. package/dist/_chunks/EditViewPage-BqNpC6hO.js.map +1 -0
  19. package/dist/_chunks/{EditViewPage-aUnqL-63.mjs → EditViewPage-BtkEx339.mjs} +47 -47
  20. package/dist/_chunks/EditViewPage-BtkEx339.mjs.map +1 -0
  21. package/dist/_chunks/{Field-kVFO4ZKB.mjs → Field-R5NbffTB.mjs} +854 -707
  22. package/dist/_chunks/Field-R5NbffTB.mjs.map +1 -0
  23. package/dist/_chunks/{Field-kq1c2TF1.js → Field-lsPFnAmH.js} +906 -760
  24. package/dist/_chunks/Field-lsPFnAmH.js.map +1 -0
  25. package/dist/_chunks/{Form-Jgh5hGTu.mjs → Form-BHmXSfyy.mjs} +39 -37
  26. package/dist/_chunks/Form-BHmXSfyy.mjs.map +1 -0
  27. package/dist/_chunks/{Form-CQ67ZifP.js → Form-CcGboku8.js} +39 -38
  28. package/dist/_chunks/Form-CcGboku8.js.map +1 -0
  29. package/dist/_chunks/{History-BLEnudTX.js → History-Bsud8jwh.js} +138 -51
  30. package/dist/_chunks/History-Bsud8jwh.js.map +1 -0
  31. package/dist/_chunks/{History-DKhZAPcK.mjs → History-ByUPL3T3.mjs} +137 -49
  32. package/dist/_chunks/History-ByUPL3T3.mjs.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-nrXcxNYi.mjs → ListConfigurationPage-Bm5HACXf.mjs} +49 -51
  34. package/dist/_chunks/ListConfigurationPage-Bm5HACXf.mjs.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-Zso_LUjn.js → ListConfigurationPage-DiT463qx.js} +53 -56
  36. package/dist/_chunks/ListConfigurationPage-DiT463qx.js.map +1 -0
  37. package/dist/_chunks/{ListViewPage-DsaOakWQ.js → ListViewPage-CsrC9L_d.js} +92 -108
  38. package/dist/_chunks/ListViewPage-CsrC9L_d.js.map +1 -0
  39. package/dist/_chunks/{ListViewPage-ChhYmA-L.mjs → ListViewPage-JSyNAAYu.mjs} +87 -103
  40. package/dist/_chunks/ListViewPage-JSyNAAYu.mjs.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-DPCuS9Y1.js → NoContentTypePage-Bsvng4II.js} +3 -3
  42. package/dist/_chunks/NoContentTypePage-Bsvng4II.js.map +1 -0
  43. package/dist/_chunks/{NoContentTypePage-BrdFcN33.mjs → NoContentTypePage-CsrQUpBE.mjs} +3 -3
  44. package/dist/_chunks/NoContentTypePage-CsrQUpBE.mjs.map +1 -0
  45. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js → NoPermissionsPage-CdHNJtEf.js} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js.map → NoPermissionsPage-CdHNJtEf.js.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs → NoPermissionsPage-DNmf_pj0.mjs} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs.map → NoPermissionsPage-DNmf_pj0.mjs.map} +1 -1
  49. package/dist/_chunks/{Relations-CY8Isqdu.js → Relations-CghaPv2D.js} +70 -61
  50. package/dist/_chunks/Relations-CghaPv2D.js.map +1 -0
  51. package/dist/_chunks/{Relations-DjFiYd7-.mjs → Relations-u8-37jK0.mjs} +66 -56
  52. package/dist/_chunks/Relations-u8-37jK0.mjs.map +1 -0
  53. package/dist/_chunks/{en-MBPul9Su.mjs → en-Ux26r5pl.mjs} +7 -1
  54. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-Ux26r5pl.mjs.map} +1 -1
  55. package/dist/_chunks/{en-C-V1_90f.js → en-fbKQxLGn.js} +7 -1
  56. package/dist/_chunks/{en-C-V1_90f.js.map → en-fbKQxLGn.js.map} +1 -1
  57. package/dist/_chunks/{index-DNa1J4HE.js → index-BOZx6IMg.js} +1481 -864
  58. package/dist/_chunks/index-BOZx6IMg.js.map +1 -0
  59. package/dist/_chunks/{index-CAc9yTnx.mjs → index-CaE6NG4a.mjs} +1450 -832
  60. package/dist/_chunks/index-CaE6NG4a.mjs.map +1 -0
  61. package/dist/_chunks/{layout-CXsHbc3E.mjs → layout-Bx7svTbY.mjs} +28 -23
  62. package/dist/_chunks/layout-Bx7svTbY.mjs.map +1 -0
  63. package/dist/_chunks/{layout-BqtLA6Lb.js → layout-Ciz224q5.js} +29 -26
  64. package/dist/_chunks/layout-Ciz224q5.js.map +1 -0
  65. package/dist/_chunks/{relations-BHY_KDJ_.js → relations-CP8sB2YZ.js} +2 -2
  66. package/dist/_chunks/{relations-BHY_KDJ_.js.map → relations-CP8sB2YZ.js.map} +1 -1
  67. package/dist/_chunks/{relations-mMFEcZRq.mjs → relations-Cxc1cEv3.mjs} +2 -2
  68. package/dist/_chunks/{relations-mMFEcZRq.mjs.map → relations-Cxc1cEv3.mjs.map} +1 -1
  69. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
  70. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
  71. package/dist/_chunks/usePrev-B9w_-eYc.js +15 -0
  72. package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
  73. package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
  74. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +1 -0
  75. package/dist/admin/index.js +2 -1
  76. package/dist/admin/index.js.map +1 -1
  77. package/dist/admin/index.mjs +5 -4
  78. package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
  79. package/dist/admin/src/content-manager.d.ts +3 -3
  80. package/dist/admin/src/exports.d.ts +1 -0
  81. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  82. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  83. package/dist/admin/src/hooks/useDocument.d.ts +5 -8
  84. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  85. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  86. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  87. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  88. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +10 -4
  89. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  90. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  91. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  92. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  93. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +10 -18
  95. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  96. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  97. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  98. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +59 -52
  99. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  100. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  101. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  102. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  103. package/dist/admin/src/services/api.d.ts +2 -3
  104. package/dist/admin/src/services/components.d.ts +2 -2
  105. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  106. package/dist/admin/src/services/documents.d.ts +29 -17
  107. package/dist/admin/src/services/init.d.ts +2 -2
  108. package/dist/admin/src/services/relations.d.ts +3 -3
  109. package/dist/admin/src/services/uid.d.ts +3 -3
  110. package/dist/admin/src/utils/api.d.ts +4 -18
  111. package/dist/admin/src/utils/validation.d.ts +1 -6
  112. package/dist/server/index.js +293 -203
  113. package/dist/server/index.js.map +1 -1
  114. package/dist/server/index.mjs +295 -205
  115. package/dist/server/index.mjs.map +1 -1
  116. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  117. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  118. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  119. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  120. package/dist/server/src/controllers/validation/dimensions.d.ts +9 -0
  121. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  122. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  123. package/dist/server/src/history/services/history.d.ts.map +1 -1
  124. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  125. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  126. package/dist/server/src/index.d.ts +17 -33
  127. package/dist/server/src/index.d.ts.map +1 -1
  128. package/dist/server/src/services/document-manager.d.ts +11 -6
  129. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  130. package/dist/server/src/services/document-metadata.d.ts +8 -29
  131. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  132. package/dist/server/src/services/index.d.ts +17 -33
  133. package/dist/server/src/services/index.d.ts.map +1 -1
  134. package/dist/server/src/services/utils/populate.d.ts +8 -1
  135. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  136. package/dist/shared/contracts/collection-types.d.ts +14 -6
  137. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  138. package/dist/shared/contracts/relations.d.ts +2 -2
  139. package/dist/shared/contracts/relations.d.ts.map +1 -1
  140. package/package.json +13 -14
  141. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  142. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  143. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  144. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  145. package/dist/_chunks/EditViewPage-KRG56aCq.js.map +0 -1
  146. package/dist/_chunks/EditViewPage-aUnqL-63.mjs.map +0 -1
  147. package/dist/_chunks/Field-kVFO4ZKB.mjs.map +0 -1
  148. package/dist/_chunks/Field-kq1c2TF1.js.map +0 -1
  149. package/dist/_chunks/Form-CQ67ZifP.js.map +0 -1
  150. package/dist/_chunks/Form-Jgh5hGTu.mjs.map +0 -1
  151. package/dist/_chunks/History-BLEnudTX.js.map +0 -1
  152. package/dist/_chunks/History-DKhZAPcK.mjs.map +0 -1
  153. package/dist/_chunks/ListConfigurationPage-Zso_LUjn.js.map +0 -1
  154. package/dist/_chunks/ListConfigurationPage-nrXcxNYi.mjs.map +0 -1
  155. package/dist/_chunks/ListViewPage-ChhYmA-L.mjs.map +0 -1
  156. package/dist/_chunks/ListViewPage-DsaOakWQ.js.map +0 -1
  157. package/dist/_chunks/NoContentTypePage-BrdFcN33.mjs.map +0 -1
  158. package/dist/_chunks/NoContentTypePage-DPCuS9Y1.js.map +0 -1
  159. package/dist/_chunks/Relations-CY8Isqdu.js.map +0 -1
  160. package/dist/_chunks/Relations-DjFiYd7-.mjs.map +0 -1
  161. package/dist/_chunks/index-CAc9yTnx.mjs.map +0 -1
  162. package/dist/_chunks/index-DNa1J4HE.js.map +0 -1
  163. package/dist/_chunks/layout-BqtLA6Lb.js.map +0 -1
  164. package/dist/_chunks/layout-CXsHbc3E.mjs.map +0 -1
  165. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  166. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  167. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  168. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  169. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  170. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
@@ -232,6 +232,10 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
232
232
  return attributes.reduce((acc, [attributeName, attribute]) => {
233
233
  switch (attribute.type) {
234
234
  case "relation": {
235
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
236
+ if (isMorphRelation) {
237
+ break;
238
+ }
235
239
  const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
236
240
  if (isVisible2) {
237
241
  acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
@@ -495,8 +499,6 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
495
499
  deleteExpiredJob: null,
496
500
  isInitialized: false
497
501
  };
498
- const query = strapi2.db.query(HISTORY_VERSION_UID);
499
- const historyService = getService(strapi2, "history");
500
502
  const serviceUtils = createServiceUtils({ strapi: strapi2 });
501
503
  return {
502
504
  async bootstrap() {
@@ -507,7 +509,10 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
507
509
  if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
508
510
  return next();
509
511
  }
510
- if (context.action !== "create" && context.action !== "update" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
512
+ if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
513
+ return next();
514
+ }
515
+ if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
511
516
  return next();
512
517
  }
513
518
  const contentTypeUid = context.contentType.uid;
@@ -515,9 +520,18 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
515
520
  return next();
516
521
  }
517
522
  const result = await next();
518
- const documentContext = context.action === "create" ? { documentId: result.documentId, locale: context.params?.locale } : { documentId: context.params.documentId, locale: context.params?.locale };
523
+ const documentContext = {
524
+ documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
525
+ locale: context.params?.locale
526
+ };
519
527
  const defaultLocale = await serviceUtils.getDefaultLocale();
520
528
  const locale = documentContext.locale || defaultLocale;
529
+ if (Array.isArray(locale)) {
530
+ strapi2.log.warn(
531
+ "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
532
+ );
533
+ return next();
534
+ }
521
535
  const document = await strapi2.documents(contentTypeUid).findOne({
522
536
  documentId: documentContext.documentId,
523
537
  locale,
@@ -540,7 +554,7 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
540
554
  }, {});
541
555
  await strapi2.db.transaction(async ({ onCommit }) => {
542
556
  onCommit(() => {
543
- historyService.createVersion({
557
+ getService(strapi2, "history").createVersion({
544
558
  contentType: contentTypeUid,
545
559
  data: fp.omit(FIELDS_TO_IGNORE, document),
546
560
  schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
@@ -553,11 +567,10 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
553
567
  });
554
568
  return result;
555
569
  });
556
- const retentionDays = serviceUtils.getRetentionDays();
557
570
  state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
558
- const retentionDaysInMilliseconds = retentionDays * 24 * 60 * 60 * 1e3;
571
+ const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
559
572
  const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
560
- query.deleteMany({
573
+ strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
561
574
  where: {
562
575
  created_at: {
563
576
  $lt: expirationDate.toISOString()
@@ -1478,7 +1491,7 @@ const { PaginationError, ValidationError } = strapiUtils.errors;
1478
1491
  const TYPES = ["singleType", "collectionType"];
1479
1492
  const kindSchema = strapiUtils.yup.string().oneOf(TYPES).nullable();
1480
1493
  const bulkActionInputSchema = strapiUtils.yup.object({
1481
- ids: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()).min(1).required()
1494
+ documentIds: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()).min(1).required()
1482
1495
  }).required();
1483
1496
  const generateUIDInputSchema = strapiUtils.yup.object({
1484
1497
  contentTypeUID: strapiUtils.yup.string().required(),
@@ -1577,15 +1590,47 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
1577
1590
  }
1578
1591
  }, body);
1579
1592
  };
1580
- const getDocumentLocaleAndStatus = (request) => {
1593
+ const singleLocaleSchema = strapiUtils.yup.string().nullable();
1594
+ const multipleLocaleSchema = strapiUtils.yup.lazy(
1595
+ (value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
1596
+ );
1597
+ const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
1598
+ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
1599
+ const { allowMultipleLocales } = opts;
1581
1600
  const { locale, status, ...rest } = request || {};
1582
- if (!fp.isNil(locale) && typeof locale !== "string") {
1583
- throw new strapiUtils.errors.ValidationError(`Invalid locale: ${locale}`);
1584
- }
1585
- if (!fp.isNil(status) && !["draft", "published"].includes(status)) {
1586
- throw new strapiUtils.errors.ValidationError(`Invalid status: ${status}`);
1601
+ const schema = strapiUtils.yup.object().shape({
1602
+ locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
1603
+ status: statusSchema
1604
+ });
1605
+ try {
1606
+ await strapiUtils.validateYupSchema(schema, { strict: true, abortEarly: false })(request);
1607
+ return { locale, status, ...rest };
1608
+ } catch (error) {
1609
+ throw new strapiUtils.errors.ValidationError(`Validation error: ${error.message}`);
1587
1610
  }
1588
- return { locale, status, ...rest };
1611
+ };
1612
+ const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
1613
+ const documentMetadata2 = getService$1("document-metadata");
1614
+ const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
1615
+ let {
1616
+ meta: { availableLocales, availableStatus }
1617
+ } = serviceOutput;
1618
+ const metadataSanitizer = permissionChecker2.sanitizeOutput;
1619
+ availableLocales = await strapiUtils.async.map(
1620
+ availableLocales,
1621
+ async (localeDocument) => metadataSanitizer(localeDocument)
1622
+ );
1623
+ availableStatus = await strapiUtils.async.map(
1624
+ availableStatus,
1625
+ async (statusDocument) => metadataSanitizer(statusDocument)
1626
+ );
1627
+ return {
1628
+ ...serviceOutput,
1629
+ meta: {
1630
+ availableLocales,
1631
+ availableStatus
1632
+ }
1633
+ };
1589
1634
  };
1590
1635
  const createDocument = async (ctx, opts) => {
1591
1636
  const { userAbility, user } = ctx.state;
@@ -1600,7 +1645,7 @@ const createDocument = async (ctx, opts) => {
1600
1645
  const setCreator = strapiUtils.setCreatorFields({ user });
1601
1646
  const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1602
1647
  const sanitizedBody = await sanitizeFn(body);
1603
- const { locale, status = "draft" } = getDocumentLocaleAndStatus(body);
1648
+ const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
1604
1649
  return documentManager2.create(model, {
1605
1650
  data: sanitizedBody,
1606
1651
  locale,
@@ -1619,7 +1664,7 @@ const updateDocument = async (ctx, opts) => {
1619
1664
  }
1620
1665
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1621
1666
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1622
- const { locale } = getDocumentLocaleAndStatus(body);
1667
+ const { locale } = await getDocumentLocaleAndStatus(body);
1623
1668
  const [documentVersion, documentExists] = await Promise.all([
1624
1669
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1625
1670
  documentManager2.exists(model, id)
@@ -1657,7 +1702,7 @@ const collectionTypes = {
1657
1702
  }
1658
1703
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1659
1704
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1660
- const { locale, status } = getDocumentLocaleAndStatus(query);
1705
+ const { locale, status } = await getDocumentLocaleAndStatus(query);
1661
1706
  const { results: documents, pagination } = await documentManager2.findPage(
1662
1707
  { ...permissionQuery, populate, locale, status },
1663
1708
  model
@@ -1686,14 +1731,13 @@ const collectionTypes = {
1686
1731
  const { userAbility } = ctx.state;
1687
1732
  const { model, id } = ctx.params;
1688
1733
  const documentManager2 = getService$1("document-manager");
1689
- const documentMetadata2 = getService$1("document-metadata");
1690
1734
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1691
1735
  if (permissionChecker2.cannot.read()) {
1692
1736
  return ctx.forbidden();
1693
1737
  }
1694
1738
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1695
1739
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1696
- const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
1740
+ const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
1697
1741
  const version = await documentManager2.findOne(id, model, {
1698
1742
  populate,
1699
1743
  locale,
@@ -1704,8 +1748,10 @@ const collectionTypes = {
1704
1748
  if (!exists) {
1705
1749
  return ctx.notFound();
1706
1750
  }
1707
- const { meta } = await documentMetadata2.formatDocumentWithMetadata(
1751
+ const { meta } = await formatDocumentWithMetadata(
1752
+ permissionChecker2,
1708
1753
  model,
1754
+ // @ts-expect-error TODO: fix
1709
1755
  { id, locale, publishedAt: null },
1710
1756
  { availableLocales: true, availableStatus: false }
1711
1757
  );
@@ -1716,12 +1762,11 @@ const collectionTypes = {
1716
1762
  return ctx.forbidden();
1717
1763
  }
1718
1764
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
1719
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
1765
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
1720
1766
  },
1721
1767
  async create(ctx) {
1722
1768
  const { userAbility } = ctx.state;
1723
1769
  const { model } = ctx.params;
1724
- const documentMetadata2 = getService$1("document-metadata");
1725
1770
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1726
1771
  const [totalEntries, document] = await Promise.all([
1727
1772
  strapi.db.query(model).count(),
@@ -1729,7 +1774,7 @@ const collectionTypes = {
1729
1774
  ]);
1730
1775
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
1731
1776
  ctx.status = 201;
1732
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument, {
1777
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
1733
1778
  // Empty metadata as it's not relevant for a new document
1734
1779
  availableLocales: false,
1735
1780
  availableStatus: false
@@ -1743,25 +1788,23 @@ const collectionTypes = {
1743
1788
  async update(ctx) {
1744
1789
  const { userAbility } = ctx.state;
1745
1790
  const { model } = ctx.params;
1746
- const documentMetadata2 = getService$1("document-metadata");
1747
1791
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1748
1792
  const updatedVersion = await updateDocument(ctx);
1749
1793
  const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
1750
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedVersion);
1794
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
1751
1795
  },
1752
1796
  async clone(ctx) {
1753
1797
  const { userAbility, user } = ctx.state;
1754
1798
  const { model, sourceId: id } = ctx.params;
1755
1799
  const { body } = ctx.request;
1756
1800
  const documentManager2 = getService$1("document-manager");
1757
- const documentMetadata2 = getService$1("document-metadata");
1758
1801
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1759
1802
  if (permissionChecker2.cannot.create()) {
1760
1803
  return ctx.forbidden();
1761
1804
  }
1762
1805
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1763
1806
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1764
- const { locale } = getDocumentLocaleAndStatus(body);
1807
+ const { locale } = await getDocumentLocaleAndStatus(body);
1765
1808
  const document = await documentManager2.findOne(id, model, {
1766
1809
  populate,
1767
1810
  locale,
@@ -1777,7 +1820,7 @@ const collectionTypes = {
1777
1820
  const sanitizedBody = await sanitizeFn(body);
1778
1821
  const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
1779
1822
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
1780
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument, {
1823
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
1781
1824
  // Empty metadata as it's not relevant for a new document
1782
1825
  availableLocales: false,
1783
1826
  availableStatus: false
@@ -1806,7 +1849,7 @@ const collectionTypes = {
1806
1849
  }
1807
1850
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1808
1851
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1809
- const { locale } = getDocumentLocaleAndStatus(ctx.query);
1852
+ const { locale } = await getDocumentLocaleAndStatus(ctx.query);
1810
1853
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1811
1854
  if (documentLocales.length === 0) {
1812
1855
  return ctx.notFound();
@@ -1828,7 +1871,6 @@ const collectionTypes = {
1828
1871
  const { id, model } = ctx.params;
1829
1872
  const { body } = ctx.request;
1830
1873
  const documentManager2 = getService$1("document-manager");
1831
- const documentMetadata2 = getService$1("document-metadata");
1832
1874
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1833
1875
  if (permissionChecker2.cannot.publish()) {
1834
1876
  return ctx.forbidden();
@@ -1840,21 +1882,25 @@ const collectionTypes = {
1840
1882
  if (permissionChecker2.cannot.publish(document)) {
1841
1883
  throw new strapiUtils.errors.ForbiddenError();
1842
1884
  }
1843
- const { locale } = getDocumentLocaleAndStatus(body);
1844
- return documentManager2.publish(document.documentId, model, {
1885
+ const { locale } = await getDocumentLocaleAndStatus(body);
1886
+ const publishResult = await documentManager2.publish(document.documentId, model, {
1845
1887
  locale
1846
1888
  // TODO: Allow setting creator fields on publish
1847
1889
  // data: setCreatorFields({ user, isEdition: true })({}),
1848
1890
  });
1891
+ if (!publishResult || publishResult.length === 0) {
1892
+ throw new strapiUtils.errors.NotFoundError("Document not found or already published.");
1893
+ }
1894
+ return publishResult[0];
1849
1895
  });
1850
1896
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
1851
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
1897
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
1852
1898
  },
1853
1899
  async bulkPublish(ctx) {
1854
1900
  const { userAbility } = ctx.state;
1855
1901
  const { model } = ctx.params;
1856
1902
  const { body } = ctx.request;
1857
- const { ids } = body;
1903
+ const { documentIds } = body;
1858
1904
  await validateBulkActionInput(body);
1859
1905
  const documentManager2 = getService$1("document-manager");
1860
1906
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
@@ -1863,8 +1909,11 @@ const collectionTypes = {
1863
1909
  }
1864
1910
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1865
1911
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1866
- const entityPromises = ids.map((id) => documentManager2.findOne(id, model, { populate }));
1867
- const entities = await Promise.all(entityPromises);
1912
+ const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
1913
+ const entityPromises = documentIds.map(
1914
+ (documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
1915
+ );
1916
+ const entities = (await Promise.all(entityPromises)).flat();
1868
1917
  for (const entity of entities) {
1869
1918
  if (!entity) {
1870
1919
  return ctx.notFound();
@@ -1873,24 +1922,25 @@ const collectionTypes = {
1873
1922
  return ctx.forbidden();
1874
1923
  }
1875
1924
  }
1876
- const { count } = await documentManager2.publishMany(entities, model);
1925
+ const count = await documentManager2.publishMany(model, documentIds, locale);
1877
1926
  ctx.body = { count };
1878
1927
  },
1879
1928
  async bulkUnpublish(ctx) {
1880
1929
  const { userAbility } = ctx.state;
1881
1930
  const { model } = ctx.params;
1882
1931
  const { body } = ctx.request;
1883
- const { ids } = body;
1932
+ const { documentIds } = body;
1884
1933
  await validateBulkActionInput(body);
1885
1934
  const documentManager2 = getService$1("document-manager");
1886
1935
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1887
1936
  if (permissionChecker2.cannot.unpublish()) {
1888
1937
  return ctx.forbidden();
1889
1938
  }
1890
- const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1891
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1892
- const entityPromises = ids.map((id) => documentManager2.findOne(id, model, { populate }));
1893
- const entities = await Promise.all(entityPromises);
1939
+ const { locale } = await getDocumentLocaleAndStatus(body);
1940
+ const entityPromises = documentIds.map(
1941
+ (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1942
+ );
1943
+ const entities = (await Promise.all(entityPromises)).flat();
1894
1944
  for (const entity of entities) {
1895
1945
  if (!entity) {
1896
1946
  return ctx.notFound();
@@ -1899,7 +1949,8 @@ const collectionTypes = {
1899
1949
  return ctx.forbidden();
1900
1950
  }
1901
1951
  }
1902
- const { count } = await documentManager2.unpublishMany(entities, model);
1952
+ const entitiesIds = entities.map((document) => document.documentId);
1953
+ const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
1903
1954
  ctx.body = { count };
1904
1955
  },
1905
1956
  async unpublish(ctx) {
@@ -1909,7 +1960,6 @@ const collectionTypes = {
1909
1960
  body: { discardDraft, ...body }
1910
1961
  } = ctx.request;
1911
1962
  const documentManager2 = getService$1("document-manager");
1912
- const documentMetadata2 = getService$1("document-metadata");
1913
1963
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1914
1964
  if (permissionChecker2.cannot.unpublish()) {
1915
1965
  return ctx.forbidden();
@@ -1919,7 +1969,7 @@ const collectionTypes = {
1919
1969
  }
1920
1970
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1921
1971
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1922
- const { locale } = getDocumentLocaleAndStatus(body);
1972
+ const { locale } = await getDocumentLocaleAndStatus(body);
1923
1973
  const document = await documentManager2.findOne(id, model, {
1924
1974
  populate,
1925
1975
  locale,
@@ -1941,7 +1991,7 @@ const collectionTypes = {
1941
1991
  ctx.body = await strapiUtils.async.pipe(
1942
1992
  (document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
1943
1993
  permissionChecker2.sanitizeOutput,
1944
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
1994
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
1945
1995
  )(document);
1946
1996
  });
1947
1997
  },
@@ -1950,14 +2000,13 @@ const collectionTypes = {
1950
2000
  const { id, model } = ctx.params;
1951
2001
  const { body } = ctx.request;
1952
2002
  const documentManager2 = getService$1("document-manager");
1953
- const documentMetadata2 = getService$1("document-metadata");
1954
2003
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1955
2004
  if (permissionChecker2.cannot.discard()) {
1956
2005
  return ctx.forbidden();
1957
2006
  }
1958
2007
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
1959
2008
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1960
- const { locale } = getDocumentLocaleAndStatus(body);
2009
+ const { locale } = await getDocumentLocaleAndStatus(body);
1961
2010
  const document = await documentManager2.findOne(id, model, {
1962
2011
  populate,
1963
2012
  locale,
@@ -1972,14 +2021,14 @@ const collectionTypes = {
1972
2021
  ctx.body = await strapiUtils.async.pipe(
1973
2022
  (document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
1974
2023
  permissionChecker2.sanitizeOutput,
1975
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2024
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
1976
2025
  )(document);
1977
2026
  },
1978
2027
  async bulkDelete(ctx) {
1979
2028
  const { userAbility } = ctx.state;
1980
2029
  const { model } = ctx.params;
1981
2030
  const { query, body } = ctx.request;
1982
- const { ids } = body;
2031
+ const { documentIds } = body;
1983
2032
  await validateBulkActionInput(body);
1984
2033
  const documentManager2 = getService$1("document-manager");
1985
2034
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
@@ -1987,14 +2036,22 @@ const collectionTypes = {
1987
2036
  return ctx.forbidden();
1988
2037
  }
1989
2038
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
1990
- const idsWhereClause = { id: { $in: ids } };
1991
- const params = {
1992
- ...permissionQuery,
1993
- filters: {
1994
- $and: [idsWhereClause].concat(permissionQuery.filters || [])
2039
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2040
+ const { locale } = await getDocumentLocaleAndStatus(body);
2041
+ const documentLocales = await documentManager2.findLocales(documentIds, model, {
2042
+ populate,
2043
+ locale
2044
+ });
2045
+ if (documentLocales.length === 0) {
2046
+ return ctx.notFound();
2047
+ }
2048
+ for (const document of documentLocales) {
2049
+ if (permissionChecker2.cannot.delete(document)) {
2050
+ return ctx.forbidden();
1995
2051
  }
1996
- };
1997
- const { count } = await documentManager2.deleteMany(params, model);
2052
+ }
2053
+ const localeDocumentsIds = documentLocales.map((document) => document.documentId);
2054
+ const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
1998
2055
  ctx.body = { count };
1999
2056
  },
2000
2057
  async countDraftRelations(ctx) {
@@ -2007,7 +2064,7 @@ const collectionTypes = {
2007
2064
  }
2008
2065
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2009
2066
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2010
- const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
2067
+ const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
2011
2068
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
2012
2069
  if (!entity) {
2013
2070
  return ctx.notFound();
@@ -2022,7 +2079,7 @@ const collectionTypes = {
2022
2079
  },
2023
2080
  async countManyEntriesDraftRelations(ctx) {
2024
2081
  const { userAbility } = ctx.state;
2025
- const ids = ctx.request.query.ids;
2082
+ const ids = ctx.request.query.documentIds;
2026
2083
  const locale = ctx.request.query.locale;
2027
2084
  const { model } = ctx.params;
2028
2085
  const documentManager2 = getService$1("document-manager");
@@ -2030,16 +2087,16 @@ const collectionTypes = {
2030
2087
  if (permissionChecker2.cannot.read()) {
2031
2088
  return ctx.forbidden();
2032
2089
  }
2033
- const entities = await documentManager2.findMany(
2090
+ const documents = await documentManager2.findMany(
2034
2091
  {
2035
2092
  filters: {
2036
- id: ids
2093
+ documentId: ids
2037
2094
  },
2038
2095
  locale
2039
2096
  },
2040
2097
  model
2041
2098
  );
2042
- if (!entities) {
2099
+ if (!documents) {
2043
2100
  return ctx.notFound();
2044
2101
  }
2045
2102
  const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
@@ -2535,7 +2592,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
2535
2592
  throw new strapiUtils.errors.ForbiddenError();
2536
2593
  }
2537
2594
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2538
- const { locale } = getDocumentLocaleAndStatus(body);
2595
+ const { locale } = await getDocumentLocaleAndStatus(body);
2539
2596
  const [documentVersion, otherDocumentVersion] = await Promise.all([
2540
2597
  findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2541
2598
  // Find the first document to check if it exists
@@ -2572,12 +2629,11 @@ const singleTypes = {
2572
2629
  const { model } = ctx.params;
2573
2630
  const { query = {} } = ctx.request;
2574
2631
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2575
- const documentMetadata2 = getService$1("document-metadata");
2576
2632
  if (permissionChecker2.cannot.read()) {
2577
2633
  return ctx.forbidden();
2578
2634
  }
2579
2635
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2580
- const { locale, status } = getDocumentLocaleAndStatus(query);
2636
+ const { locale, status } = await getDocumentLocaleAndStatus(query);
2581
2637
  const version = await findDocument(permissionQuery, model, { locale, status });
2582
2638
  if (!version) {
2583
2639
  if (permissionChecker2.cannot.create()) {
@@ -2587,8 +2643,10 @@ const singleTypes = {
2587
2643
  if (!document) {
2588
2644
  return ctx.notFound();
2589
2645
  }
2590
- const { meta } = await documentMetadata2.formatDocumentWithMetadata(
2646
+ const { meta } = await formatDocumentWithMetadata(
2647
+ permissionChecker2,
2591
2648
  model,
2649
+ // @ts-expect-error - fix types
2592
2650
  { id: document.documentId, locale, publishedAt: null },
2593
2651
  { availableLocales: true, availableStatus: false }
2594
2652
  );
@@ -2599,16 +2657,15 @@ const singleTypes = {
2599
2657
  return ctx.forbidden();
2600
2658
  }
2601
2659
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
2602
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2660
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
2603
2661
  },
2604
2662
  async createOrUpdate(ctx) {
2605
2663
  const { userAbility } = ctx.state;
2606
2664
  const { model } = ctx.params;
2607
- const documentMetadata2 = getService$1("document-metadata");
2608
2665
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2609
2666
  const document = await createOrUpdateDocument(ctx);
2610
2667
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
2611
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2668
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
2612
2669
  },
2613
2670
  async delete(ctx) {
2614
2671
  const { userAbility } = ctx.state;
@@ -2621,7 +2678,7 @@ const singleTypes = {
2621
2678
  }
2622
2679
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2623
2680
  const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2624
- const { locale } = getDocumentLocaleAndStatus(query);
2681
+ const { locale } = await getDocumentLocaleAndStatus(query);
2625
2682
  const documentLocales = await documentManager2.findLocales(void 0, model, {
2626
2683
  populate,
2627
2684
  locale
@@ -2644,7 +2701,6 @@ const singleTypes = {
2644
2701
  const { model } = ctx.params;
2645
2702
  const { query = {} } = ctx.request;
2646
2703
  const documentManager2 = getService$1("document-manager");
2647
- const documentMetadata2 = getService$1("document-metadata");
2648
2704
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2649
2705
  if (permissionChecker2.cannot.publish()) {
2650
2706
  return ctx.forbidden();
@@ -2659,11 +2715,12 @@ const singleTypes = {
2659
2715
  if (permissionChecker2.cannot.publish(document)) {
2660
2716
  throw new strapiUtils.errors.ForbiddenError();
2661
2717
  }
2662
- const { locale } = getDocumentLocaleAndStatus(document);
2663
- return documentManager2.publish(document.documentId, model, { locale });
2718
+ const { locale } = await getDocumentLocaleAndStatus(document);
2719
+ const publishResult = await documentManager2.publish(document.documentId, model, { locale });
2720
+ return publishResult.at(0);
2664
2721
  });
2665
2722
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
2666
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2723
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
2667
2724
  },
2668
2725
  async unpublish(ctx) {
2669
2726
  const { userAbility } = ctx.state;
@@ -2673,7 +2730,6 @@ const singleTypes = {
2673
2730
  query = {}
2674
2731
  } = ctx.request;
2675
2732
  const documentManager2 = getService$1("document-manager");
2676
- const documentMetadata2 = getService$1("document-metadata");
2677
2733
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2678
2734
  if (permissionChecker2.cannot.unpublish()) {
2679
2735
  return ctx.forbidden();
@@ -2682,7 +2738,7 @@ const singleTypes = {
2682
2738
  return ctx.forbidden();
2683
2739
  }
2684
2740
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2685
- const { locale } = getDocumentLocaleAndStatus(body);
2741
+ const { locale } = await getDocumentLocaleAndStatus(body);
2686
2742
  const document = await findDocument(sanitizedQuery, model, { locale });
2687
2743
  if (!document) {
2688
2744
  return ctx.notFound();
@@ -2700,7 +2756,7 @@ const singleTypes = {
2700
2756
  ctx.body = await strapiUtils.async.pipe(
2701
2757
  (document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
2702
2758
  permissionChecker2.sanitizeOutput,
2703
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2759
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
2704
2760
  )(document);
2705
2761
  });
2706
2762
  },
@@ -2709,13 +2765,12 @@ const singleTypes = {
2709
2765
  const { model } = ctx.params;
2710
2766
  const { body, query = {} } = ctx.request;
2711
2767
  const documentManager2 = getService$1("document-manager");
2712
- const documentMetadata2 = getService$1("document-metadata");
2713
2768
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2714
2769
  if (permissionChecker2.cannot.discard()) {
2715
2770
  return ctx.forbidden();
2716
2771
  }
2717
2772
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2718
- const { locale } = getDocumentLocaleAndStatus(body);
2773
+ const { locale } = await getDocumentLocaleAndStatus(body);
2719
2774
  const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2720
2775
  if (!document) {
2721
2776
  return ctx.notFound();
@@ -2726,7 +2781,7 @@ const singleTypes = {
2726
2781
  ctx.body = await strapiUtils.async.pipe(
2727
2782
  (document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
2728
2783
  permissionChecker2.sanitizeOutput,
2729
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2784
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
2730
2785
  )(document);
2731
2786
  },
2732
2787
  async countDraftRelations(ctx) {
@@ -2735,7 +2790,7 @@ const singleTypes = {
2735
2790
  const { query } = ctx.request;
2736
2791
  const documentManager2 = getService$1("document-manager");
2737
2792
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2738
- const { locale } = getDocumentLocaleAndStatus(query);
2793
+ const { locale } = await getDocumentLocaleAndStatus(query);
2739
2794
  if (permissionChecker2.cannot.read()) {
2740
2795
  return ctx.forbidden();
2741
2796
  }
@@ -2756,7 +2811,7 @@ const uid$1 = {
2756
2811
  async generateUID(ctx) {
2757
2812
  const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2758
2813
  const { query = {} } = ctx.request;
2759
- const { locale } = getDocumentLocaleAndStatus(query);
2814
+ const { locale } = await getDocumentLocaleAndStatus(query);
2760
2815
  await validateUIDField(contentTypeUID, field);
2761
2816
  const uidService = getService$1("uid");
2762
2817
  ctx.body = {
@@ -2768,7 +2823,7 @@ const uid$1 = {
2768
2823
  ctx.request.body
2769
2824
  );
2770
2825
  const { query = {} } = ctx.request;
2771
- const { locale } = getDocumentLocaleAndStatus(query);
2826
+ const { locale } = await getDocumentLocaleAndStatus(query);
2772
2827
  await validateUIDField(contentTypeUID, field);
2773
2828
  const uidService = getService$1("uid");
2774
2829
  const isAvailable = await uidService.checkUIDAvailability({
@@ -3559,7 +3614,7 @@ const permission = ({ strapi: strapi2 }) => ({
3559
3614
  await strapi2.service("admin::permission").actionProvider.registerMany(actions);
3560
3615
  }
3561
3616
  });
3562
- const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils__default.default.contentTypes;
3617
+ const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils__default.default.contentTypes;
3563
3618
  const { isAnyToMany } = strapiUtils__default.default.relations;
3564
3619
  const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils__default.default.contentTypes.constants;
3565
3620
  const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
@@ -3650,6 +3705,42 @@ const getDeepPopulate = (uid2, {
3650
3705
  {}
3651
3706
  );
3652
3707
  };
3708
+ const getValidatableFieldsPopulate = (uid2, {
3709
+ initialPopulate = {},
3710
+ countMany = false,
3711
+ countOne = false,
3712
+ maxLevel = Infinity
3713
+ } = {}, level = 1) => {
3714
+ if (level > maxLevel) {
3715
+ return {};
3716
+ }
3717
+ const model = strapi.getModel(uid2);
3718
+ return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
3719
+ if (!getDoesAttributeRequireValidation(attribute)) {
3720
+ return populateAcc;
3721
+ }
3722
+ if (isScalarAttribute(attribute)) {
3723
+ return fp.merge(populateAcc, {
3724
+ [attributeName]: true
3725
+ });
3726
+ }
3727
+ return fp.merge(
3728
+ populateAcc,
3729
+ getPopulateFor(
3730
+ attributeName,
3731
+ model,
3732
+ {
3733
+ // @ts-expect-error - improve types
3734
+ initialPopulate: initialPopulate?.[attributeName],
3735
+ countMany,
3736
+ countOne,
3737
+ maxLevel
3738
+ },
3739
+ level
3740
+ )
3741
+ );
3742
+ }, {});
3743
+ };
3653
3744
  const getDeepPopulateDraftCount = (uid2) => {
3654
3745
  const model = strapi.getModel(uid2);
3655
3746
  let hasRelations = false;
@@ -3671,22 +3762,24 @@ const getDeepPopulateDraftCount = (uid2) => {
3671
3762
  attribute.component
3672
3763
  );
3673
3764
  if (childHasRelations) {
3674
- populateAcc[attributeName] = { populate: populate2 };
3765
+ populateAcc[attributeName] = {
3766
+ populate: populate2
3767
+ };
3675
3768
  hasRelations = true;
3676
3769
  }
3677
3770
  break;
3678
3771
  }
3679
3772
  case "dynamiczone": {
3680
- const dzPopulate = (attribute.components || []).reduce((acc, componentUID) => {
3681
- const { populate: populate2, hasRelations: childHasRelations } = getDeepPopulateDraftCount(componentUID);
3682
- if (childHasRelations) {
3773
+ const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
3774
+ const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
3775
+ if (componentHasRelations) {
3683
3776
  hasRelations = true;
3684
- return fp.merge(acc, populate2);
3777
+ return { ...acc, [componentUID]: { populate: componentPopulate } };
3685
3778
  }
3686
3779
  return acc;
3687
3780
  }, {});
3688
- if (!fp.isEmpty(dzPopulate)) {
3689
- populateAcc[attributeName] = { populate: dzPopulate };
3781
+ if (!fp.isEmpty(dzPopulateFragment)) {
3782
+ populateAcc[attributeName] = { on: dzPopulateFragment };
3690
3783
  }
3691
3784
  break;
3692
3785
  }
@@ -3878,41 +3971,70 @@ const AVAILABLE_STATUS_FIELDS = [
3878
3971
  "updatedBy",
3879
3972
  "status"
3880
3973
  ];
3881
- const AVAILABLE_LOCALES_FIELDS = ["id", "locale", "updatedAt", "createdAt", "status"];
3974
+ const AVAILABLE_LOCALES_FIELDS = [
3975
+ "id",
3976
+ "locale",
3977
+ "updatedAt",
3978
+ "createdAt",
3979
+ "status",
3980
+ "publishedAt",
3981
+ "documentId"
3982
+ ];
3882
3983
  const CONTENT_MANAGER_STATUS = {
3883
3984
  PUBLISHED: "published",
3884
3985
  DRAFT: "draft",
3885
3986
  MODIFIED: "modified"
3886
3987
  };
3887
- const areDatesEqual = (date1, date2, threshold) => {
3888
- if (!date1 || !date2) {
3988
+ const getIsVersionLatestModification = (version, otherVersion) => {
3989
+ if (!version || !version.updatedAt) {
3889
3990
  return false;
3890
3991
  }
3891
- const time1 = new Date(date1).getTime();
3892
- const time2 = new Date(date2).getTime();
3893
- const difference = Math.abs(time1 - time2);
3894
- return difference <= threshold;
3992
+ const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
3993
+ const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
3994
+ return versionUpdatedAt > otherUpdatedAt;
3895
3995
  };
3896
3996
  const documentMetadata = ({ strapi: strapi2 }) => ({
3897
3997
  /**
3898
3998
  * Returns available locales of a document for the current status
3899
3999
  */
3900
- getAvailableLocales(uid2, version, allVersions) {
4000
+ async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
3901
4001
  const versionsByLocale = fp.groupBy("locale", allVersions);
3902
4002
  delete versionsByLocale[version.locale];
3903
- return Object.values(versionsByLocale).map((localeVersions) => {
3904
- if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2))) {
3905
- return fp.pick(AVAILABLE_LOCALES_FIELDS, localeVersions[0]);
4003
+ const model = strapi2.getModel(uid2);
4004
+ const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
4005
+ const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
4006
+ ({ key }, { remove }) => {
4007
+ if (keysToKeep.includes(key)) {
4008
+ return;
4009
+ }
4010
+ remove(key);
4011
+ },
4012
+ { schema: model, getModel: strapi2.getModel.bind(strapi2) },
4013
+ // @ts-expect-error fix types DocumentVersion incompatible with Data
4014
+ localeVersion
4015
+ );
4016
+ const mappingResult = await strapiUtils.async.map(
4017
+ Object.values(versionsByLocale),
4018
+ async (localeVersions) => {
4019
+ const mappedLocaleVersions = await strapiUtils.async.map(
4020
+ localeVersions,
4021
+ traversalFunction
4022
+ );
4023
+ if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
4024
+ return mappedLocaleVersions[0];
4025
+ }
4026
+ const draftVersion = mappedLocaleVersions.find((v) => v.publishedAt === null);
4027
+ const otherVersions = mappedLocaleVersions.filter((v) => v.id !== draftVersion?.id);
4028
+ if (!draftVersion) {
4029
+ return;
4030
+ }
4031
+ return {
4032
+ ...draftVersion,
4033
+ status: this.getStatus(draftVersion, otherVersions)
4034
+ };
3906
4035
  }
3907
- const draftVersion = localeVersions.find((v) => v.publishedAt === null);
3908
- const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
3909
- if (!draftVersion)
3910
- return;
3911
- return {
3912
- ...fp.pick(AVAILABLE_LOCALES_FIELDS, draftVersion),
3913
- status: this.getStatus(draftVersion, otherVersions)
3914
- };
3915
- }).filter(Boolean);
4036
+ );
4037
+ return mappingResult.filter(Boolean);
3916
4038
  },
3917
4039
  /**
3918
4040
  * Returns available status of a document for the current locale
@@ -3950,26 +4072,37 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3950
4072
  });
3951
4073
  },
3952
4074
  getStatus(version, otherDocumentStatuses) {
3953
- const isDraft = version.publishedAt === null;
3954
- if (!otherDocumentStatuses?.length) {
3955
- return isDraft ? CONTENT_MANAGER_STATUS.DRAFT : CONTENT_MANAGER_STATUS.PUBLISHED;
4075
+ let draftVersion;
4076
+ let publishedVersion;
4077
+ if (version.publishedAt) {
4078
+ publishedVersion = version;
4079
+ } else {
4080
+ draftVersion = version;
3956
4081
  }
3957
- if (isDraft) {
3958
- const publishedVersion = otherDocumentStatuses?.find((d) => d.publishedAt !== null);
3959
- if (!publishedVersion) {
3960
- return CONTENT_MANAGER_STATUS.DRAFT;
3961
- }
4082
+ const otherVersion = otherDocumentStatuses?.at(0);
4083
+ if (otherVersion?.publishedAt) {
4084
+ publishedVersion = otherVersion;
4085
+ } else if (otherVersion) {
4086
+ draftVersion = otherVersion;
3962
4087
  }
3963
- if (areDatesEqual(version.updatedAt, otherDocumentStatuses.at(0)?.updatedAt, 500)) {
4088
+ if (!draftVersion)
3964
4089
  return CONTENT_MANAGER_STATUS.PUBLISHED;
3965
- }
3966
- return CONTENT_MANAGER_STATUS.MODIFIED;
4090
+ if (!publishedVersion)
4091
+ return CONTENT_MANAGER_STATUS.DRAFT;
4092
+ const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
4093
+ return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
3967
4094
  },
4095
+ // TODO is it necessary to return metadata on every page of the CM
4096
+ // We could refactor this so the locales are only loaded when they're
4097
+ // needed. e.g. in the bulk locale action modal.
3968
4098
  async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
4099
+ const populate = getValidatableFieldsPopulate(uid2);
3969
4100
  const versions = await strapi2.db.query(uid2).findMany({
3970
4101
  where: { documentId: version.documentId },
3971
- select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
3972
4102
  populate: {
4103
+ // Populate only fields that require validation for bulk locale actions
4104
+ ...populate,
4105
+ // NOTE: creator fields are selected in this way to avoid exposing sensitive data
3973
4106
  createdBy: {
3974
4107
  select: ["id", "firstname", "lastname", "email"]
3975
4108
  },
@@ -3978,7 +4111,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3978
4111
  }
3979
4112
  }
3980
4113
  });
3981
- const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
4114
+ const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions, Object.keys(populate)) : [];
3982
4115
  const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
3983
4116
  return {
3984
4117
  availableLocales: availableLocalesResult,
@@ -3991,8 +4124,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3991
4124
  * - Available status of the document for the current locale
3992
4125
  */
3993
4126
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
3994
- if (!document)
4127
+ if (!document) {
3995
4128
  return document;
4129
+ }
3996
4130
  const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
3997
4131
  if (!hasDraftAndPublish) {
3998
4132
  opts.availableStatus = false;
@@ -4042,26 +4176,9 @@ const sumDraftCounts = (entity, uid2) => {
4042
4176
  }, 0);
4043
4177
  };
4044
4178
  const { ApplicationError } = strapiUtils.errors;
4045
- const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
4046
4179
  const { PUBLISHED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
4047
4180
  const omitPublishedAtField = fp.omit(PUBLISHED_AT_ATTRIBUTE);
4048
4181
  const omitIdField = fp.omit("id");
4049
- const emitEvent = async (uid2, event, document) => {
4050
- const modelDef = strapi.getModel(uid2);
4051
- const sanitizedDocument = await strapiUtils.sanitize.sanitizers.defaultSanitizeOutput(
4052
- {
4053
- schema: modelDef,
4054
- getModel(uid22) {
4055
- return strapi.getModel(uid22);
4056
- }
4057
- },
4058
- document
4059
- );
4060
- strapi.eventHub.emit(event, {
4061
- model: modelDef.modelName,
4062
- entry: sanitizedDocument
4063
- });
4064
- };
4065
4182
  const documentManager = ({ strapi: strapi2 }) => {
4066
4183
  return {
4067
4184
  async findOne(id, uid2, opts = {}) {
@@ -4080,6 +4197,9 @@ const documentManager = ({ strapi: strapi2 }) => {
4080
4197
  } else if (opts.locale && opts.locale !== "*") {
4081
4198
  where.locale = opts.locale;
4082
4199
  }
4200
+ if (typeof opts.isPublished === "boolean") {
4201
+ where.publishedAt = { $notNull: opts.isPublished };
4202
+ }
4083
4203
  return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
4084
4204
  },
4085
4205
  async findMany(opts, uid2) {
@@ -4142,70 +4262,36 @@ const documentManager = ({ strapi: strapi2 }) => {
4142
4262
  return {};
4143
4263
  },
4144
4264
  // FIXME: handle relations
4145
- async deleteMany(opts, uid2) {
4146
- const docs = await strapi2.documents(uid2).findMany(opts);
4147
- for (const doc of docs) {
4148
- await strapi2.documents(uid2).delete({ documentId: doc.documentId });
4149
- }
4150
- return { count: docs.length };
4265
+ async deleteMany(documentIds, uid2, opts = {}) {
4266
+ const deletedEntries = await strapi2.db.transaction(async () => {
4267
+ return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
4268
+ });
4269
+ return { count: deletedEntries.length };
4151
4270
  },
4152
4271
  async publish(id, uid2, opts = {}) {
4153
4272
  const populate = await buildDeepPopulate(uid2);
4154
4273
  const params = { ...opts, populate };
4155
- return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries.at(0));
4274
+ return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
4156
4275
  },
4157
- async publishMany(entities, uid2) {
4158
- if (!entities.length) {
4159
- return null;
4160
- }
4161
- await Promise.all(
4162
- entities.map((document) => {
4163
- return strapi2.entityValidator.validateEntityCreation(
4164
- strapi2.getModel(uid2),
4165
- document,
4166
- void 0,
4167
- // @ts-expect-error - FIXME: entity here is unnecessary
4168
- document
4169
- );
4170
- })
4171
- );
4172
- const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
4173
- const filters = { id: { $in: entitiesToPublish } };
4174
- const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
4175
- const populate = await buildDeepPopulate(uid2);
4176
- const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
4177
- where: filters,
4178
- data
4179
- });
4180
- const publishedEntities = await strapi2.db.query(uid2).findMany({
4181
- where: filters,
4182
- populate
4276
+ async publishMany(uid2, documentIds, locale) {
4277
+ return strapi2.db.transaction(async () => {
4278
+ const results = await Promise.all(
4279
+ documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
4280
+ );
4281
+ const publishedEntitiesCount = results.flat().filter(Boolean).length;
4282
+ return publishedEntitiesCount;
4183
4283
  });
4184
- await Promise.all(
4185
- publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
4186
- );
4187
- return publishedEntitiesCount;
4188
4284
  },
4189
- async unpublishMany(documents, uid2) {
4190
- if (!documents.length) {
4191
- return null;
4192
- }
4193
- const entitiesToUnpublish = documents.filter((doc) => doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
4194
- const filters = { id: { $in: entitiesToUnpublish } };
4195
- const data = { [PUBLISHED_AT_ATTRIBUTE]: null };
4196
- const populate = await buildDeepPopulate(uid2);
4197
- const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
4198
- where: filters,
4199
- data
4200
- });
4201
- const unpublishedEntities = await strapi2.db.query(uid2).findMany({
4202
- where: filters,
4203
- populate
4285
+ async unpublishMany(documentIds, uid2, opts = {}) {
4286
+ const unpublishedEntries = await strapi2.db.transaction(async () => {
4287
+ return Promise.all(
4288
+ documentIds.map(
4289
+ (id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
4290
+ )
4291
+ );
4204
4292
  });
4205
- await Promise.all(
4206
- unpublishedEntities.map((doc) => emitEvent(uid2, ENTRY_UNPUBLISH, doc))
4207
- );
4208
- return unpublishedEntitiesCount;
4293
+ const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
4294
+ return { count: unpublishedEntitiesCount };
4209
4295
  },
4210
4296
  async unpublish(id, uid2, opts = {}) {
4211
4297
  const populate = await buildDeepPopulate(uid2);
@@ -4230,16 +4316,20 @@ const documentManager = ({ strapi: strapi2 }) => {
4230
4316
  }
4231
4317
  return sumDraftCounts(document, uid2);
4232
4318
  },
4233
- async countManyEntriesDraftRelations(ids, uid2, locale) {
4319
+ async countManyEntriesDraftRelations(documentIds, uid2, locale) {
4234
4320
  const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
4235
4321
  if (!hasRelations) {
4236
4322
  return 0;
4237
4323
  }
4324
+ let localeFilter = {};
4325
+ if (locale) {
4326
+ localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
4327
+ }
4238
4328
  const entities = await strapi2.db.query(uid2).findMany({
4239
4329
  populate,
4240
4330
  where: {
4241
- id: { $in: ids },
4242
- ...locale ? { locale } : {}
4331
+ documentId: { $in: documentIds },
4332
+ ...localeFilter
4243
4333
  }
4244
4334
  });
4245
4335
  const totalNumberDraftRelations = entities.reduce(