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

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 (165) 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-BPvzFjM7.mjs → ComponentConfigurationPage-CuWgXugY.mjs} +3 -3
  6. package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs.map → ComponentConfigurationPage-CuWgXugY.mjs.map} +1 -1
  7. package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js → ComponentConfigurationPage-by0e_kNd.js} +3 -3
  8. package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js.map → ComponentConfigurationPage-by0e_kNd.js.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-Dmv83RlS.js → EditConfigurationPage-CqBeCPGH.js} +3 -3
  14. package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js.map → EditConfigurationPage-CqBeCPGH.js.map} +1 -1
  15. package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs → EditConfigurationPage-DbI4KMyz.mjs} +3 -3
  16. package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs.map → EditConfigurationPage-DbI4KMyz.mjs.map} +1 -1
  17. package/dist/_chunks/{EditViewPage-DvNpQkam.js → EditViewPage-ChgloMyO.js} +7 -9
  18. package/dist/_chunks/EditViewPage-ChgloMyO.js.map +1 -0
  19. package/dist/_chunks/{EditViewPage-DDS6H9HO.mjs → EditViewPage-dFPBya9U.mjs} +6 -6
  20. package/dist/_chunks/EditViewPage-dFPBya9U.mjs.map +1 -0
  21. package/dist/_chunks/{Field-6gvGdPBV.mjs → Field-C1nUKcdS.mjs} +500 -608
  22. package/dist/_chunks/Field-C1nUKcdS.mjs.map +1 -0
  23. package/dist/_chunks/{Field-DmVKIAOo.js → Field-dLk-vgLL.js} +552 -661
  24. package/dist/_chunks/Field-dLk-vgLL.js.map +1 -0
  25. package/dist/_chunks/{Form-CPZC9vWa.js → Form-CbXtmHC_.js} +18 -16
  26. package/dist/_chunks/Form-CbXtmHC_.js.map +1 -0
  27. package/dist/_chunks/{Form-DW6K1IH-.mjs → Form-DOlpi7Js.mjs} +16 -13
  28. package/dist/_chunks/Form-DOlpi7Js.mjs.map +1 -0
  29. package/dist/_chunks/{History-Dmr9fmUA.mjs → History-BFNUAiGc.mjs} +29 -40
  30. package/dist/_chunks/History-BFNUAiGc.mjs.map +1 -0
  31. package/dist/_chunks/{History-DeAPlvtv.js → History-BjDfohBr.js} +30 -42
  32. package/dist/_chunks/History-BjDfohBr.js.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-DhwvYcNv.mjs → ListConfigurationPage-DDi0KqFm.mjs} +9 -9
  34. package/dist/_chunks/ListConfigurationPage-DDi0KqFm.mjs.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-DPCwW5Vr.js → ListConfigurationPage-IQBgWTaa.js} +14 -16
  36. package/dist/_chunks/ListConfigurationPage-IQBgWTaa.js.map +1 -0
  37. package/dist/_chunks/{ListViewPage-BtAwuYLE.mjs → ListViewPage-BPjljUsH.mjs} +21 -41
  38. package/dist/_chunks/ListViewPage-BPjljUsH.mjs.map +1 -0
  39. package/dist/_chunks/{ListViewPage-5ySZ-VUs.js → ListViewPage-CZYGqlvF.js} +28 -48
  40. package/dist/_chunks/ListViewPage-CZYGqlvF.js.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-DOC_yWOf.js → NoContentTypePage-BOAI6VZ1.js} +3 -3
  42. package/dist/_chunks/NoContentTypePage-BOAI6VZ1.js.map +1 -0
  43. package/dist/_chunks/{NoContentTypePage-DSPxnxxp.mjs → NoContentTypePage-DaWw67K-.mjs} +3 -3
  44. package/dist/_chunks/NoContentTypePage-DaWw67K-.mjs.map +1 -0
  45. package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs → NoPermissionsPage-CZrJH00p.mjs} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs.map → NoPermissionsPage-CZrJH00p.mjs.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js → NoPermissionsPage-cYEtLc_e.js} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js.map → NoPermissionsPage-cYEtLc_e.js.map} +1 -1
  49. package/dist/_chunks/{Relations-J8cscLlR.mjs → Relations-DTowyge2.mjs} +66 -56
  50. package/dist/_chunks/Relations-DTowyge2.mjs.map +1 -0
  51. package/dist/_chunks/{Relations-CgWtgnPe.js → Relations-DU6B7irU.js} +70 -61
  52. package/dist/_chunks/Relations-DU6B7irU.js.map +1 -0
  53. package/dist/_chunks/{en-C-V1_90f.js → en-DTULi5-d.js} +3 -1
  54. package/dist/_chunks/{en-C-V1_90f.js.map → en-DTULi5-d.js.map} +1 -1
  55. package/dist/_chunks/{en-MBPul9Su.mjs → en-GCOTL6jR.mjs} +3 -1
  56. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-GCOTL6jR.mjs.map} +1 -1
  57. package/dist/_chunks/{index-CwRRo1V9.mjs → index-BaGHmIir.mjs} +507 -202
  58. package/dist/_chunks/index-BaGHmIir.mjs.map +1 -0
  59. package/dist/_chunks/{index-C6AH2hEl.js → index-CCJeB7Rw.js} +502 -198
  60. package/dist/_chunks/index-CCJeB7Rw.js.map +1 -0
  61. package/dist/_chunks/{layout-jIDzX0Fp.mjs → layout-BinjszSQ.mjs} +10 -10
  62. package/dist/_chunks/layout-BinjszSQ.mjs.map +1 -0
  63. package/dist/_chunks/{layout-B_SXLhqf.js → layout-ni_L9kT1.js} +12 -14
  64. package/dist/_chunks/layout-ni_L9kT1.js.map +1 -0
  65. package/dist/_chunks/{relations-iBMa_OFG.js → relations-CeJAJc5I.js} +2 -2
  66. package/dist/_chunks/{relations-iBMa_OFG.js.map → relations-CeJAJc5I.js.map} +1 -1
  67. package/dist/_chunks/{relations-CuvIgCqI.mjs → relations-c91ji5eR.mjs} +2 -2
  68. package/dist/_chunks/{relations-CuvIgCqI.mjs.map → relations-c91ji5eR.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/services/historyVersion.d.ts +1 -1
  82. package/dist/admin/src/hooks/useDocument.d.ts +5 -8
  83. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  84. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  85. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  86. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  87. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +3 -1
  88. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  89. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  90. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  91. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  92. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +10 -18
  93. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  95. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  96. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +67 -52
  97. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  98. package/dist/admin/src/services/api.d.ts +2 -3
  99. package/dist/admin/src/services/components.d.ts +2 -2
  100. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  101. package/dist/admin/src/services/documents.d.ts +29 -17
  102. package/dist/admin/src/services/init.d.ts +2 -2
  103. package/dist/admin/src/services/relations.d.ts +3 -3
  104. package/dist/admin/src/services/uid.d.ts +3 -3
  105. package/dist/admin/src/utils/api.d.ts +4 -18
  106. package/dist/admin/src/utils/validation.d.ts +1 -6
  107. package/dist/server/index.js +273 -196
  108. package/dist/server/index.js.map +1 -1
  109. package/dist/server/index.mjs +281 -204
  110. package/dist/server/index.mjs.map +1 -1
  111. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  112. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  113. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  114. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  115. package/dist/server/src/controllers/validation/dimensions.d.ts +9 -0
  116. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  117. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  118. package/dist/server/src/history/services/history.d.ts.map +1 -1
  119. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  120. package/dist/server/src/index.d.ts +18 -39
  121. package/dist/server/src/index.d.ts.map +1 -1
  122. package/dist/server/src/services/document-manager.d.ts +13 -12
  123. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  124. package/dist/server/src/services/document-metadata.d.ts +8 -29
  125. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  126. package/dist/server/src/services/index.d.ts +18 -39
  127. package/dist/server/src/services/index.d.ts.map +1 -1
  128. package/dist/server/src/services/utils/populate.d.ts +8 -1
  129. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  130. package/dist/shared/contracts/collection-types.d.ts +14 -6
  131. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  132. package/dist/shared/contracts/relations.d.ts +2 -2
  133. package/dist/shared/contracts/relations.d.ts.map +1 -1
  134. package/package.json +13 -14
  135. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  136. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  137. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  138. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  139. package/dist/_chunks/EditViewPage-DDS6H9HO.mjs.map +0 -1
  140. package/dist/_chunks/EditViewPage-DvNpQkam.js.map +0 -1
  141. package/dist/_chunks/Field-6gvGdPBV.mjs.map +0 -1
  142. package/dist/_chunks/Field-DmVKIAOo.js.map +0 -1
  143. package/dist/_chunks/Form-CPZC9vWa.js.map +0 -1
  144. package/dist/_chunks/Form-DW6K1IH-.mjs.map +0 -1
  145. package/dist/_chunks/History-DeAPlvtv.js.map +0 -1
  146. package/dist/_chunks/History-Dmr9fmUA.mjs.map +0 -1
  147. package/dist/_chunks/ListConfigurationPage-DPCwW5Vr.js.map +0 -1
  148. package/dist/_chunks/ListConfigurationPage-DhwvYcNv.mjs.map +0 -1
  149. package/dist/_chunks/ListViewPage-5ySZ-VUs.js.map +0 -1
  150. package/dist/_chunks/ListViewPage-BtAwuYLE.mjs.map +0 -1
  151. package/dist/_chunks/NoContentTypePage-DOC_yWOf.js.map +0 -1
  152. package/dist/_chunks/NoContentTypePage-DSPxnxxp.mjs.map +0 -1
  153. package/dist/_chunks/Relations-CgWtgnPe.js.map +0 -1
  154. package/dist/_chunks/Relations-J8cscLlR.mjs.map +0 -1
  155. package/dist/_chunks/index-C6AH2hEl.js.map +0 -1
  156. package/dist/_chunks/index-CwRRo1V9.mjs.map +0 -1
  157. package/dist/_chunks/layout-B_SXLhqf.js.map +0 -1
  158. package/dist/_chunks/layout-jIDzX0Fp.mjs.map +0 -1
  159. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  160. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  161. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  162. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  163. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +0 -31
  164. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  165. 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) {
@@ -309,7 +309,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
309
309
  },
310
310
  async findVersionsPage(params) {
311
311
  const locale = params.query.locale || await serviceUtils.getDefaultLocale();
312
- const [{ results, pagination }, localeDictionary] = await Promise.all([
312
+ const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
313
313
  query.findPage({
314
314
  ...params.query,
315
315
  where: {
@@ -408,7 +408,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
408
408
  );
409
409
  return {
410
410
  results: formattedResults,
411
- pagination
411
+ pagination: pagination2
412
412
  };
413
413
  },
414
414
  async restoreVersion(versionId) {
@@ -492,6 +492,12 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
492
492
  const documentContext = context.action === "create" ? { documentId: result.documentId, locale: context.params?.locale } : { documentId: context.params.documentId, locale: context.params?.locale };
493
493
  const defaultLocale = await serviceUtils.getDefaultLocale();
494
494
  const locale = documentContext.locale || defaultLocale;
495
+ if (Array.isArray(locale)) {
496
+ strapi2.log.warn(
497
+ "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
498
+ );
499
+ return next();
500
+ }
495
501
  const document = await strapi2.documents(contentTypeUid).findOne({
496
502
  documentId: documentContext.documentId,
497
503
  locale,
@@ -1452,7 +1458,7 @@ const { PaginationError, ValidationError } = errors;
1452
1458
  const TYPES = ["singleType", "collectionType"];
1453
1459
  const kindSchema = yup$1.string().oneOf(TYPES).nullable();
1454
1460
  const bulkActionInputSchema = yup$1.object({
1455
- ids: yup$1.array().of(yup$1.strapiID()).min(1).required()
1461
+ documentIds: yup$1.array().of(yup$1.strapiID()).min(1).required()
1456
1462
  }).required();
1457
1463
  const generateUIDInputSchema = yup$1.object({
1458
1464
  contentTypeUID: yup$1.string().required(),
@@ -1551,15 +1557,47 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
1551
1557
  }
1552
1558
  }, body);
1553
1559
  };
1554
- const getDocumentLocaleAndStatus = (request) => {
1560
+ const singleLocaleSchema = yup$1.string().nullable();
1561
+ const multipleLocaleSchema = yup$1.lazy(
1562
+ (value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
1563
+ );
1564
+ const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
1565
+ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
1566
+ const { allowMultipleLocales } = opts;
1555
1567
  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}`);
1568
+ const schema = yup$1.object().shape({
1569
+ locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
1570
+ status: statusSchema
1571
+ });
1572
+ try {
1573
+ await validateYupSchema(schema, { strict: true, abortEarly: false })(request);
1574
+ return { locale, status, ...rest };
1575
+ } catch (error) {
1576
+ throw new errors.ValidationError(`Validation error: ${error.message}`);
1561
1577
  }
1562
- return { locale, status, ...rest };
1578
+ };
1579
+ const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
1580
+ const documentMetadata2 = getService$1("document-metadata");
1581
+ const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
1582
+ let {
1583
+ meta: { availableLocales, availableStatus }
1584
+ } = serviceOutput;
1585
+ const metadataSanitizer = permissionChecker2.sanitizeOutput;
1586
+ availableLocales = await async.map(
1587
+ availableLocales,
1588
+ async (localeDocument) => metadataSanitizer(localeDocument)
1589
+ );
1590
+ availableStatus = await async.map(
1591
+ availableStatus,
1592
+ async (statusDocument) => metadataSanitizer(statusDocument)
1593
+ );
1594
+ return {
1595
+ ...serviceOutput,
1596
+ meta: {
1597
+ availableLocales,
1598
+ availableStatus
1599
+ }
1600
+ };
1563
1601
  };
1564
1602
  const createDocument = async (ctx, opts) => {
1565
1603
  const { userAbility, user } = ctx.state;
@@ -1574,7 +1612,7 @@ const createDocument = async (ctx, opts) => {
1574
1612
  const setCreator = setCreatorFields({ user });
1575
1613
  const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
1576
1614
  const sanitizedBody = await sanitizeFn(body);
1577
- const { locale, status = "draft" } = getDocumentLocaleAndStatus(body);
1615
+ const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
1578
1616
  return documentManager2.create(model, {
1579
1617
  data: sanitizedBody,
1580
1618
  locale,
@@ -1593,7 +1631,7 @@ const updateDocument = async (ctx, opts) => {
1593
1631
  }
1594
1632
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1595
1633
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1596
- const { locale } = getDocumentLocaleAndStatus(body);
1634
+ const { locale } = await getDocumentLocaleAndStatus(body);
1597
1635
  const [documentVersion, documentExists] = await Promise.all([
1598
1636
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1599
1637
  documentManager2.exists(model, id)
@@ -1631,8 +1669,8 @@ const collectionTypes = {
1631
1669
  }
1632
1670
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1633
1671
  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(
1672
+ const { locale, status } = await getDocumentLocaleAndStatus(query);
1673
+ const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
1636
1674
  { ...permissionQuery, populate, locale, status },
1637
1675
  model
1638
1676
  );
@@ -1653,21 +1691,20 @@ const collectionTypes = {
1653
1691
  );
1654
1692
  ctx.body = {
1655
1693
  results,
1656
- pagination
1694
+ pagination: pagination2
1657
1695
  };
1658
1696
  },
1659
1697
  async findOne(ctx) {
1660
1698
  const { userAbility } = ctx.state;
1661
1699
  const { model, id } = ctx.params;
1662
1700
  const documentManager2 = getService$1("document-manager");
1663
- const documentMetadata2 = getService$1("document-metadata");
1664
1701
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1665
1702
  if (permissionChecker2.cannot.read()) {
1666
1703
  return ctx.forbidden();
1667
1704
  }
1668
1705
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1669
1706
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1670
- const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
1707
+ const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
1671
1708
  const version = await documentManager2.findOne(id, model, {
1672
1709
  populate,
1673
1710
  locale,
@@ -1678,8 +1715,10 @@ const collectionTypes = {
1678
1715
  if (!exists) {
1679
1716
  return ctx.notFound();
1680
1717
  }
1681
- const { meta } = await documentMetadata2.formatDocumentWithMetadata(
1718
+ const { meta } = await formatDocumentWithMetadata(
1719
+ permissionChecker2,
1682
1720
  model,
1721
+ // @ts-expect-error TODO: fix
1683
1722
  { id, locale, publishedAt: null },
1684
1723
  { availableLocales: true, availableStatus: false }
1685
1724
  );
@@ -1690,12 +1729,11 @@ const collectionTypes = {
1690
1729
  return ctx.forbidden();
1691
1730
  }
1692
1731
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
1693
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
1732
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
1694
1733
  },
1695
1734
  async create(ctx) {
1696
1735
  const { userAbility } = ctx.state;
1697
1736
  const { model } = ctx.params;
1698
- const documentMetadata2 = getService$1("document-metadata");
1699
1737
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1700
1738
  const [totalEntries, document] = await Promise.all([
1701
1739
  strapi.db.query(model).count(),
@@ -1703,7 +1741,7 @@ const collectionTypes = {
1703
1741
  ]);
1704
1742
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
1705
1743
  ctx.status = 201;
1706
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument, {
1744
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
1707
1745
  // Empty metadata as it's not relevant for a new document
1708
1746
  availableLocales: false,
1709
1747
  availableStatus: false
@@ -1717,25 +1755,23 @@ const collectionTypes = {
1717
1755
  async update(ctx) {
1718
1756
  const { userAbility } = ctx.state;
1719
1757
  const { model } = ctx.params;
1720
- const documentMetadata2 = getService$1("document-metadata");
1721
1758
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1722
1759
  const updatedVersion = await updateDocument(ctx);
1723
1760
  const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
1724
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedVersion);
1761
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
1725
1762
  },
1726
1763
  async clone(ctx) {
1727
1764
  const { userAbility, user } = ctx.state;
1728
1765
  const { model, sourceId: id } = ctx.params;
1729
1766
  const { body } = ctx.request;
1730
1767
  const documentManager2 = getService$1("document-manager");
1731
- const documentMetadata2 = getService$1("document-metadata");
1732
1768
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1733
1769
  if (permissionChecker2.cannot.create()) {
1734
1770
  return ctx.forbidden();
1735
1771
  }
1736
1772
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1737
1773
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1738
- const { locale } = getDocumentLocaleAndStatus(body);
1774
+ const { locale } = await getDocumentLocaleAndStatus(body);
1739
1775
  const document = await documentManager2.findOne(id, model, {
1740
1776
  populate,
1741
1777
  locale,
@@ -1751,7 +1787,7 @@ const collectionTypes = {
1751
1787
  const sanitizedBody = await sanitizeFn(body);
1752
1788
  const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
1753
1789
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
1754
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument, {
1790
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
1755
1791
  // Empty metadata as it's not relevant for a new document
1756
1792
  availableLocales: false,
1757
1793
  availableStatus: false
@@ -1780,7 +1816,7 @@ const collectionTypes = {
1780
1816
  }
1781
1817
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1782
1818
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1783
- const { locale } = getDocumentLocaleAndStatus(ctx.query);
1819
+ const { locale } = await getDocumentLocaleAndStatus(ctx.query);
1784
1820
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1785
1821
  if (documentLocales.length === 0) {
1786
1822
  return ctx.notFound();
@@ -1802,7 +1838,6 @@ const collectionTypes = {
1802
1838
  const { id, model } = ctx.params;
1803
1839
  const { body } = ctx.request;
1804
1840
  const documentManager2 = getService$1("document-manager");
1805
- const documentMetadata2 = getService$1("document-metadata");
1806
1841
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1807
1842
  if (permissionChecker2.cannot.publish()) {
1808
1843
  return ctx.forbidden();
@@ -1814,21 +1849,25 @@ const collectionTypes = {
1814
1849
  if (permissionChecker2.cannot.publish(document)) {
1815
1850
  throw new errors.ForbiddenError();
1816
1851
  }
1817
- const { locale } = getDocumentLocaleAndStatus(body);
1818
- return documentManager2.publish(document.documentId, model, {
1852
+ const { locale } = await getDocumentLocaleAndStatus(body);
1853
+ const publishResult = await documentManager2.publish(document.documentId, model, {
1819
1854
  locale
1820
1855
  // TODO: Allow setting creator fields on publish
1821
1856
  // data: setCreatorFields({ user, isEdition: true })({}),
1822
1857
  });
1858
+ if (!publishResult || publishResult.length === 0) {
1859
+ throw new errors.NotFoundError("Document not found or already published.");
1860
+ }
1861
+ return publishResult[0];
1823
1862
  });
1824
1863
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
1825
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
1864
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
1826
1865
  },
1827
1866
  async bulkPublish(ctx) {
1828
1867
  const { userAbility } = ctx.state;
1829
1868
  const { model } = ctx.params;
1830
1869
  const { body } = ctx.request;
1831
- const { ids } = body;
1870
+ const { documentIds } = body;
1832
1871
  await validateBulkActionInput(body);
1833
1872
  const documentManager2 = getService$1("document-manager");
1834
1873
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
@@ -1837,8 +1876,11 @@ const collectionTypes = {
1837
1876
  }
1838
1877
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1839
1878
  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);
1879
+ const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
1880
+ const entityPromises = documentIds.map(
1881
+ (documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
1882
+ );
1883
+ const entities = (await Promise.all(entityPromises)).flat();
1842
1884
  for (const entity of entities) {
1843
1885
  if (!entity) {
1844
1886
  return ctx.notFound();
@@ -1847,24 +1889,25 @@ const collectionTypes = {
1847
1889
  return ctx.forbidden();
1848
1890
  }
1849
1891
  }
1850
- const { count } = await documentManager2.publishMany(entities, model);
1892
+ const count = await documentManager2.publishMany(model, documentIds, locale);
1851
1893
  ctx.body = { count };
1852
1894
  },
1853
1895
  async bulkUnpublish(ctx) {
1854
1896
  const { userAbility } = ctx.state;
1855
1897
  const { model } = ctx.params;
1856
1898
  const { body } = ctx.request;
1857
- const { ids } = body;
1899
+ const { documentIds } = body;
1858
1900
  await validateBulkActionInput(body);
1859
1901
  const documentManager2 = getService$1("document-manager");
1860
1902
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1861
1903
  if (permissionChecker2.cannot.unpublish()) {
1862
1904
  return ctx.forbidden();
1863
1905
  }
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);
1906
+ const { locale } = await getDocumentLocaleAndStatus(body);
1907
+ const entityPromises = documentIds.map(
1908
+ (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1909
+ );
1910
+ const entities = (await Promise.all(entityPromises)).flat();
1868
1911
  for (const entity of entities) {
1869
1912
  if (!entity) {
1870
1913
  return ctx.notFound();
@@ -1873,7 +1916,8 @@ const collectionTypes = {
1873
1916
  return ctx.forbidden();
1874
1917
  }
1875
1918
  }
1876
- const { count } = await documentManager2.unpublishMany(entities, model);
1919
+ const entitiesIds = entities.map((document) => document.documentId);
1920
+ const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
1877
1921
  ctx.body = { count };
1878
1922
  },
1879
1923
  async unpublish(ctx) {
@@ -1883,7 +1927,6 @@ const collectionTypes = {
1883
1927
  body: { discardDraft, ...body }
1884
1928
  } = ctx.request;
1885
1929
  const documentManager2 = getService$1("document-manager");
1886
- const documentMetadata2 = getService$1("document-metadata");
1887
1930
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1888
1931
  if (permissionChecker2.cannot.unpublish()) {
1889
1932
  return ctx.forbidden();
@@ -1893,7 +1936,7 @@ const collectionTypes = {
1893
1936
  }
1894
1937
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1895
1938
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1896
- const { locale } = getDocumentLocaleAndStatus(body);
1939
+ const { locale } = await getDocumentLocaleAndStatus(body);
1897
1940
  const document = await documentManager2.findOne(id, model, {
1898
1941
  populate,
1899
1942
  locale,
@@ -1915,7 +1958,7 @@ const collectionTypes = {
1915
1958
  ctx.body = await async.pipe(
1916
1959
  (document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
1917
1960
  permissionChecker2.sanitizeOutput,
1918
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
1961
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
1919
1962
  )(document);
1920
1963
  });
1921
1964
  },
@@ -1924,14 +1967,13 @@ const collectionTypes = {
1924
1967
  const { id, model } = ctx.params;
1925
1968
  const { body } = ctx.request;
1926
1969
  const documentManager2 = getService$1("document-manager");
1927
- const documentMetadata2 = getService$1("document-metadata");
1928
1970
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1929
1971
  if (permissionChecker2.cannot.discard()) {
1930
1972
  return ctx.forbidden();
1931
1973
  }
1932
1974
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
1933
1975
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1934
- const { locale } = getDocumentLocaleAndStatus(body);
1976
+ const { locale } = await getDocumentLocaleAndStatus(body);
1935
1977
  const document = await documentManager2.findOne(id, model, {
1936
1978
  populate,
1937
1979
  locale,
@@ -1946,14 +1988,14 @@ const collectionTypes = {
1946
1988
  ctx.body = await async.pipe(
1947
1989
  (document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
1948
1990
  permissionChecker2.sanitizeOutput,
1949
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
1991
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
1950
1992
  )(document);
1951
1993
  },
1952
1994
  async bulkDelete(ctx) {
1953
1995
  const { userAbility } = ctx.state;
1954
1996
  const { model } = ctx.params;
1955
1997
  const { query, body } = ctx.request;
1956
- const { ids } = body;
1998
+ const { documentIds } = body;
1957
1999
  await validateBulkActionInput(body);
1958
2000
  const documentManager2 = getService$1("document-manager");
1959
2001
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
@@ -1961,14 +2003,22 @@ const collectionTypes = {
1961
2003
  return ctx.forbidden();
1962
2004
  }
1963
2005
  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 || [])
2006
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2007
+ const { locale } = await getDocumentLocaleAndStatus(body);
2008
+ const documentLocales = await documentManager2.findLocales(documentIds, model, {
2009
+ populate,
2010
+ locale
2011
+ });
2012
+ if (documentLocales.length === 0) {
2013
+ return ctx.notFound();
2014
+ }
2015
+ for (const document of documentLocales) {
2016
+ if (permissionChecker2.cannot.delete(document)) {
2017
+ return ctx.forbidden();
1969
2018
  }
1970
- };
1971
- const { count } = await documentManager2.deleteMany(params, model);
2019
+ }
2020
+ const localeDocumentsIds = documentLocales.map((document) => document.documentId);
2021
+ const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
1972
2022
  ctx.body = { count };
1973
2023
  },
1974
2024
  async countDraftRelations(ctx) {
@@ -1981,7 +2031,7 @@ const collectionTypes = {
1981
2031
  }
1982
2032
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1983
2033
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1984
- const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
2034
+ const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
1985
2035
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
1986
2036
  if (!entity) {
1987
2037
  return ctx.notFound();
@@ -1996,7 +2046,7 @@ const collectionTypes = {
1996
2046
  },
1997
2047
  async countManyEntriesDraftRelations(ctx) {
1998
2048
  const { userAbility } = ctx.state;
1999
- const ids = ctx.request.query.ids;
2049
+ const ids = ctx.request.query.documentIds;
2000
2050
  const locale = ctx.request.query.locale;
2001
2051
  const { model } = ctx.params;
2002
2052
  const documentManager2 = getService$1("document-manager");
@@ -2007,7 +2057,7 @@ const collectionTypes = {
2007
2057
  const entities = await documentManager2.findMany(
2008
2058
  {
2009
2059
  filters: {
2010
- id: ids
2060
+ documentId: ids
2011
2061
  },
2012
2062
  locale
2013
2063
  },
@@ -2509,7 +2559,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
2509
2559
  throw new errors.ForbiddenError();
2510
2560
  }
2511
2561
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2512
- const { locale } = getDocumentLocaleAndStatus(body);
2562
+ const { locale } = await getDocumentLocaleAndStatus(body);
2513
2563
  const [documentVersion, otherDocumentVersion] = await Promise.all([
2514
2564
  findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2515
2565
  // Find the first document to check if it exists
@@ -2546,12 +2596,11 @@ const singleTypes = {
2546
2596
  const { model } = ctx.params;
2547
2597
  const { query = {} } = ctx.request;
2548
2598
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2549
- const documentMetadata2 = getService$1("document-metadata");
2550
2599
  if (permissionChecker2.cannot.read()) {
2551
2600
  return ctx.forbidden();
2552
2601
  }
2553
2602
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2554
- const { locale, status } = getDocumentLocaleAndStatus(query);
2603
+ const { locale, status } = await getDocumentLocaleAndStatus(query);
2555
2604
  const version = await findDocument(permissionQuery, model, { locale, status });
2556
2605
  if (!version) {
2557
2606
  if (permissionChecker2.cannot.create()) {
@@ -2561,8 +2610,10 @@ const singleTypes = {
2561
2610
  if (!document) {
2562
2611
  return ctx.notFound();
2563
2612
  }
2564
- const { meta } = await documentMetadata2.formatDocumentWithMetadata(
2613
+ const { meta } = await formatDocumentWithMetadata(
2614
+ permissionChecker2,
2565
2615
  model,
2616
+ // @ts-expect-error - fix types
2566
2617
  { id: document.documentId, locale, publishedAt: null },
2567
2618
  { availableLocales: true, availableStatus: false }
2568
2619
  );
@@ -2573,16 +2624,15 @@ const singleTypes = {
2573
2624
  return ctx.forbidden();
2574
2625
  }
2575
2626
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
2576
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2627
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
2577
2628
  },
2578
2629
  async createOrUpdate(ctx) {
2579
2630
  const { userAbility } = ctx.state;
2580
2631
  const { model } = ctx.params;
2581
- const documentMetadata2 = getService$1("document-metadata");
2582
2632
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2583
2633
  const document = await createOrUpdateDocument(ctx);
2584
2634
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
2585
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2635
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
2586
2636
  },
2587
2637
  async delete(ctx) {
2588
2638
  const { userAbility } = ctx.state;
@@ -2595,7 +2645,7 @@ const singleTypes = {
2595
2645
  }
2596
2646
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2597
2647
  const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2598
- const { locale } = getDocumentLocaleAndStatus(query);
2648
+ const { locale } = await getDocumentLocaleAndStatus(query);
2599
2649
  const documentLocales = await documentManager2.findLocales(void 0, model, {
2600
2650
  populate,
2601
2651
  locale
@@ -2618,7 +2668,6 @@ const singleTypes = {
2618
2668
  const { model } = ctx.params;
2619
2669
  const { query = {} } = ctx.request;
2620
2670
  const documentManager2 = getService$1("document-manager");
2621
- const documentMetadata2 = getService$1("document-metadata");
2622
2671
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2623
2672
  if (permissionChecker2.cannot.publish()) {
2624
2673
  return ctx.forbidden();
@@ -2633,11 +2682,12 @@ const singleTypes = {
2633
2682
  if (permissionChecker2.cannot.publish(document)) {
2634
2683
  throw new errors.ForbiddenError();
2635
2684
  }
2636
- const { locale } = getDocumentLocaleAndStatus(document);
2637
- return documentManager2.publish(document.documentId, model, { locale });
2685
+ const { locale } = await getDocumentLocaleAndStatus(document);
2686
+ const publishResult = await documentManager2.publish(document.documentId, model, { locale });
2687
+ return publishResult.at(0);
2638
2688
  });
2639
2689
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
2640
- ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2690
+ ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
2641
2691
  },
2642
2692
  async unpublish(ctx) {
2643
2693
  const { userAbility } = ctx.state;
@@ -2647,7 +2697,6 @@ const singleTypes = {
2647
2697
  query = {}
2648
2698
  } = ctx.request;
2649
2699
  const documentManager2 = getService$1("document-manager");
2650
- const documentMetadata2 = getService$1("document-metadata");
2651
2700
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2652
2701
  if (permissionChecker2.cannot.unpublish()) {
2653
2702
  return ctx.forbidden();
@@ -2656,7 +2705,7 @@ const singleTypes = {
2656
2705
  return ctx.forbidden();
2657
2706
  }
2658
2707
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2659
- const { locale } = getDocumentLocaleAndStatus(body);
2708
+ const { locale } = await getDocumentLocaleAndStatus(body);
2660
2709
  const document = await findDocument(sanitizedQuery, model, { locale });
2661
2710
  if (!document) {
2662
2711
  return ctx.notFound();
@@ -2674,7 +2723,7 @@ const singleTypes = {
2674
2723
  ctx.body = await async.pipe(
2675
2724
  (document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
2676
2725
  permissionChecker2.sanitizeOutput,
2677
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2726
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
2678
2727
  )(document);
2679
2728
  });
2680
2729
  },
@@ -2683,13 +2732,12 @@ const singleTypes = {
2683
2732
  const { model } = ctx.params;
2684
2733
  const { body, query = {} } = ctx.request;
2685
2734
  const documentManager2 = getService$1("document-manager");
2686
- const documentMetadata2 = getService$1("document-metadata");
2687
2735
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2688
2736
  if (permissionChecker2.cannot.discard()) {
2689
2737
  return ctx.forbidden();
2690
2738
  }
2691
2739
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2692
- const { locale } = getDocumentLocaleAndStatus(body);
2740
+ const { locale } = await getDocumentLocaleAndStatus(body);
2693
2741
  const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2694
2742
  if (!document) {
2695
2743
  return ctx.notFound();
@@ -2700,7 +2748,7 @@ const singleTypes = {
2700
2748
  ctx.body = await async.pipe(
2701
2749
  (document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
2702
2750
  permissionChecker2.sanitizeOutput,
2703
- (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2751
+ (document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
2704
2752
  )(document);
2705
2753
  },
2706
2754
  async countDraftRelations(ctx) {
@@ -2709,7 +2757,7 @@ const singleTypes = {
2709
2757
  const { query } = ctx.request;
2710
2758
  const documentManager2 = getService$1("document-manager");
2711
2759
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2712
- const { locale } = getDocumentLocaleAndStatus(query);
2760
+ const { locale } = await getDocumentLocaleAndStatus(query);
2713
2761
  if (permissionChecker2.cannot.read()) {
2714
2762
  return ctx.forbidden();
2715
2763
  }
@@ -2730,7 +2778,7 @@ const uid$1 = {
2730
2778
  async generateUID(ctx) {
2731
2779
  const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2732
2780
  const { query = {} } = ctx.request;
2733
- const { locale } = getDocumentLocaleAndStatus(query);
2781
+ const { locale } = await getDocumentLocaleAndStatus(query);
2734
2782
  await validateUIDField(contentTypeUID, field);
2735
2783
  const uidService = getService$1("uid");
2736
2784
  ctx.body = {
@@ -2742,7 +2790,7 @@ const uid$1 = {
2742
2790
  ctx.request.body
2743
2791
  );
2744
2792
  const { query = {} } = ctx.request;
2745
- const { locale } = getDocumentLocaleAndStatus(query);
2793
+ const { locale } = await getDocumentLocaleAndStatus(query);
2746
2794
  await validateUIDField(contentTypeUID, field);
2747
2795
  const uidService = getService$1("uid");
2748
2796
  const isAvailable = await uidService.checkUIDAvailability({
@@ -3533,7 +3581,7 @@ const permission = ({ strapi: strapi2 }) => ({
3533
3581
  await strapi2.service("admin::permission").actionProvider.registerMany(actions);
3534
3582
  }
3535
3583
  });
3536
- const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils.contentTypes;
3584
+ const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils.contentTypes;
3537
3585
  const { isAnyToMany } = strapiUtils.relations;
3538
3586
  const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils.contentTypes.constants;
3539
3587
  const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
@@ -3624,6 +3672,42 @@ const getDeepPopulate = (uid2, {
3624
3672
  {}
3625
3673
  );
3626
3674
  };
3675
+ const getValidatableFieldsPopulate = (uid2, {
3676
+ initialPopulate = {},
3677
+ countMany = false,
3678
+ countOne = false,
3679
+ maxLevel = Infinity
3680
+ } = {}, level = 1) => {
3681
+ if (level > maxLevel) {
3682
+ return {};
3683
+ }
3684
+ const model = strapi.getModel(uid2);
3685
+ return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
3686
+ if (!getDoesAttributeRequireValidation(attribute)) {
3687
+ return populateAcc;
3688
+ }
3689
+ if (isScalarAttribute(attribute)) {
3690
+ return merge(populateAcc, {
3691
+ [attributeName]: true
3692
+ });
3693
+ }
3694
+ return merge(
3695
+ populateAcc,
3696
+ getPopulateFor(
3697
+ attributeName,
3698
+ model,
3699
+ {
3700
+ // @ts-expect-error - improve types
3701
+ initialPopulate: initialPopulate?.[attributeName],
3702
+ countMany,
3703
+ countOne,
3704
+ maxLevel
3705
+ },
3706
+ level
3707
+ )
3708
+ );
3709
+ }, {});
3710
+ };
3627
3711
  const getDeepPopulateDraftCount = (uid2) => {
3628
3712
  const model = strapi.getModel(uid2);
3629
3713
  let hasRelations = false;
@@ -3852,41 +3936,70 @@ const AVAILABLE_STATUS_FIELDS = [
3852
3936
  "updatedBy",
3853
3937
  "status"
3854
3938
  ];
3855
- const AVAILABLE_LOCALES_FIELDS = ["id", "locale", "updatedAt", "createdAt", "status"];
3939
+ const AVAILABLE_LOCALES_FIELDS = [
3940
+ "id",
3941
+ "locale",
3942
+ "updatedAt",
3943
+ "createdAt",
3944
+ "status",
3945
+ "publishedAt",
3946
+ "documentId"
3947
+ ];
3856
3948
  const CONTENT_MANAGER_STATUS = {
3857
3949
  PUBLISHED: "published",
3858
3950
  DRAFT: "draft",
3859
3951
  MODIFIED: "modified"
3860
3952
  };
3861
- const areDatesEqual = (date1, date2, threshold) => {
3862
- if (!date1 || !date2) {
3953
+ const getIsVersionLatestModification = (version, otherVersion) => {
3954
+ if (!version || !version.updatedAt) {
3863
3955
  return false;
3864
3956
  }
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;
3957
+ const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
3958
+ const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
3959
+ return versionUpdatedAt > otherUpdatedAt;
3869
3960
  };
3870
3961
  const documentMetadata = ({ strapi: strapi2 }) => ({
3871
3962
  /**
3872
3963
  * Returns available locales of a document for the current status
3873
3964
  */
3874
- getAvailableLocales(uid2, version, allVersions) {
3965
+ async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
3875
3966
  const versionsByLocale = groupBy("locale", allVersions);
3876
3967
  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]);
3968
+ const model = strapi2.getModel(uid2);
3969
+ const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
3970
+ const traversalFunction = async (localeVersion) => traverseEntity(
3971
+ ({ key }, { remove }) => {
3972
+ if (keysToKeep.includes(key)) {
3973
+ return;
3974
+ }
3975
+ remove(key);
3976
+ },
3977
+ { schema: model, getModel: strapi2.getModel.bind(strapi2) },
3978
+ // @ts-expect-error fix types DocumentVersion incompatible with Data
3979
+ localeVersion
3980
+ );
3981
+ const mappingResult = await async.map(
3982
+ Object.values(versionsByLocale),
3983
+ async (localeVersions) => {
3984
+ const mappedLocaleVersions = await async.map(
3985
+ localeVersions,
3986
+ traversalFunction
3987
+ );
3988
+ if (!contentTypes$1.hasDraftAndPublish(model)) {
3989
+ return mappedLocaleVersions[0];
3990
+ }
3991
+ const draftVersion = mappedLocaleVersions.find((v) => v.publishedAt === null);
3992
+ const otherVersions = mappedLocaleVersions.filter((v) => v.id !== draftVersion?.id);
3993
+ if (!draftVersion) {
3994
+ return;
3995
+ }
3996
+ return {
3997
+ ...draftVersion,
3998
+ status: this.getStatus(draftVersion, otherVersions)
3999
+ };
3880
4000
  }
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);
4001
+ );
4002
+ return mappingResult.filter(Boolean);
3890
4003
  },
3891
4004
  /**
3892
4005
  * Returns available status of a document for the current locale
@@ -3924,26 +4037,37 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3924
4037
  });
3925
4038
  },
3926
4039
  getStatus(version, otherDocumentStatuses) {
3927
- const isDraft = version.publishedAt === null;
3928
- if (!otherDocumentStatuses?.length) {
3929
- return isDraft ? CONTENT_MANAGER_STATUS.DRAFT : CONTENT_MANAGER_STATUS.PUBLISHED;
4040
+ let draftVersion;
4041
+ let publishedVersion;
4042
+ if (version.publishedAt) {
4043
+ publishedVersion = version;
4044
+ } else {
4045
+ draftVersion = version;
3930
4046
  }
3931
- if (isDraft) {
3932
- const publishedVersion = otherDocumentStatuses?.find((d) => d.publishedAt !== null);
3933
- if (!publishedVersion) {
3934
- return CONTENT_MANAGER_STATUS.DRAFT;
3935
- }
4047
+ const otherVersion = otherDocumentStatuses?.at(0);
4048
+ if (otherVersion?.publishedAt) {
4049
+ publishedVersion = otherVersion;
4050
+ } else if (otherVersion) {
4051
+ draftVersion = otherVersion;
3936
4052
  }
3937
- if (areDatesEqual(version.updatedAt, otherDocumentStatuses.at(0)?.updatedAt, 500)) {
4053
+ if (!draftVersion)
3938
4054
  return CONTENT_MANAGER_STATUS.PUBLISHED;
3939
- }
3940
- return CONTENT_MANAGER_STATUS.MODIFIED;
4055
+ if (!publishedVersion)
4056
+ return CONTENT_MANAGER_STATUS.DRAFT;
4057
+ const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
4058
+ return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
3941
4059
  },
4060
+ // TODO is it necessary to return metadata on every page of the CM
4061
+ // We could refactor this so the locales are only loaded when they're
4062
+ // needed. e.g. in the bulk locale action modal.
3942
4063
  async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
4064
+ const populate = getValidatableFieldsPopulate(uid2);
3943
4065
  const versions = await strapi2.db.query(uid2).findMany({
3944
4066
  where: { documentId: version.documentId },
3945
- select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
3946
4067
  populate: {
4068
+ // Populate only fields that require validation for bulk locale actions
4069
+ ...populate,
4070
+ // NOTE: creator fields are selected in this way to avoid exposing sensitive data
3947
4071
  createdBy: {
3948
4072
  select: ["id", "firstname", "lastname", "email"]
3949
4073
  },
@@ -3952,7 +4076,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3952
4076
  }
3953
4077
  }
3954
4078
  });
3955
- const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
4079
+ const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions, Object.keys(populate)) : [];
3956
4080
  const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
3957
4081
  return {
3958
4082
  availableLocales: availableLocalesResult,
@@ -3965,8 +4089,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3965
4089
  * - Available status of the document for the current locale
3966
4090
  */
3967
4091
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
3968
- if (!document)
4092
+ if (!document) {
3969
4093
  return document;
4094
+ }
3970
4095
  const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
3971
4096
  if (!hasDraftAndPublish) {
3972
4097
  opts.availableStatus = false;
@@ -4016,26 +4141,9 @@ const sumDraftCounts = (entity, uid2) => {
4016
4141
  }, 0);
4017
4142
  };
4018
4143
  const { ApplicationError } = errors;
4019
- const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
4020
4144
  const { PUBLISHED_AT_ATTRIBUTE } = contentTypes$1.constants;
4021
4145
  const omitPublishedAtField = omit(PUBLISHED_AT_ATTRIBUTE);
4022
4146
  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
4147
  const documentManager = ({ strapi: strapi2 }) => {
4040
4148
  return {
4041
4149
  async findOne(id, uid2, opts = {}) {
@@ -4054,6 +4162,9 @@ const documentManager = ({ strapi: strapi2 }) => {
4054
4162
  } else if (opts.locale && opts.locale !== "*") {
4055
4163
  where.locale = opts.locale;
4056
4164
  }
4165
+ if (typeof opts.isPublished === "boolean") {
4166
+ where.publishedAt = { $notNull: opts.isPublished };
4167
+ }
4057
4168
  return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
4058
4169
  },
4059
4170
  async findMany(opts, uid2) {
@@ -4061,20 +4172,16 @@ const documentManager = ({ strapi: strapi2 }) => {
4061
4172
  return strapi2.documents(uid2).findMany(params);
4062
4173
  },
4063
4174
  async findPage(opts, uid2) {
4064
- const page = Number(opts?.page) || 1;
4065
- const pageSize = Number(opts?.pageSize) || 10;
4175
+ const params = pagination.withDefaultPagination(opts || {}, {
4176
+ maxLimit: 1e3
4177
+ });
4066
4178
  const [documents, total = 0] = await Promise.all([
4067
- strapi2.documents(uid2).findMany(opts),
4068
- strapi2.documents(uid2).count(opts)
4179
+ strapi2.documents(uid2).findMany(params),
4180
+ strapi2.documents(uid2).count(params)
4069
4181
  ]);
4070
4182
  return {
4071
4183
  results: documents,
4072
- pagination: {
4073
- page,
4074
- pageSize,
4075
- pageCount: Math.ceil(total / pageSize),
4076
- total
4077
- }
4184
+ pagination: pagination.transformPagedPaginationInfo(params, total)
4078
4185
  };
4079
4186
  },
4080
4187
  async create(uid2, opts = {}) {
@@ -4120,70 +4227,36 @@ const documentManager = ({ strapi: strapi2 }) => {
4120
4227
  return {};
4121
4228
  },
4122
4229
  // 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 };
4230
+ async deleteMany(documentIds, uid2, opts = {}) {
4231
+ const deletedEntries = await strapi2.db.transaction(async () => {
4232
+ return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
4233
+ });
4234
+ return { count: deletedEntries.length };
4129
4235
  },
4130
4236
  async publish(id, uid2, opts = {}) {
4131
4237
  const populate = await buildDeepPopulate(uid2);
4132
4238
  const params = { ...opts, populate };
4133
- return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries.at(0));
4239
+ return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
4134
4240
  },
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
4241
+ async publishMany(uid2, documentIds, locale) {
4242
+ return strapi2.db.transaction(async () => {
4243
+ const results = await Promise.all(
4244
+ documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
4245
+ );
4246
+ const publishedEntitiesCount = results.flat().filter(Boolean).length;
4247
+ return publishedEntitiesCount;
4161
4248
  });
4162
- await Promise.all(
4163
- publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
4164
- );
4165
- return publishedEntitiesCount;
4166
4249
  },
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
4250
+ async unpublishMany(documentIds, uid2, opts = {}) {
4251
+ const unpublishedEntries = await strapi2.db.transaction(async () => {
4252
+ return Promise.all(
4253
+ documentIds.map(
4254
+ (id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
4255
+ )
4256
+ );
4182
4257
  });
4183
- await Promise.all(
4184
- unpublishedEntities.map((doc) => emitEvent(uid2, ENTRY_UNPUBLISH, doc))
4185
- );
4186
- return unpublishedEntitiesCount;
4258
+ const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
4259
+ return { count: unpublishedEntitiesCount };
4187
4260
  },
4188
4261
  async unpublish(id, uid2, opts = {}) {
4189
4262
  const populate = await buildDeepPopulate(uid2);
@@ -4208,16 +4281,20 @@ const documentManager = ({ strapi: strapi2 }) => {
4208
4281
  }
4209
4282
  return sumDraftCounts(document, uid2);
4210
4283
  },
4211
- async countManyEntriesDraftRelations(ids, uid2, locale) {
4284
+ async countManyEntriesDraftRelations(documentIds, uid2, locale) {
4212
4285
  const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
4213
4286
  if (!hasRelations) {
4214
4287
  return 0;
4215
4288
  }
4289
+ let localeFilter = {};
4290
+ if (locale) {
4291
+ localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
4292
+ }
4216
4293
  const entities = await strapi2.db.query(uid2).findMany({
4217
4294
  populate,
4218
4295
  where: {
4219
- id: { $in: ids },
4220
- ...locale ? { locale } : {}
4296
+ documentId: { $in: documentIds },
4297
+ ...localeFilter
4221
4298
  }
4222
4299
  });
4223
4300
  const totalNumberDraftRelations = entities.reduce(