@strapi/content-manager 0.0.0-experimental.826f263c58b6886b849d3f03b81f7a530bc51c91 → 0.0.0-experimental.8c83c87960f2f5ddf95ae2f0acf849052f4a9ab4

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 (223) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
  3. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-CR5XdR33.mjs → ComponentConfigurationPage-BgCLcjXO.mjs} +4 -4
  5. package/dist/_chunks/{ComponentConfigurationPage-CR5XdR33.mjs.map → ComponentConfigurationPage-BgCLcjXO.mjs.map} +1 -1
  6. package/dist/_chunks/{ComponentConfigurationPage-DJcn1DrO.js → ComponentConfigurationPage-DywpTZeV.js} +5 -6
  7. package/dist/_chunks/{ComponentConfigurationPage-DJcn1DrO.js.map → ComponentConfigurationPage-DywpTZeV.js.map} +1 -1
  8. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
  9. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
  10. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
  11. package/dist/_chunks/{EditConfigurationPage-DmCIb4kD.mjs → EditConfigurationPage-BNjOAHNS.mjs} +4 -4
  12. package/dist/_chunks/{EditConfigurationPage-DmCIb4kD.mjs.map → EditConfigurationPage-BNjOAHNS.mjs.map} +1 -1
  13. package/dist/_chunks/{EditConfigurationPage-tDtWj7R2.js → EditConfigurationPage-CxRlP5if.js} +5 -6
  14. package/dist/_chunks/{EditConfigurationPage-tDtWj7R2.js.map → EditConfigurationPage-CxRlP5if.js.map} +1 -1
  15. package/dist/_chunks/{EditViewPage-CoQEnFlC.js → EditViewPage-BRewdTqE.js} +101 -51
  16. package/dist/_chunks/EditViewPage-BRewdTqE.js.map +1 -0
  17. package/dist/_chunks/{EditViewPage-DvaV7U9b.mjs → EditViewPage-CD_hqc1J.mjs} +102 -51
  18. package/dist/_chunks/EditViewPage-CD_hqc1J.mjs.map +1 -0
  19. package/dist/_chunks/{Field-Cz_J9551.mjs → Field-BPkQ-3Ku.mjs} +631 -279
  20. package/dist/_chunks/Field-BPkQ-3Ku.mjs.map +1 -0
  21. package/dist/_chunks/{Field-ZdrmmQ4Y.js → Field-DwvmENVf.js} +634 -283
  22. package/dist/_chunks/Field-DwvmENVf.js.map +1 -0
  23. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
  24. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
  25. package/dist/_chunks/{Form-Bpig5rch.js → Form-C_Gwv8P_.js} +55 -38
  26. package/dist/_chunks/Form-C_Gwv8P_.js.map +1 -0
  27. package/dist/_chunks/{Form-Dxmihyw8.mjs → Form-Czi0cf_2.mjs} +55 -37
  28. package/dist/_chunks/Form-Czi0cf_2.mjs.map +1 -0
  29. package/dist/_chunks/{History-BfX6XmZK.js → History-C1TKAig-.js} +175 -129
  30. package/dist/_chunks/History-C1TKAig-.js.map +1 -0
  31. package/dist/_chunks/{History-BZP8n7KT.mjs → History-CIQHyi4T.mjs} +176 -129
  32. package/dist/_chunks/History-CIQHyi4T.mjs.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-B3CXj8PY.js → ListConfigurationPage-D-NGRLYu.js} +62 -51
  34. package/dist/_chunks/ListConfigurationPage-D-NGRLYu.js.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-DxKuVkKz.mjs → ListConfigurationPage-DcZsfyEL.mjs} +63 -52
  36. package/dist/_chunks/ListConfigurationPage-DcZsfyEL.mjs.map +1 -0
  37. package/dist/_chunks/{ListViewPage-D5D3tVPq.mjs → ListViewPage-C10McTK1.mjs} +152 -128
  38. package/dist/_chunks/ListViewPage-C10McTK1.mjs.map +1 -0
  39. package/dist/_chunks/{ListViewPage-Bk9VO__I.js → ListViewPage-xv5IQoZp.js} +155 -132
  40. package/dist/_chunks/ListViewPage-xv5IQoZp.js.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-DnMeuQCj.mjs → NoContentTypePage-CPc0Cd3S.mjs} +2 -2
  42. package/dist/_chunks/{NoContentTypePage-DnMeuQCj.mjs.map → NoContentTypePage-CPc0Cd3S.mjs.map} +1 -1
  43. package/dist/_chunks/{NoContentTypePage-DsB2F7Z1.js → NoContentTypePage-Dzw5Yj5u.js} +2 -2
  44. package/dist/_chunks/{NoContentTypePage-DsB2F7Z1.js.map → NoContentTypePage-Dzw5Yj5u.js.map} +1 -1
  45. package/dist/_chunks/{NoPermissionsPage-BQDM64_b.js → NoPermissionsPage-DAe5CDCC.js} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-BQDM64_b.js.map → NoPermissionsPage-DAe5CDCC.js.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-OyoME_Tf.mjs → NoPermissionsPage-wfPBh2_0.mjs} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-OyoME_Tf.mjs.map → NoPermissionsPage-wfPBh2_0.mjs.map} +1 -1
  49. package/dist/_chunks/Preview-B7LyGT_b.js +290 -0
  50. package/dist/_chunks/Preview-B7LyGT_b.js.map +1 -0
  51. package/dist/_chunks/Preview-BVFFm7uB.mjs +272 -0
  52. package/dist/_chunks/Preview-BVFFm7uB.mjs.map +1 -0
  53. package/dist/_chunks/{Relations-B6B3A3mb.js → Relations-BmYR1AjY.js} +76 -43
  54. package/dist/_chunks/Relations-BmYR1AjY.js.map +1 -0
  55. package/dist/_chunks/{Relations-BOYZmuWy.mjs → Relations-JPhWxk-s.mjs} +76 -42
  56. package/dist/_chunks/Relations-JPhWxk-s.mjs.map +1 -0
  57. package/dist/_chunks/{en-BN1bvFK7.js → en-BK8Xyl5I.js} +35 -18
  58. package/dist/_chunks/{en-BN1bvFK7.js.map → en-BK8Xyl5I.js.map} +1 -1
  59. package/dist/_chunks/{en-Dzv55oQw.mjs → en-Dtk_ot79.mjs} +35 -18
  60. package/dist/_chunks/{en-Dzv55oQw.mjs.map → en-Dtk_ot79.mjs.map} +1 -1
  61. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  62. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  63. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  64. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  65. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
  66. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
  67. package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
  68. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
  69. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
  70. package/dist/_chunks/{index-DzN3kBgx.js → index-C2Q_PLWj.js} +1165 -880
  71. package/dist/_chunks/index-C2Q_PLWj.js.map +1 -0
  72. package/dist/_chunks/{index-VHviNMeW.mjs → index-DLIkNVnQ.mjs} +1185 -900
  73. package/dist/_chunks/index-DLIkNVnQ.mjs.map +1 -0
  74. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  75. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  76. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  77. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  78. package/dist/_chunks/{layout-b91XRlD2.js → layout-7AsWJzZJ.js} +41 -24
  79. package/dist/_chunks/layout-7AsWJzZJ.js.map +1 -0
  80. package/dist/_chunks/{layout-CPn1PM6x.mjs → layout-qE8qkNH_.mjs} +42 -24
  81. package/dist/_chunks/layout-qE8qkNH_.mjs.map +1 -0
  82. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  83. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  84. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  85. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  86. package/dist/_chunks/{relations-BsqxS6tR.mjs → relations-BjHH_1Am.mjs} +6 -7
  87. package/dist/_chunks/relations-BjHH_1Am.mjs.map +1 -0
  88. package/dist/_chunks/{relations-CA7IYmcP.js → relations-EifVzf_2.js} +6 -7
  89. package/dist/_chunks/relations-EifVzf_2.js.map +1 -0
  90. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  91. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  92. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  93. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  94. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
  95. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
  96. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
  97. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
  98. package/dist/admin/index.js +2 -1
  99. package/dist/admin/index.js.map +1 -1
  100. package/dist/admin/index.mjs +8 -7
  101. package/dist/admin/src/exports.d.ts +1 -1
  102. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  103. package/dist/admin/src/history/index.d.ts +3 -0
  104. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  105. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  106. package/dist/admin/src/index.d.ts +1 -0
  107. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  108. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +8 -3
  109. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
  110. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  111. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  112. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  113. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  114. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +6 -58
  115. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  116. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  117. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  118. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  119. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  120. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  121. package/dist/admin/src/preview/constants.d.ts +1 -0
  122. package/dist/admin/src/preview/index.d.ts +4 -0
  123. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  124. package/dist/admin/src/preview/routes.d.ts +3 -0
  125. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  126. package/dist/admin/src/router.d.ts +1 -1
  127. package/dist/admin/src/services/api.d.ts +1 -1
  128. package/dist/admin/src/services/components.d.ts +2 -2
  129. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  130. package/dist/admin/src/services/documents.d.ts +19 -20
  131. package/dist/admin/src/services/init.d.ts +1 -1
  132. package/dist/admin/src/services/relations.d.ts +2 -2
  133. package/dist/admin/src/services/uid.d.ts +3 -3
  134. package/dist/admin/src/utils/validation.d.ts +4 -1
  135. package/dist/server/index.js +616 -299
  136. package/dist/server/index.js.map +1 -1
  137. package/dist/server/index.mjs +616 -298
  138. package/dist/server/index.mjs.map +1 -1
  139. package/dist/server/src/bootstrap.d.ts.map +1 -1
  140. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  141. package/dist/server/src/controllers/index.d.ts.map +1 -1
  142. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  143. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  144. package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
  145. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  146. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  147. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  148. package/dist/server/src/history/services/history.d.ts.map +1 -1
  149. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  150. package/dist/server/src/history/services/utils.d.ts +4 -4
  151. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  152. package/dist/server/src/index.d.ts +4 -4
  153. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  154. package/dist/server/src/preview/constants.d.ts +2 -0
  155. package/dist/server/src/preview/constants.d.ts.map +1 -0
  156. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  157. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  158. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  159. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  160. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  161. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  162. package/dist/server/src/preview/index.d.ts +4 -0
  163. package/dist/server/src/preview/index.d.ts.map +1 -0
  164. package/dist/server/src/preview/routes/index.d.ts +8 -0
  165. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  166. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  167. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  168. package/dist/server/src/preview/services/index.d.ts +16 -0
  169. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  170. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  171. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  172. package/dist/server/src/preview/services/preview.d.ts +12 -0
  173. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  174. package/dist/server/src/preview/utils.d.ts +19 -0
  175. package/dist/server/src/preview/utils.d.ts.map +1 -0
  176. package/dist/server/src/register.d.ts.map +1 -1
  177. package/dist/server/src/routes/index.d.ts.map +1 -1
  178. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  179. package/dist/server/src/services/document-metadata.d.ts +8 -8
  180. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  181. package/dist/server/src/services/index.d.ts +4 -4
  182. package/dist/server/src/services/index.d.ts.map +1 -1
  183. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  184. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  185. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  186. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  187. package/dist/server/src/utils/index.d.ts +2 -0
  188. package/dist/server/src/utils/index.d.ts.map +1 -1
  189. package/dist/shared/contracts/collection-types.d.ts +3 -1
  190. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  191. package/dist/shared/contracts/index.d.ts +1 -0
  192. package/dist/shared/contracts/index.d.ts.map +1 -1
  193. package/dist/shared/contracts/preview.d.ts +27 -0
  194. package/dist/shared/contracts/preview.d.ts.map +1 -0
  195. package/dist/shared/index.js +4 -0
  196. package/dist/shared/index.js.map +1 -1
  197. package/dist/shared/index.mjs +4 -0
  198. package/dist/shared/index.mjs.map +1 -1
  199. package/package.json +15 -15
  200. package/dist/_chunks/EditViewPage-CoQEnFlC.js.map +0 -1
  201. package/dist/_chunks/EditViewPage-DvaV7U9b.mjs.map +0 -1
  202. package/dist/_chunks/Field-Cz_J9551.mjs.map +0 -1
  203. package/dist/_chunks/Field-ZdrmmQ4Y.js.map +0 -1
  204. package/dist/_chunks/Form-Bpig5rch.js.map +0 -1
  205. package/dist/_chunks/Form-Dxmihyw8.mjs.map +0 -1
  206. package/dist/_chunks/History-BZP8n7KT.mjs.map +0 -1
  207. package/dist/_chunks/History-BfX6XmZK.js.map +0 -1
  208. package/dist/_chunks/ListConfigurationPage-B3CXj8PY.js.map +0 -1
  209. package/dist/_chunks/ListConfigurationPage-DxKuVkKz.mjs.map +0 -1
  210. package/dist/_chunks/ListViewPage-Bk9VO__I.js.map +0 -1
  211. package/dist/_chunks/ListViewPage-D5D3tVPq.mjs.map +0 -1
  212. package/dist/_chunks/Relations-B6B3A3mb.js.map +0 -1
  213. package/dist/_chunks/Relations-BOYZmuWy.mjs.map +0 -1
  214. package/dist/_chunks/index-DzN3kBgx.js.map +0 -1
  215. package/dist/_chunks/index-VHviNMeW.mjs.map +0 -1
  216. package/dist/_chunks/layout-CPn1PM6x.mjs.map +0 -1
  217. package/dist/_chunks/layout-b91XRlD2.js.map +0 -1
  218. package/dist/_chunks/relations-BsqxS6tR.mjs.map +0 -1
  219. package/dist/_chunks/relations-CA7IYmcP.js.map +0 -1
  220. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  221. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  222. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  223. package/strapi-server.js +0 -3
@@ -1,5 +1,5 @@
1
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";
2
+ import { pick, omit, difference, castArray, mergeWith, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy } from "lodash/fp";
3
3
  import "@strapi/types";
4
4
  import * as yup from "yup";
5
5
  import { scheduleJob } from "node-schedule";
@@ -7,10 +7,10 @@ import isNil from "lodash/isNil";
7
7
  import _, { intersection as intersection$1, difference as difference$1 } from "lodash";
8
8
  import qs from "qs";
9
9
  import slugify from "@sindresorhus/slugify";
10
- const getService$1 = (name) => {
10
+ const getService$2 = (name) => {
11
11
  return strapi.plugin("content-manager").service(name);
12
12
  };
13
- function getService(strapi2, name) {
13
+ function getService$1(strapi2, name) {
14
14
  return strapi2.service(`plugin::content-manager.${name}`);
15
15
  }
16
16
  const historyRestoreVersionSchema = yup.object().shape({
@@ -46,7 +46,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
46
46
  if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
47
47
  throw new errors.ForbiddenError("contentType and documentId are required");
48
48
  }
49
- const permissionChecker2 = getService$1("permission-checker").create({
49
+ const permissionChecker2 = getService$2("permission-checker").create({
50
50
  userAbility: ctx.state.userAbility,
51
51
  model: ctx.query.contentType
52
52
  });
@@ -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: pagination2 } = await getService(strapi2, "history").findVersionsPage({
57
+ const { results, pagination: pagination2 } = await getService$1(strapi2, "history").findVersionsPage({
58
58
  query: {
59
59
  ...query,
60
60
  ...getValidPagination({ page: query.page, pageSize: query.pageSize })
@@ -79,14 +79,14 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
79
79
  async restoreVersion(ctx) {
80
80
  const request = ctx.request;
81
81
  await validateRestoreVersion(request.body, "contentType is required");
82
- const permissionChecker2 = getService$1("permission-checker").create({
82
+ const permissionChecker2 = getService$2("permission-checker").create({
83
83
  userAbility: ctx.state.userAbility,
84
84
  model: request.body.contentType
85
85
  });
86
86
  if (permissionChecker2.cannot.update()) {
87
87
  throw new errors.ForbiddenError();
88
88
  }
89
- const restoredDocument = await getService(strapi2, "history").restoreVersion(
89
+ const restoredDocument = await getService$1(strapi2, "history").restoreVersion(
90
90
  request.params.versionId
91
91
  );
92
92
  return {
@@ -95,7 +95,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
95
95
  }
96
96
  };
97
97
  };
98
- const controllers$1 = {
98
+ const controllers$2 = {
99
99
  "history-version": createHistoryVersionController
100
100
  /**
101
101
  * Casting is needed because the types aren't aware that Strapi supports
@@ -141,8 +141,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
141
141
  };
142
142
  const getRelationRestoreValue = async (versionRelationData, attribute) => {
143
143
  if (Array.isArray(versionRelationData)) {
144
- if (versionRelationData.length === 0)
145
- return versionRelationData;
144
+ if (versionRelationData.length === 0) return versionRelationData;
146
145
  const existingAndMissingRelations = await Promise.all(
147
146
  versionRelationData.map((relation) => {
148
147
  return strapi2.documents(attribute.target).findOne({
@@ -173,10 +172,11 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
173
172
  return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
174
173
  };
175
174
  const localesService = strapi2.plugin("i18n")?.service("locales");
175
+ const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
176
176
  const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
177
+ const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
177
178
  const getLocaleDictionary = async () => {
178
- if (!localesService)
179
- return {};
179
+ if (!localesService) return {};
180
180
  const locales = await localesService.find() || [];
181
181
  return locales.reduce(
182
182
  (acc, locale) => {
@@ -200,31 +200,53 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
200
200
  const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
201
201
  return documentMetadataService.getStatus(document, meta.availableStatus);
202
202
  };
203
- const getDeepPopulate2 = (uid2) => {
203
+ const getComponentFields = (componentUID) => {
204
+ return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
205
+ (fieldsAcc, [key, attribute]) => {
206
+ if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
207
+ fieldsAcc.push(key);
208
+ }
209
+ return fieldsAcc;
210
+ },
211
+ []
212
+ );
213
+ };
214
+ const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
204
215
  const model = strapi2.getModel(uid2);
205
216
  const attributes = Object.entries(model.attributes);
217
+ const fieldSelector = useDatabaseSyntax ? "select" : "fields";
206
218
  return attributes.reduce((acc, [attributeName, attribute]) => {
207
219
  switch (attribute.type) {
208
220
  case "relation": {
221
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
222
+ if (isMorphRelation) {
223
+ break;
224
+ }
209
225
  const isVisible2 = contentTypes$1.isVisibleAttribute(model, attributeName);
210
226
  if (isVisible2) {
211
- acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
227
+ acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
212
228
  }
213
229
  break;
214
230
  }
215
231
  case "media": {
216
- acc[attributeName] = { fields: ["id"] };
232
+ acc[attributeName] = { [fieldSelector]: ["id"] };
217
233
  break;
218
234
  }
219
235
  case "component": {
220
236
  const populate = getDeepPopulate2(attribute.component);
221
- acc[attributeName] = { populate };
237
+ acc[attributeName] = {
238
+ populate,
239
+ [fieldSelector]: getComponentFields(attribute.component)
240
+ };
222
241
  break;
223
242
  }
224
243
  case "dynamiczone": {
225
244
  const populatedComponents = (attribute.components || []).reduce(
226
245
  (acc2, componentUID) => {
227
- acc2[componentUID] = { populate: getDeepPopulate2(componentUID) };
246
+ acc2[componentUID] = {
247
+ populate: getDeepPopulate2(componentUID),
248
+ [fieldSelector]: getComponentFields(componentUID)
249
+ };
228
250
  return acc2;
229
251
  },
230
252
  {}
@@ -286,6 +308,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
286
308
  getRelationRestoreValue,
287
309
  getMediaRestoreValue,
288
310
  getDefaultLocale,
311
+ isLocalizedContentType,
289
312
  getLocaleDictionary,
290
313
  getRetentionDays,
291
314
  getVersionStatus,
@@ -308,7 +331,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
308
331
  });
309
332
  },
310
333
  async findVersionsPage(params) {
311
- const locale = params.query.locale || await serviceUtils.getDefaultLocale();
334
+ const model = strapi2.getModel(params.query.contentType);
335
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
336
+ const defaultLocale = await serviceUtils.getDefaultLocale();
337
+ let locale = null;
338
+ if (isLocalizedContentType) {
339
+ locale = params.query.locale || defaultLocale;
340
+ }
312
341
  const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
313
342
  query.findPage({
314
343
  ...params.query,
@@ -330,7 +359,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
330
359
  const attributeValue = entry.data[attributeKey];
331
360
  const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
332
361
  if (attributeSchema.type === "media") {
333
- const permissionChecker2 = getService$1("permission-checker").create({
362
+ const permissionChecker2 = getService$2("permission-checker").create({
334
363
  userAbility: params.state.userAbility,
335
364
  model: "plugin::upload.file"
336
365
  });
@@ -353,7 +382,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
353
382
  if (userToPopulate == null) {
354
383
  return null;
355
384
  }
356
- return strapi2.query("admin::user").findOne({ where: { id: userToPopulate.id } });
385
+ return strapi2.query("admin::user").findOne({
386
+ where: {
387
+ ...userToPopulate.id ? { id: userToPopulate.id } : {},
388
+ ...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
389
+ }
390
+ });
357
391
  })
358
392
  );
359
393
  return {
@@ -366,7 +400,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
366
400
  [attributeKey]: adminUsers
367
401
  };
368
402
  }
369
- const permissionChecker2 = getService$1("permission-checker").create({
403
+ const permissionChecker2 = getService$2("permission-checker").create({
370
404
  userAbility: params.state.userAbility,
371
405
  model: attributeSchema.target
372
406
  });
@@ -464,13 +498,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
464
498
  }
465
499
  };
466
500
  };
501
+ const shouldCreateHistoryVersion = (context) => {
502
+ if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
503
+ return false;
504
+ }
505
+ if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
506
+ return false;
507
+ }
508
+ if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
509
+ return false;
510
+ }
511
+ if (!context.contentType.uid.startsWith("api::")) {
512
+ return false;
513
+ }
514
+ return true;
515
+ };
516
+ const getSchemas = (uid2) => {
517
+ const attributesSchema = strapi.getModel(uid2).attributes;
518
+ const componentsSchemas = Object.keys(attributesSchema).reduce(
519
+ (currentComponentSchemas, key) => {
520
+ const fieldSchema = attributesSchema[key];
521
+ if (fieldSchema.type === "component") {
522
+ const componentSchema = strapi.getModel(fieldSchema.component).attributes;
523
+ return {
524
+ ...currentComponentSchemas,
525
+ [fieldSchema.component]: componentSchema
526
+ };
527
+ }
528
+ return currentComponentSchemas;
529
+ },
530
+ {}
531
+ );
532
+ return {
533
+ schema: omit(FIELDS_TO_IGNORE, attributesSchema),
534
+ componentsSchemas
535
+ };
536
+ };
467
537
  const createLifecyclesService = ({ strapi: strapi2 }) => {
468
538
  const state = {
469
539
  deleteExpiredJob: null,
470
540
  isInitialized: false
471
541
  };
472
- const query = strapi2.db.query(HISTORY_VERSION_UID);
473
- const historyService = getService(strapi2, "history");
474
542
  const serviceUtils = createServiceUtils({ strapi: strapi2 });
475
543
  return {
476
544
  async bootstrap() {
@@ -478,73 +546,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
478
546
  return;
479
547
  }
480
548
  strapi2.documents.use(async (context, next) => {
481
- if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
482
- return next();
483
- }
484
- if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
485
- return next();
486
- }
487
- const contentTypeUid = context.contentType.uid;
488
- if (!contentTypeUid.startsWith("api::")) {
489
- return next();
490
- }
491
549
  const result = await next();
492
- const documentContext = {
493
- documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
494
- locale: context.params?.locale
495
- };
550
+ if (!shouldCreateHistoryVersion(context)) {
551
+ return result;
552
+ }
553
+ const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
496
554
  const defaultLocale = await serviceUtils.getDefaultLocale();
497
- const locale = documentContext.locale || defaultLocale;
498
- if (Array.isArray(locale)) {
499
- strapi2.log.warn(
500
- "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
501
- );
502
- return next();
555
+ const locales = castArray(context.params?.locale || defaultLocale);
556
+ if (!locales.length) {
557
+ return result;
503
558
  }
504
- const document = await strapi2.documents(contentTypeUid).findOne({
505
- documentId: documentContext.documentId,
506
- locale,
507
- populate: serviceUtils.getDeepPopulate(contentTypeUid)
559
+ const uid2 = context.contentType.uid;
560
+ const schemas = getSchemas(uid2);
561
+ const model = strapi2.getModel(uid2);
562
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
563
+ const localeEntries = await strapi2.db.query(uid2).findMany({
564
+ where: {
565
+ documentId,
566
+ ...isLocalizedContentType ? { locale: { $in: locales } } : {},
567
+ ...contentTypes$1.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
568
+ },
569
+ populate: serviceUtils.getDeepPopulate(
570
+ uid2,
571
+ true
572
+ /* use database syntax */
573
+ )
508
574
  });
509
- const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
510
- const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
511
- const componentsSchemas = Object.keys(
512
- attributesSchema
513
- ).reduce((currentComponentSchemas, key) => {
514
- const fieldSchema = attributesSchema[key];
515
- if (fieldSchema.type === "component") {
516
- const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
517
- return {
518
- ...currentComponentSchemas,
519
- [fieldSchema.component]: componentSchema
520
- };
521
- }
522
- return currentComponentSchemas;
523
- }, {});
524
575
  await strapi2.db.transaction(async ({ onCommit }) => {
525
- onCommit(() => {
526
- historyService.createVersion({
527
- contentType: contentTypeUid,
528
- data: omit(FIELDS_TO_IGNORE, document),
529
- schema: omit(FIELDS_TO_IGNORE, attributesSchema),
530
- componentsSchemas,
531
- relatedDocumentId: documentContext.documentId,
532
- locale,
533
- status
534
- });
576
+ onCommit(async () => {
577
+ for (const entry of localeEntries) {
578
+ const status = await serviceUtils.getVersionStatus(uid2, entry);
579
+ await getService$1(strapi2, "history").createVersion({
580
+ contentType: uid2,
581
+ data: omit(FIELDS_TO_IGNORE, entry),
582
+ relatedDocumentId: documentId,
583
+ locale: entry.locale,
584
+ status,
585
+ ...schemas
586
+ });
587
+ }
535
588
  });
536
589
  });
537
590
  return result;
538
591
  });
539
- state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
592
+ state.deleteExpiredJob = scheduleJob("historyDaily", "0 0 * * *", () => {
540
593
  const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
541
594
  const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
542
- query.deleteMany({
595
+ strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
543
596
  where: {
544
597
  created_at: {
545
- $lt: expirationDate.toISOString()
598
+ $lt: expirationDate
546
599
  }
547
600
  }
601
+ }).catch((error) => {
602
+ if (error instanceof Error) {
603
+ strapi2.log.error("Error deleting expired history versions", error.message);
604
+ }
548
605
  });
549
606
  });
550
607
  state.isInitialized = true;
@@ -556,17 +613,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
556
613
  }
557
614
  };
558
615
  };
559
- const services$1 = {
616
+ const services$2 = {
560
617
  history: createHistoryService,
561
618
  lifecycles: createLifecyclesService
562
619
  };
563
- const info = { pluginName: "content-manager", type: "admin" };
620
+ const info$1 = { pluginName: "content-manager", type: "admin" };
564
621
  const historyVersionRouter = {
565
622
  type: "admin",
566
623
  routes: [
567
624
  {
568
625
  method: "GET",
569
- info,
626
+ info: info$1,
570
627
  path: "/history-versions",
571
628
  handler: "history-version.findMany",
572
629
  config: {
@@ -575,7 +632,7 @@ const historyVersionRouter = {
575
632
  },
576
633
  {
577
634
  method: "PUT",
578
- info,
635
+ info: info$1,
579
636
  path: "/history-versions/:versionId/restore",
580
637
  handler: "history-version.restoreVersion",
581
638
  config: {
@@ -584,7 +641,7 @@ const historyVersionRouter = {
584
641
  }
585
642
  ]
586
643
  };
587
- const routes$1 = {
644
+ const routes$2 = {
588
645
  "history-version": historyVersionRouter
589
646
  };
590
647
  const historyVersion = {
@@ -631,21 +688,21 @@ const historyVersion = {
631
688
  }
632
689
  }
633
690
  };
634
- const getFeature = () => {
691
+ const getFeature$1 = () => {
635
692
  if (strapi.ee.features.isEnabled("cms-content-history")) {
636
693
  return {
637
694
  register({ strapi: strapi2 }) {
638
695
  strapi2.get("models").add(historyVersion);
639
696
  },
640
697
  bootstrap({ strapi: strapi2 }) {
641
- getService(strapi2, "lifecycles").bootstrap();
698
+ getService$1(strapi2, "lifecycles").bootstrap();
642
699
  },
643
700
  destroy({ strapi: strapi2 }) {
644
- getService(strapi2, "lifecycles").destroy();
701
+ getService$1(strapi2, "lifecycles").destroy();
645
702
  },
646
- controllers: controllers$1,
647
- services: services$1,
648
- routes: routes$1
703
+ controllers: controllers$2,
704
+ services: services$2,
705
+ routes: routes$2
649
706
  };
650
707
  }
651
708
  return {
@@ -654,9 +711,205 @@ const getFeature = () => {
654
711
  }
655
712
  };
656
713
  };
657
- const history = getFeature();
714
+ const history = getFeature$1();
715
+ const FEATURE_ID = "preview";
716
+ const info = { pluginName: "content-manager", type: "admin" };
717
+ const previewRouter = {
718
+ type: "admin",
719
+ routes: [
720
+ {
721
+ method: "GET",
722
+ info,
723
+ path: "/preview/url/:contentType",
724
+ handler: "preview.getPreviewUrl",
725
+ config: {
726
+ policies: ["admin::isAuthenticatedAdmin"]
727
+ }
728
+ }
729
+ ]
730
+ };
731
+ const routes$1 = {
732
+ preview: previewRouter
733
+ };
734
+ function getService(strapi2, name) {
735
+ return strapi2.service(`plugin::content-manager.${name}`);
736
+ }
737
+ const getPreviewUrlSchema = yup.object().shape({
738
+ // Will be undefined for single types
739
+ documentId: yup.string(),
740
+ locale: yup.string().nullable(),
741
+ status: yup.string()
742
+ }).required();
743
+ const validatePreviewUrl = async (strapi2, uid2, params) => {
744
+ await validateYupSchema(getPreviewUrlSchema)(params);
745
+ const newParams = pick(["documentId", "locale", "status"], params);
746
+ const model = strapi2.getModel(uid2);
747
+ if (!model || model.modelType !== "contentType") {
748
+ throw new errors.ValidationError("Invalid content type");
749
+ }
750
+ const isSingleType = model?.kind === "singleType";
751
+ if (!isSingleType && !params.documentId) {
752
+ throw new errors.ValidationError("documentId is required for Collection Types");
753
+ }
754
+ if (isSingleType) {
755
+ const doc = await strapi2.documents(uid2).findFirst();
756
+ if (!doc) {
757
+ throw new errors.NotFoundError("Document not found");
758
+ }
759
+ newParams.documentId = doc?.documentId;
760
+ }
761
+ if (!newParams.status) {
762
+ const isDPEnabled = model?.options?.draftAndPublish;
763
+ newParams.status = isDPEnabled ? "draft" : "published";
764
+ }
765
+ return newParams;
766
+ };
767
+ const createPreviewController = () => {
768
+ return {
769
+ /**
770
+ * Transforms an entry into a preview URL, so that it can be previewed
771
+ * in the Content Manager.
772
+ */
773
+ async getPreviewUrl(ctx) {
774
+ const uid2 = ctx.params.contentType;
775
+ const query = ctx.request.query;
776
+ const params = await validatePreviewUrl(strapi, uid2, query);
777
+ const previewService = getService(strapi, "preview");
778
+ const url = await previewService.getPreviewUrl(uid2, params);
779
+ if (!url) {
780
+ ctx.status = 204;
781
+ }
782
+ return {
783
+ data: { url }
784
+ };
785
+ }
786
+ };
787
+ };
788
+ const controllers$1 = {
789
+ preview: createPreviewController
790
+ /**
791
+ * Casting is needed because the types aren't aware that Strapi supports
792
+ * passing a controller factory as the value, instead of a controller object directly
793
+ */
794
+ };
795
+ const createPreviewService = ({ strapi: strapi2 }) => {
796
+ const config = getService(strapi2, "preview-config");
797
+ return {
798
+ async getPreviewUrl(uid2, params) {
799
+ const handler = config.getPreviewHandler();
800
+ try {
801
+ return handler(uid2, params);
802
+ } catch (error) {
803
+ strapi2.log.error(`Failed to get preview URL: ${error}`);
804
+ throw new errors.ApplicationError("Failed to get preview URL");
805
+ }
806
+ return;
807
+ }
808
+ };
809
+ };
810
+ const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
811
+ const middlewares = strapi.config.get("middlewares");
812
+ const configuredMiddlewares = middlewares.map((currentMiddleware) => {
813
+ if (currentMiddleware === middleware.name) {
814
+ return middleware;
815
+ }
816
+ if (currentMiddleware.name === middleware.name) {
817
+ return mergeWith(
818
+ (objValue, srcValue) => {
819
+ if (Array.isArray(objValue)) {
820
+ return objValue.concat(srcValue);
821
+ }
822
+ return void 0;
823
+ },
824
+ currentMiddleware,
825
+ middleware
826
+ );
827
+ }
828
+ return currentMiddleware;
829
+ });
830
+ strapi.config.set("middlewares", configuredMiddlewares);
831
+ };
832
+ const createPreviewConfigService = ({ strapi: strapi2 }) => {
833
+ return {
834
+ register() {
835
+ if (!this.isEnabled()) {
836
+ return;
837
+ }
838
+ const config = strapi2.config.get("admin.preview");
839
+ if (config.config?.allowedOrigins) {
840
+ extendMiddlewareConfiguration({
841
+ name: "strapi::security",
842
+ config: {
843
+ contentSecurityPolicy: {
844
+ directives: {
845
+ "frame-src": config.config.allowedOrigins
846
+ }
847
+ }
848
+ }
849
+ });
850
+ }
851
+ },
852
+ isEnabled() {
853
+ const config = strapi2.config.get("admin.preview");
854
+ if (!config) {
855
+ return false;
856
+ }
857
+ return config?.enabled ?? true;
858
+ },
859
+ /**
860
+ * Validate if the configuration is valid
861
+ */
862
+ validate() {
863
+ if (!this.isEnabled()) {
864
+ return;
865
+ }
866
+ const handler = this.getPreviewHandler();
867
+ if (typeof handler !== "function") {
868
+ throw new errors.ValidationError(
869
+ "Preview configuration is invalid. Handler must be a function"
870
+ );
871
+ }
872
+ },
873
+ /**
874
+ * Utility to get the preview handler from the configuration
875
+ */
876
+ getPreviewHandler() {
877
+ const config = strapi2.config.get("admin.preview");
878
+ const emptyHandler = () => {
879
+ return void 0;
880
+ };
881
+ if (!this.isEnabled()) {
882
+ return emptyHandler;
883
+ }
884
+ return config?.config?.handler || emptyHandler;
885
+ }
886
+ };
887
+ };
888
+ const services$1 = {
889
+ preview: createPreviewService,
890
+ "preview-config": createPreviewConfigService
891
+ };
892
+ const getFeature = () => {
893
+ if (!strapi.features.future.isEnabled(FEATURE_ID)) {
894
+ return {};
895
+ }
896
+ return {
897
+ register() {
898
+ const config = getService(strapi, "preview-config");
899
+ config.validate();
900
+ config.register();
901
+ },
902
+ bootstrap() {
903
+ },
904
+ routes: routes$1,
905
+ controllers: controllers$1,
906
+ services: services$1
907
+ };
908
+ };
909
+ const preview = getFeature();
658
910
  const register = async ({ strapi: strapi2 }) => {
659
911
  await history.register?.({ strapi: strapi2 });
912
+ await preview.register?.({ strapi: strapi2 });
660
913
  };
661
914
  const ALLOWED_WEBHOOK_EVENTS = {
662
915
  ENTRY_PUBLISH: "entry.publish",
@@ -666,11 +919,12 @@ const bootstrap = async () => {
666
919
  Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
667
920
  strapi.get("webhookStore").addAllowedEvent(key, value);
668
921
  });
669
- getService$1("field-sizes").setCustomFieldInputSizes();
670
- await getService$1("components").syncConfigurations();
671
- await getService$1("content-types").syncConfigurations();
672
- await getService$1("permission").registerPermissions();
922
+ getService$2("field-sizes").setCustomFieldInputSizes();
923
+ await getService$2("components").syncConfigurations();
924
+ await getService$2("content-types").syncConfigurations();
925
+ await getService$2("permission").registerPermissions();
673
926
  await history.bootstrap?.({ strapi });
927
+ await preview.bootstrap?.({ strapi });
674
928
  };
675
929
  const destroy = async ({ strapi: strapi2 }) => {
676
930
  await history.destroy?.({ strapi: strapi2 });
@@ -1160,7 +1414,8 @@ const admin = {
1160
1414
  };
1161
1415
  const routes = {
1162
1416
  admin,
1163
- ...history.routes ? history.routes : {}
1417
+ ...history.routes ? history.routes : {},
1418
+ ...preview.routes ? preview.routes : {}
1164
1419
  };
1165
1420
  const hasPermissionsSchema = yup$1.object({
1166
1421
  actions: yup$1.array().of(yup$1.string()),
@@ -1171,6 +1426,11 @@ const { createPolicy } = policy;
1171
1426
  const hasPermissions = createPolicy({
1172
1427
  name: "plugin::content-manager.hasPermissions",
1173
1428
  validator: validateHasPermissionsInput,
1429
+ /**
1430
+ * NOTE: Action aliases are currently not checked at this level (policy).
1431
+ * This is currently the intended behavior to avoid changing the behavior of API related permissions.
1432
+ * If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
1433
+ */
1174
1434
  handler(ctx, config = {}) {
1175
1435
  const { actions = [], hasAtLeastOne = false } = config;
1176
1436
  const { userAbility } = ctx.state;
@@ -1218,8 +1478,7 @@ const isSortable = (schema, name) => {
1218
1478
  if (!_.has(schema.attributes, name)) {
1219
1479
  return false;
1220
1480
  }
1221
- if (schema.modelType === "component" && name === "id")
1222
- return false;
1481
+ if (schema.modelType === "component" && name === "id") return false;
1223
1482
  const attribute = schema.attributes[name];
1224
1483
  if (NON_SORTABLES.includes(attribute.type)) {
1225
1484
  return false;
@@ -1364,8 +1623,7 @@ const createDefaultSettings = async (schema) => {
1364
1623
  };
1365
1624
  };
1366
1625
  const syncSettings = async (configuration, schema) => {
1367
- if (isEmpty(configuration.settings))
1368
- return createDefaultSettings(schema);
1626
+ if (isEmpty(configuration.settings)) return createDefaultSettings(schema);
1369
1627
  const defaultField = getDefaultMainField(schema);
1370
1628
  const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
1371
1629
  return {
@@ -1412,7 +1670,7 @@ const createMetadasSchema = (schema) => {
1412
1670
  if (!value) {
1413
1671
  return yup$1.string();
1414
1672
  }
1415
- const targetSchema = getService$1("content-types").findContentType(
1673
+ const targetSchema = getService$2("content-types").findContentType(
1416
1674
  schema.attributes[key].targetModel
1417
1675
  );
1418
1676
  if (!targetSchema) {
@@ -1541,8 +1799,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
1541
1799
  }
1542
1800
  switch (attribute.type) {
1543
1801
  case "relation": {
1544
- if (canCreate(attributePath))
1545
- return body2;
1802
+ if (canCreate(attributePath)) return body2;
1546
1803
  return set(attributePath, { set: [] }, body2);
1547
1804
  }
1548
1805
  case "component": {
@@ -1552,8 +1809,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
1552
1809
  ]);
1553
1810
  }
1554
1811
  default: {
1555
- if (canCreate(attributePath))
1556
- return body2;
1812
+ if (canCreate(attributePath)) return body2;
1557
1813
  return set(attributePath, null, body2);
1558
1814
  }
1559
1815
  }
@@ -1564,9 +1820,11 @@ const multipleLocaleSchema = yup$1.lazy(
1564
1820
  (value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
1565
1821
  );
1566
1822
  const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
1567
- const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
1823
+ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
1568
1824
  const { allowMultipleLocales } = opts;
1569
- const { locale, status, ...rest } = request || {};
1825
+ const { locale, status: providedStatus, ...rest } = request || {};
1826
+ const defaultStatus = contentTypes$1.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
1827
+ const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
1570
1828
  const schema = yup$1.object().shape({
1571
1829
  locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
1572
1830
  status: statusSchema
@@ -1579,7 +1837,7 @@ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales
1579
1837
  }
1580
1838
  };
1581
1839
  const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
1582
- const documentMetadata2 = getService$1("document-metadata");
1840
+ const documentMetadata2 = getService$2("document-metadata");
1583
1841
  const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
1584
1842
  let {
1585
1843
  meta: { availableLocales, availableStatus }
@@ -1605,8 +1863,8 @@ const createDocument = async (ctx, opts) => {
1605
1863
  const { userAbility, user } = ctx.state;
1606
1864
  const { model } = ctx.params;
1607
1865
  const { body } = ctx.request;
1608
- const documentManager2 = getService$1("document-manager");
1609
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1866
+ const documentManager2 = getService$2("document-manager");
1867
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1610
1868
  if (permissionChecker2.cannot.create()) {
1611
1869
  throw new errors.ForbiddenError();
1612
1870
  }
@@ -1614,7 +1872,7 @@ const createDocument = async (ctx, opts) => {
1614
1872
  const setCreator = setCreatorFields({ user });
1615
1873
  const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
1616
1874
  const sanitizedBody = await sanitizeFn(body);
1617
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
1875
+ const { locale, status } = await getDocumentLocaleAndStatus(body, model);
1618
1876
  return documentManager2.create(model, {
1619
1877
  data: sanitizedBody,
1620
1878
  locale,
@@ -1626,14 +1884,14 @@ const updateDocument = async (ctx, opts) => {
1626
1884
  const { userAbility, user } = ctx.state;
1627
1885
  const { id, model } = ctx.params;
1628
1886
  const { body } = ctx.request;
1629
- const documentManager2 = getService$1("document-manager");
1630
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1887
+ const documentManager2 = getService$2("document-manager");
1888
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1631
1889
  if (permissionChecker2.cannot.update()) {
1632
1890
  throw new errors.ForbiddenError();
1633
1891
  }
1634
1892
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1635
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1636
- const { locale } = await getDocumentLocaleAndStatus(body);
1893
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
1894
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1637
1895
  const [documentVersion, documentExists] = await Promise.all([
1638
1896
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1639
1897
  documentManager2.exists(model, id)
@@ -1649,7 +1907,7 @@ const updateDocument = async (ctx, opts) => {
1649
1907
  throw new errors.ForbiddenError();
1650
1908
  }
1651
1909
  const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
1652
- const setCreator = setCreatorFields({ user, isEdition: true });
1910
+ const setCreator = documentVersion ? setCreatorFields({ user, isEdition: true }) : setCreatorFields({ user });
1653
1911
  const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
1654
1912
  const sanitizedBody = await sanitizeFn(body);
1655
1913
  return documentManager2.update(documentVersion?.documentId || id, model, {
@@ -1663,15 +1921,15 @@ const collectionTypes = {
1663
1921
  const { userAbility } = ctx.state;
1664
1922
  const { model } = ctx.params;
1665
1923
  const { query } = ctx.request;
1666
- const documentMetadata2 = getService$1("document-metadata");
1667
- const documentManager2 = getService$1("document-manager");
1668
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1924
+ const documentMetadata2 = getService$2("document-metadata");
1925
+ const documentManager2 = getService$2("document-manager");
1926
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1669
1927
  if (permissionChecker2.cannot.read()) {
1670
1928
  return ctx.forbidden();
1671
1929
  }
1672
1930
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1673
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1674
- const { locale, status } = await getDocumentLocaleAndStatus(query);
1931
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1932
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
1675
1933
  const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
1676
1934
  { ...permissionQuery, populate, locale, status },
1677
1935
  model
@@ -1699,14 +1957,14 @@ const collectionTypes = {
1699
1957
  async findOne(ctx) {
1700
1958
  const { userAbility } = ctx.state;
1701
1959
  const { model, id } = ctx.params;
1702
- const documentManager2 = getService$1("document-manager");
1703
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1960
+ const documentManager2 = getService$2("document-manager");
1961
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1704
1962
  if (permissionChecker2.cannot.read()) {
1705
1963
  return ctx.forbidden();
1706
1964
  }
1707
1965
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1708
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1709
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
1966
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1967
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
1710
1968
  const version = await documentManager2.findOne(id, model, {
1711
1969
  populate,
1712
1970
  locale,
@@ -1721,7 +1979,7 @@ const collectionTypes = {
1721
1979
  permissionChecker2,
1722
1980
  model,
1723
1981
  // @ts-expect-error TODO: fix
1724
- { id, locale, publishedAt: null },
1982
+ { documentId: id, locale, publishedAt: null },
1725
1983
  { availableLocales: true, availableStatus: false }
1726
1984
  );
1727
1985
  ctx.body = { data: {}, meta };
@@ -1736,7 +1994,7 @@ const collectionTypes = {
1736
1994
  async create(ctx) {
1737
1995
  const { userAbility } = ctx.state;
1738
1996
  const { model } = ctx.params;
1739
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1997
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1740
1998
  const [totalEntries, document] = await Promise.all([
1741
1999
  strapi.db.query(model).count(),
1742
2000
  createDocument(ctx)
@@ -1757,7 +2015,7 @@ const collectionTypes = {
1757
2015
  async update(ctx) {
1758
2016
  const { userAbility } = ctx.state;
1759
2017
  const { model } = ctx.params;
1760
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2018
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1761
2019
  const updatedVersion = await updateDocument(ctx);
1762
2020
  const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
1763
2021
  ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
@@ -1766,14 +2024,14 @@ const collectionTypes = {
1766
2024
  const { userAbility, user } = ctx.state;
1767
2025
  const { model, sourceId: id } = ctx.params;
1768
2026
  const { body } = ctx.request;
1769
- const documentManager2 = getService$1("document-manager");
1770
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2027
+ const documentManager2 = getService$2("document-manager");
2028
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1771
2029
  if (permissionChecker2.cannot.create()) {
1772
2030
  return ctx.forbidden();
1773
2031
  }
1774
2032
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1775
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1776
- const { locale } = await getDocumentLocaleAndStatus(body);
2033
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2034
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1777
2035
  const document = await documentManager2.findOne(id, model, {
1778
2036
  populate,
1779
2037
  locale,
@@ -1811,14 +2069,14 @@ const collectionTypes = {
1811
2069
  async delete(ctx) {
1812
2070
  const { userAbility } = ctx.state;
1813
2071
  const { id, model } = ctx.params;
1814
- const documentManager2 = getService$1("document-manager");
1815
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2072
+ const documentManager2 = getService$2("document-manager");
2073
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1816
2074
  if (permissionChecker2.cannot.delete()) {
1817
2075
  return ctx.forbidden();
1818
2076
  }
1819
2077
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1820
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1821
- const { locale } = await getDocumentLocaleAndStatus(ctx.query);
2078
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2079
+ const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
1822
2080
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1823
2081
  if (documentLocales.length === 0) {
1824
2082
  return ctx.notFound();
@@ -1839,19 +2097,42 @@ const collectionTypes = {
1839
2097
  const { userAbility } = ctx.state;
1840
2098
  const { id, model } = ctx.params;
1841
2099
  const { body } = ctx.request;
1842
- const documentManager2 = getService$1("document-manager");
1843
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2100
+ const documentManager2 = getService$2("document-manager");
2101
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1844
2102
  if (permissionChecker2.cannot.publish()) {
1845
2103
  return ctx.forbidden();
1846
2104
  }
1847
2105
  const publishedDocument = await strapi.db.transaction(async () => {
1848
2106
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1849
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1850
- const document = id ? await updateDocument(ctx, { populate }) : await createDocument(ctx, { populate });
2107
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
2108
+ let document;
2109
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2110
+ const isCreate = isNil$1(id);
2111
+ if (isCreate) {
2112
+ if (permissionChecker2.cannot.create()) {
2113
+ throw new errors.ForbiddenError();
2114
+ }
2115
+ document = await createDocument(ctx, { populate });
2116
+ }
2117
+ const isUpdate = !isCreate;
2118
+ if (isUpdate) {
2119
+ const documentExists = documentManager2.exists(model, id);
2120
+ if (!documentExists) {
2121
+ throw new errors.NotFoundError("Document not found");
2122
+ }
2123
+ document = await documentManager2.findOne(id, model, { populate, locale });
2124
+ if (!document) {
2125
+ if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
2126
+ throw new errors.ForbiddenError();
2127
+ }
2128
+ document = await updateDocument(ctx);
2129
+ } else if (permissionChecker2.can.update(document)) {
2130
+ await updateDocument(ctx);
2131
+ }
2132
+ }
1851
2133
  if (permissionChecker2.cannot.publish(document)) {
1852
2134
  throw new errors.ForbiddenError();
1853
2135
  }
1854
- const { locale } = await getDocumentLocaleAndStatus(body);
1855
2136
  const publishResult = await documentManager2.publish(document.documentId, model, {
1856
2137
  locale
1857
2138
  // TODO: Allow setting creator fields on publish
@@ -1871,14 +2152,16 @@ const collectionTypes = {
1871
2152
  const { body } = ctx.request;
1872
2153
  const { documentIds } = body;
1873
2154
  await validateBulkActionInput(body);
1874
- const documentManager2 = getService$1("document-manager");
1875
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2155
+ const documentManager2 = getService$2("document-manager");
2156
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1876
2157
  if (permissionChecker2.cannot.publish()) {
1877
2158
  return ctx.forbidden();
1878
2159
  }
1879
2160
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1880
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1881
- const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
2161
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
2162
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
2163
+ allowMultipleLocales: true
2164
+ });
1882
2165
  const entityPromises = documentIds.map(
1883
2166
  (documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
1884
2167
  );
@@ -1900,12 +2183,14 @@ const collectionTypes = {
1900
2183
  const { body } = ctx.request;
1901
2184
  const { documentIds } = body;
1902
2185
  await validateBulkActionInput(body);
1903
- const documentManager2 = getService$1("document-manager");
1904
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2186
+ const documentManager2 = getService$2("document-manager");
2187
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1905
2188
  if (permissionChecker2.cannot.unpublish()) {
1906
2189
  return ctx.forbidden();
1907
2190
  }
1908
- const { locale } = await getDocumentLocaleAndStatus(body);
2191
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
2192
+ allowMultipleLocales: true
2193
+ });
1909
2194
  const entityPromises = documentIds.map(
1910
2195
  (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1911
2196
  );
@@ -1928,8 +2213,8 @@ const collectionTypes = {
1928
2213
  const {
1929
2214
  body: { discardDraft, ...body }
1930
2215
  } = ctx.request;
1931
- const documentManager2 = getService$1("document-manager");
1932
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2216
+ const documentManager2 = getService$2("document-manager");
2217
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1933
2218
  if (permissionChecker2.cannot.unpublish()) {
1934
2219
  return ctx.forbidden();
1935
2220
  }
@@ -1937,8 +2222,8 @@ const collectionTypes = {
1937
2222
  return ctx.forbidden();
1938
2223
  }
1939
2224
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1940
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1941
- const { locale } = await getDocumentLocaleAndStatus(body);
2225
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2226
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1942
2227
  const document = await documentManager2.findOne(id, model, {
1943
2228
  populate,
1944
2229
  locale,
@@ -1968,14 +2253,14 @@ const collectionTypes = {
1968
2253
  const { userAbility } = ctx.state;
1969
2254
  const { id, model } = ctx.params;
1970
2255
  const { body } = ctx.request;
1971
- const documentManager2 = getService$1("document-manager");
1972
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2256
+ const documentManager2 = getService$2("document-manager");
2257
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1973
2258
  if (permissionChecker2.cannot.discard()) {
1974
2259
  return ctx.forbidden();
1975
2260
  }
1976
2261
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
1977
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1978
- const { locale } = await getDocumentLocaleAndStatus(body);
2262
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2263
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1979
2264
  const document = await documentManager2.findOne(id, model, {
1980
2265
  populate,
1981
2266
  locale,
@@ -1999,14 +2284,14 @@ const collectionTypes = {
1999
2284
  const { query, body } = ctx.request;
2000
2285
  const { documentIds } = body;
2001
2286
  await validateBulkActionInput(body);
2002
- const documentManager2 = getService$1("document-manager");
2003
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2287
+ const documentManager2 = getService$2("document-manager");
2288
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2004
2289
  if (permissionChecker2.cannot.delete()) {
2005
2290
  return ctx.forbidden();
2006
2291
  }
2007
2292
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
2008
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2009
- const { locale } = await getDocumentLocaleAndStatus(body);
2293
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2294
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2010
2295
  const documentLocales = await documentManager2.findLocales(documentIds, model, {
2011
2296
  populate,
2012
2297
  locale
@@ -2026,14 +2311,14 @@ const collectionTypes = {
2026
2311
  async countDraftRelations(ctx) {
2027
2312
  const { userAbility } = ctx.state;
2028
2313
  const { model, id } = ctx.params;
2029
- const documentManager2 = getService$1("document-manager");
2030
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2314
+ const documentManager2 = getService$2("document-manager");
2315
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2031
2316
  if (permissionChecker2.cannot.read()) {
2032
2317
  return ctx.forbidden();
2033
2318
  }
2034
2319
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2035
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2036
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
2320
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2321
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
2037
2322
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
2038
2323
  if (!entity) {
2039
2324
  return ctx.notFound();
@@ -2051,12 +2336,12 @@ const collectionTypes = {
2051
2336
  const ids = ctx.request.query.documentIds;
2052
2337
  const locale = ctx.request.query.locale;
2053
2338
  const { model } = ctx.params;
2054
- const documentManager2 = getService$1("document-manager");
2055
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2339
+ const documentManager2 = getService$2("document-manager");
2340
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2056
2341
  if (permissionChecker2.cannot.read()) {
2057
2342
  return ctx.forbidden();
2058
2343
  }
2059
- const entities = await documentManager2.findMany(
2344
+ const documents = await documentManager2.findMany(
2060
2345
  {
2061
2346
  filters: {
2062
2347
  documentId: ids
@@ -2065,7 +2350,7 @@ const collectionTypes = {
2065
2350
  },
2066
2351
  model
2067
2352
  );
2068
- if (!entities) {
2353
+ if (!documents) {
2069
2354
  return ctx.notFound();
2070
2355
  }
2071
2356
  const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
@@ -2076,13 +2361,13 @@ const collectionTypes = {
2076
2361
  };
2077
2362
  const components$1 = {
2078
2363
  findComponents(ctx) {
2079
- const components2 = getService$1("components").findAllComponents();
2080
- const { toDto } = getService$1("data-mapper");
2364
+ const components2 = getService$2("components").findAllComponents();
2365
+ const { toDto } = getService$2("data-mapper");
2081
2366
  ctx.body = { data: components2.map(toDto) };
2082
2367
  },
2083
2368
  async findComponentConfiguration(ctx) {
2084
2369
  const { uid: uid2 } = ctx.params;
2085
- const componentService = getService$1("components");
2370
+ const componentService = getService$2("components");
2086
2371
  const component = componentService.findComponent(uid2);
2087
2372
  if (!component) {
2088
2373
  return ctx.notFound("component.notFound");
@@ -2099,7 +2384,7 @@ const components$1 = {
2099
2384
  async updateComponentConfiguration(ctx) {
2100
2385
  const { uid: uid2 } = ctx.params;
2101
2386
  const { body } = ctx.request;
2102
- const componentService = getService$1("components");
2387
+ const componentService = getService$2("components");
2103
2388
  const component = componentService.findComponent(uid2);
2104
2389
  if (!component) {
2105
2390
  return ctx.notFound("component.notFound");
@@ -2133,12 +2418,12 @@ const contentTypes = {
2133
2418
  } catch (error) {
2134
2419
  return ctx.send({ error }, 400);
2135
2420
  }
2136
- const contentTypes2 = getService$1("content-types").findContentTypesByKind(kind);
2137
- const { toDto } = getService$1("data-mapper");
2421
+ const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
2422
+ const { toDto } = getService$2("data-mapper");
2138
2423
  ctx.body = { data: contentTypes2.map(toDto) };
2139
2424
  },
2140
2425
  async findContentTypesSettings(ctx) {
2141
- const { findAllContentTypes, findConfiguration } = getService$1("content-types");
2426
+ const { findAllContentTypes, findConfiguration } = getService$2("content-types");
2142
2427
  const contentTypes2 = await findAllContentTypes();
2143
2428
  const configurations = await Promise.all(
2144
2429
  contentTypes2.map(async (contentType) => {
@@ -2152,7 +2437,7 @@ const contentTypes = {
2152
2437
  },
2153
2438
  async findContentTypeConfiguration(ctx) {
2154
2439
  const { uid: uid2 } = ctx.params;
2155
- const contentTypeService = getService$1("content-types");
2440
+ const contentTypeService = getService$2("content-types");
2156
2441
  const contentType = await contentTypeService.findContentType(uid2);
2157
2442
  if (!contentType) {
2158
2443
  return ctx.notFound("contentType.notFound");
@@ -2174,13 +2459,13 @@ const contentTypes = {
2174
2459
  const { userAbility } = ctx.state;
2175
2460
  const { uid: uid2 } = ctx.params;
2176
2461
  const { body } = ctx.request;
2177
- const contentTypeService = getService$1("content-types");
2178
- const metricsService = getService$1("metrics");
2462
+ const contentTypeService = getService$2("content-types");
2463
+ const metricsService = getService$2("metrics");
2179
2464
  const contentType = await contentTypeService.findContentType(uid2);
2180
2465
  if (!contentType) {
2181
2466
  return ctx.notFound("contentType.notFound");
2182
2467
  }
2183
- if (!getService$1("permission").canConfigureContentType({ userAbility, contentType })) {
2468
+ if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
2184
2469
  return ctx.forbidden();
2185
2470
  }
2186
2471
  let input;
@@ -2213,10 +2498,10 @@ const contentTypes = {
2213
2498
  };
2214
2499
  const init = {
2215
2500
  getInitData(ctx) {
2216
- const { toDto } = getService$1("data-mapper");
2217
- const { findAllComponents } = getService$1("components");
2218
- const { getAllFieldSizes } = getService$1("field-sizes");
2219
- const { findAllContentTypes } = getService$1("content-types");
2501
+ const { toDto } = getService$2("data-mapper");
2502
+ const { findAllComponents } = getService$2("components");
2503
+ const { getAllFieldSizes } = getService$2("field-sizes");
2504
+ const { findAllContentTypes } = getService$2("content-types");
2220
2505
  ctx.body = {
2221
2506
  data: {
2222
2507
  fieldSizes: getAllFieldSizes(),
@@ -2252,36 +2537,41 @@ const addFiltersClause = (params, filtersClause) => {
2252
2537
  params.filters.$and.push(filtersClause);
2253
2538
  };
2254
2539
  const sanitizeMainField = (model, mainField, userAbility) => {
2255
- const permissionChecker2 = getService$1("permission-checker").create({
2540
+ const permissionChecker2 = getService$2("permission-checker").create({
2256
2541
  userAbility,
2257
2542
  model: model.uid
2258
2543
  });
2259
- if (!isListable(model, mainField)) {
2544
+ const isMainFieldListable = isListable(model, mainField);
2545
+ const canReadMainField = permissionChecker2.can.read(null, mainField);
2546
+ if (!isMainFieldListable || !canReadMainField) {
2260
2547
  return "id";
2261
2548
  }
2262
- if (permissionChecker2.cannot.read(null, mainField)) {
2263
- if (model.uid === "plugin::users-permissions.role") {
2264
- const userPermissionChecker = getService$1("permission-checker").create({
2265
- userAbility,
2266
- model: "plugin::users-permissions.user"
2267
- });
2268
- if (userPermissionChecker.can.read()) {
2269
- return "name";
2270
- }
2271
- }
2272
- return "id";
2549
+ if (model.uid === "plugin::users-permissions.role") {
2550
+ return "name";
2273
2551
  }
2274
2552
  return mainField;
2275
2553
  };
2276
- const addStatusToRelations = async (uid2, relations2) => {
2277
- if (!contentTypes$1.hasDraftAndPublish(strapi.contentTypes[uid2])) {
2554
+ const addStatusToRelations = async (targetUid, relations2) => {
2555
+ if (!contentTypes$1.hasDraftAndPublish(strapi.getModel(targetUid))) {
2278
2556
  return relations2;
2279
2557
  }
2280
- const documentMetadata2 = getService$1("document-metadata");
2281
- const documentsAvailableStatus = await documentMetadata2.getManyAvailableStatus(uid2, relations2);
2558
+ const documentMetadata2 = getService$2("document-metadata");
2559
+ if (!relations2.length) {
2560
+ return relations2;
2561
+ }
2562
+ const firstRelation = relations2[0];
2563
+ const filters = {
2564
+ documentId: { $in: relations2.map((r) => r.documentId) },
2565
+ // NOTE: find the "opposite" status
2566
+ publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
2567
+ };
2568
+ const availableStatus = await strapi.query(targetUid).findMany({
2569
+ select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
2570
+ filters
2571
+ });
2282
2572
  return relations2.map((relation) => {
2283
- const availableStatuses = documentsAvailableStatus.filter(
2284
- (availableDocument) => availableDocument.documentId === relation.documentId
2573
+ const availableStatuses = availableStatus.filter(
2574
+ (availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
2285
2575
  );
2286
2576
  return {
2287
2577
  ...relation,
@@ -2302,11 +2592,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
2302
2592
  const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
2303
2593
  const isSourceLocalized = isLocalized(sourceModel);
2304
2594
  const isTargetLocalized = isLocalized(targetModel);
2305
- let validatedLocale = locale;
2306
- if (!targetModel || !isTargetLocalized)
2307
- validatedLocale = void 0;
2308
2595
  return {
2309
- locale: validatedLocale,
2596
+ locale,
2310
2597
  isSourceLocalized,
2311
2598
  isTargetLocalized
2312
2599
  };
@@ -2315,8 +2602,7 @@ const validateStatus = (sourceUid, status) => {
2315
2602
  const sourceModel = strapi.getModel(sourceUid);
2316
2603
  const isDP = contentTypes$1.hasDraftAndPublish;
2317
2604
  const isSourceDP = isDP(sourceModel);
2318
- if (!isSourceDP)
2319
- return { status: void 0 };
2605
+ if (!isSourceDP) return { status: void 0 };
2320
2606
  switch (status) {
2321
2607
  case "published":
2322
2608
  return { status: "published" };
@@ -2346,7 +2632,7 @@ const relations = {
2346
2632
  ctx.request?.query?.locale
2347
2633
  );
2348
2634
  const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
2349
- const permissionChecker2 = getService$1("permission-checker").create({
2635
+ const permissionChecker2 = getService$2("permission-checker").create({
2350
2636
  userAbility,
2351
2637
  model
2352
2638
  });
@@ -2371,7 +2657,7 @@ const relations = {
2371
2657
  where.id = id;
2372
2658
  }
2373
2659
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2374
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2660
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2375
2661
  const currentEntity = await strapi.db.query(model).findOne({
2376
2662
  where,
2377
2663
  populate
@@ -2386,7 +2672,7 @@ const relations = {
2386
2672
  }
2387
2673
  entryId = currentEntity.id;
2388
2674
  }
2389
- const modelConfig = isComponent2 ? await getService$1("components").findConfiguration(sourceSchema) : await getService$1("content-types").findConfiguration(sourceSchema);
2675
+ const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
2390
2676
  const targetSchema = strapi.getModel(targetUid);
2391
2677
  const mainField = flow(
2392
2678
  prop(`metadatas.${targetField}.edit.mainField`),
@@ -2409,7 +2695,7 @@ const relations = {
2409
2695
  attribute,
2410
2696
  fieldsToSelect,
2411
2697
  mainField,
2412
- source: { schema: sourceSchema },
2698
+ source: { schema: sourceSchema, isLocalized: isSourceLocalized },
2413
2699
  target: { schema: targetSchema, isLocalized: isTargetLocalized },
2414
2700
  sourceSchema,
2415
2701
  targetSchema,
@@ -2431,7 +2717,8 @@ const relations = {
2431
2717
  fieldsToSelect,
2432
2718
  mainField,
2433
2719
  source: {
2434
- schema: { uid: sourceUid, modelType: sourceModelType }
2720
+ schema: { uid: sourceUid, modelType: sourceModelType },
2721
+ isLocalized: isSourceLocalized
2435
2722
  },
2436
2723
  target: {
2437
2724
  schema: { uid: targetUid },
@@ -2439,7 +2726,7 @@ const relations = {
2439
2726
  }
2440
2727
  } = await this.extractAndValidateRequestInfo(ctx, id);
2441
2728
  const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
2442
- const permissionChecker2 = getService$1("permission-checker").create({
2729
+ const permissionChecker2 = getService$2("permission-checker").create({
2443
2730
  userAbility: ctx.state.userAbility,
2444
2731
  model: targetUid
2445
2732
  });
@@ -2469,12 +2756,16 @@ const relations = {
2469
2756
  } else {
2470
2757
  where.id = id;
2471
2758
  }
2472
- if (status) {
2473
- where[`${alias}.published_at`] = getPublishedAtClause(status, targetUid);
2759
+ const publishedAt = getPublishedAtClause(status, targetUid);
2760
+ if (!isEmpty(publishedAt)) {
2761
+ where[`${alias}.published_at`] = publishedAt;
2474
2762
  }
2475
- if (filterByLocale) {
2763
+ if (isTargetLocalized && locale) {
2476
2764
  where[`${alias}.locale`] = locale;
2477
2765
  }
2766
+ if (isSourceLocalized && locale) {
2767
+ where.locale = locale;
2768
+ }
2478
2769
  if ((idsToInclude?.length ?? 0) !== 0) {
2479
2770
  where[`${alias}.id`].$notIn = idsToInclude;
2480
2771
  }
@@ -2492,7 +2783,8 @@ const relations = {
2492
2783
  id: { $notIn: uniq(idsToOmit) }
2493
2784
  });
2494
2785
  }
2495
- const res = await strapi.db.query(targetUid).findPage(strapi.get("query-params").transform(targetUid, queryParams));
2786
+ const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
2787
+ const res = await strapi.db.query(targetUid).findPage(dbQuery);
2496
2788
  ctx.body = {
2497
2789
  ...res,
2498
2790
  results: await addStatusToRelations(targetUid, res.results)
@@ -2507,29 +2799,39 @@ const relations = {
2507
2799
  attribute,
2508
2800
  targetField,
2509
2801
  fieldsToSelect,
2510
- source: {
2511
- schema: { uid: sourceUid }
2512
- },
2513
- target: {
2514
- schema: { uid: targetUid }
2515
- }
2802
+ status,
2803
+ source: { schema: sourceSchema },
2804
+ target: { schema: targetSchema }
2516
2805
  } = await this.extractAndValidateRequestInfo(ctx, id);
2517
- const permissionQuery = await getService$1("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
2806
+ const { uid: sourceUid } = sourceSchema;
2807
+ const { uid: targetUid } = targetSchema;
2808
+ const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
2518
2809
  const dbQuery = strapi.db.query(sourceUid);
2519
2810
  const loadRelations = relations$1.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
2811
+ const filters = {};
2812
+ if (sourceSchema?.options?.draftAndPublish) {
2813
+ if (targetSchema?.options?.draftAndPublish) {
2814
+ if (status === "published") {
2815
+ filters.publishedAt = { $notNull: true };
2816
+ } else {
2817
+ filters.publishedAt = { $null: true };
2818
+ }
2819
+ }
2820
+ } else if (targetSchema?.options?.draftAndPublish) {
2821
+ filters.publishedAt = { $null: true };
2822
+ }
2520
2823
  const res = await loadRelations({ id: entryId }, targetField, {
2521
- select: ["id", "documentId", "locale", "publishedAt"],
2824
+ select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
2522
2825
  ordering: "desc",
2523
2826
  page: ctx.request.query.page,
2524
- pageSize: ctx.request.query.pageSize
2827
+ pageSize: ctx.request.query.pageSize,
2828
+ filters
2525
2829
  });
2526
2830
  const loadedIds = res.results.map((item) => item.id);
2527
2831
  addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
2528
2832
  const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
2529
2833
  ...strapi.get("query-params").transform(targetUid, permissionQuery),
2530
- ordering: "desc",
2531
- page: ctx.request.query.page,
2532
- pageSize: ctx.request.query.pageSize
2834
+ ordering: "desc"
2533
2835
  });
2534
2836
  const relationsUnion = uniqBy("id", concat(sanitizedRes.results, res.results));
2535
2837
  ctx.body = {
@@ -2544,10 +2846,10 @@ const relations = {
2544
2846
  }
2545
2847
  };
2546
2848
  const buildPopulateFromQuery = async (query, model) => {
2547
- return getService$1("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
2849
+ return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
2548
2850
  };
2549
2851
  const findDocument = async (query, uid2, opts = {}) => {
2550
- const documentManager2 = getService$1("document-manager");
2852
+ const documentManager2 = getService$2("document-manager");
2551
2853
  const populate = await buildPopulateFromQuery(query, uid2);
2552
2854
  return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
2553
2855
  };
@@ -2555,13 +2857,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
2555
2857
  const { user, userAbility } = ctx.state;
2556
2858
  const { model } = ctx.params;
2557
2859
  const { body, query } = ctx.request;
2558
- const documentManager2 = getService$1("document-manager");
2559
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2860
+ const documentManager2 = getService$2("document-manager");
2861
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2560
2862
  if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
2561
2863
  throw new errors.ForbiddenError();
2562
2864
  }
2563
2865
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2564
- const { locale } = await getDocumentLocaleAndStatus(body);
2866
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2565
2867
  const [documentVersion, otherDocumentVersion] = await Promise.all([
2566
2868
  findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2567
2869
  // Find the first document to check if it exists
@@ -2597,12 +2899,12 @@ const singleTypes = {
2597
2899
  const { userAbility } = ctx.state;
2598
2900
  const { model } = ctx.params;
2599
2901
  const { query = {} } = ctx.request;
2600
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2902
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2601
2903
  if (permissionChecker2.cannot.read()) {
2602
2904
  return ctx.forbidden();
2603
2905
  }
2604
2906
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2605
- const { locale, status } = await getDocumentLocaleAndStatus(query);
2907
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
2606
2908
  const version = await findDocument(permissionQuery, model, { locale, status });
2607
2909
  if (!version) {
2608
2910
  if (permissionChecker2.cannot.create()) {
@@ -2616,7 +2918,7 @@ const singleTypes = {
2616
2918
  permissionChecker2,
2617
2919
  model,
2618
2920
  // @ts-expect-error - fix types
2619
- { id: document.documentId, locale, publishedAt: null },
2921
+ { documentId: document.documentId, locale, publishedAt: null },
2620
2922
  { availableLocales: true, availableStatus: false }
2621
2923
  );
2622
2924
  ctx.body = { data: {}, meta };
@@ -2631,7 +2933,7 @@ const singleTypes = {
2631
2933
  async createOrUpdate(ctx) {
2632
2934
  const { userAbility } = ctx.state;
2633
2935
  const { model } = ctx.params;
2634
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2936
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2635
2937
  const document = await createOrUpdateDocument(ctx);
2636
2938
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
2637
2939
  ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
@@ -2640,14 +2942,14 @@ const singleTypes = {
2640
2942
  const { userAbility } = ctx.state;
2641
2943
  const { model } = ctx.params;
2642
2944
  const { query = {} } = ctx.request;
2643
- const documentManager2 = getService$1("document-manager");
2644
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2945
+ const documentManager2 = getService$2("document-manager");
2946
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2645
2947
  if (permissionChecker2.cannot.delete()) {
2646
2948
  return ctx.forbidden();
2647
2949
  }
2648
2950
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2649
2951
  const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2650
- const { locale } = await getDocumentLocaleAndStatus(query);
2952
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2651
2953
  const documentLocales = await documentManager2.findLocales(void 0, model, {
2652
2954
  populate,
2653
2955
  locale
@@ -2669,8 +2971,8 @@ const singleTypes = {
2669
2971
  const { userAbility } = ctx.state;
2670
2972
  const { model } = ctx.params;
2671
2973
  const { query = {} } = ctx.request;
2672
- const documentManager2 = getService$1("document-manager");
2673
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2974
+ const documentManager2 = getService$2("document-manager");
2975
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2674
2976
  if (permissionChecker2.cannot.publish()) {
2675
2977
  return ctx.forbidden();
2676
2978
  }
@@ -2684,7 +2986,7 @@ const singleTypes = {
2684
2986
  if (permissionChecker2.cannot.publish(document)) {
2685
2987
  throw new errors.ForbiddenError();
2686
2988
  }
2687
- const { locale } = await getDocumentLocaleAndStatus(document);
2989
+ const { locale } = await getDocumentLocaleAndStatus(document, model);
2688
2990
  const publishResult = await documentManager2.publish(document.documentId, model, { locale });
2689
2991
  return publishResult.at(0);
2690
2992
  });
@@ -2698,8 +3000,8 @@ const singleTypes = {
2698
3000
  body: { discardDraft, ...body },
2699
3001
  query = {}
2700
3002
  } = ctx.request;
2701
- const documentManager2 = getService$1("document-manager");
2702
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
3003
+ const documentManager2 = getService$2("document-manager");
3004
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2703
3005
  if (permissionChecker2.cannot.unpublish()) {
2704
3006
  return ctx.forbidden();
2705
3007
  }
@@ -2707,7 +3009,7 @@ const singleTypes = {
2707
3009
  return ctx.forbidden();
2708
3010
  }
2709
3011
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2710
- const { locale } = await getDocumentLocaleAndStatus(body);
3012
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2711
3013
  const document = await findDocument(sanitizedQuery, model, { locale });
2712
3014
  if (!document) {
2713
3015
  return ctx.notFound();
@@ -2733,13 +3035,13 @@ const singleTypes = {
2733
3035
  const { userAbility } = ctx.state;
2734
3036
  const { model } = ctx.params;
2735
3037
  const { body, query = {} } = ctx.request;
2736
- const documentManager2 = getService$1("document-manager");
2737
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
3038
+ const documentManager2 = getService$2("document-manager");
3039
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2738
3040
  if (permissionChecker2.cannot.discard()) {
2739
3041
  return ctx.forbidden();
2740
3042
  }
2741
3043
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2742
- const { locale } = await getDocumentLocaleAndStatus(body);
3044
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2743
3045
  const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2744
3046
  if (!document) {
2745
3047
  return ctx.notFound();
@@ -2757,9 +3059,9 @@ const singleTypes = {
2757
3059
  const { userAbility } = ctx.state;
2758
3060
  const { model } = ctx.params;
2759
3061
  const { query } = ctx.request;
2760
- const documentManager2 = getService$1("document-manager");
2761
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2762
- const { locale } = await getDocumentLocaleAndStatus(query);
3062
+ const documentManager2 = getService$2("document-manager");
3063
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
3064
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2763
3065
  if (permissionChecker2.cannot.read()) {
2764
3066
  return ctx.forbidden();
2765
3067
  }
@@ -2780,9 +3082,9 @@ const uid$1 = {
2780
3082
  async generateUID(ctx) {
2781
3083
  const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2782
3084
  const { query = {} } = ctx.request;
2783
- const { locale } = await getDocumentLocaleAndStatus(query);
3085
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2784
3086
  await validateUIDField(contentTypeUID, field);
2785
- const uidService = getService$1("uid");
3087
+ const uidService = getService$2("uid");
2786
3088
  ctx.body = {
2787
3089
  data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
2788
3090
  };
@@ -2792,9 +3094,9 @@ const uid$1 = {
2792
3094
  ctx.request.body
2793
3095
  );
2794
3096
  const { query = {} } = ctx.request;
2795
- const { locale } = await getDocumentLocaleAndStatus(query);
3097
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2796
3098
  await validateUIDField(contentTypeUID, field);
2797
- const uidService = getService$1("uid");
3099
+ const uidService = getService$2("uid");
2798
3100
  const isAvailable = await uidService.checkUIDAvailability({
2799
3101
  contentTypeUID,
2800
3102
  field,
@@ -2815,7 +3117,8 @@ const controllers = {
2815
3117
  relations,
2816
3118
  "single-types": singleTypes,
2817
3119
  uid: uid$1,
2818
- ...history.controllers ? history.controllers : {}
3120
+ ...history.controllers ? history.controllers : {},
3121
+ ...preview.controllers ? preview.controllers : {}
2819
3122
  };
2820
3123
  const keys = {
2821
3124
  CONFIGURATION: "configuration"
@@ -2944,18 +3247,15 @@ async function syncMetadatas(configuration, schema) {
2944
3247
  _.set(updatedMeta, ["list", "searchable"], false);
2945
3248
  _.set(acc, [key], updatedMeta);
2946
3249
  }
2947
- if (!_.has(edit, "mainField"))
2948
- return acc;
3250
+ if (!_.has(edit, "mainField")) return acc;
2949
3251
  if (!isRelation$1(attr)) {
2950
3252
  _.set(updatedMeta, "edit", _.omit(edit, ["mainField"]));
2951
3253
  _.set(acc, [key], updatedMeta);
2952
3254
  return acc;
2953
3255
  }
2954
- if (edit.mainField === "id")
2955
- return acc;
3256
+ if (edit.mainField === "id") return acc;
2956
3257
  const targetSchema = getTargetSchema(attr.targetModel);
2957
- if (!targetSchema)
2958
- return acc;
3258
+ if (!targetSchema) return acc;
2959
3259
  if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
2960
3260
  _.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
2961
3261
  _.set(acc, [key], updatedMeta);
@@ -2966,12 +3266,12 @@ async function syncMetadatas(configuration, schema) {
2966
3266
  return _.assign(metasWithDefaults, updatedMetas);
2967
3267
  }
2968
3268
  const getTargetSchema = (targetModel) => {
2969
- return getService$1("content-types").findContentType(targetModel);
3269
+ return getService$2("content-types").findContentType(targetModel);
2970
3270
  };
2971
3271
  const DEFAULT_LIST_LENGTH = 4;
2972
3272
  const MAX_ROW_SIZE = 12;
2973
3273
  const isAllowedFieldSize = (type, size) => {
2974
- const { getFieldSize } = getService$1("field-sizes");
3274
+ const { getFieldSize } = getService$2("field-sizes");
2975
3275
  const fieldSize = getFieldSize(type);
2976
3276
  if (!fieldSize.isResizable && size !== fieldSize.default) {
2977
3277
  return false;
@@ -2979,7 +3279,7 @@ const isAllowedFieldSize = (type, size) => {
2979
3279
  return size <= MAX_ROW_SIZE;
2980
3280
  };
2981
3281
  const getDefaultFieldSize = (attribute) => {
2982
- const { hasFieldSize, getFieldSize } = getService$1("field-sizes");
3282
+ const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
2983
3283
  return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
2984
3284
  };
2985
3285
  async function createDefaultLayouts(schema) {
@@ -3000,8 +3300,7 @@ function createDefaultEditLayout(schema) {
3000
3300
  return appendToEditLayout([], keys2, schema);
3001
3301
  }
3002
3302
  function syncLayouts(configuration, schema) {
3003
- if (_.isEmpty(configuration.layouts))
3004
- return createDefaultLayouts(schema);
3303
+ if (_.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
3005
3304
  const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
3006
3305
  let cleanList = list.filter((attr) => isListable(schema, attr));
3007
3306
  const cleanEditRelations = editRelations.filter(
@@ -3012,9 +3311,8 @@ function syncLayouts(configuration, schema) {
3012
3311
  for (const row of edit) {
3013
3312
  const newRow = [];
3014
3313
  for (const el of row) {
3015
- if (!hasEditableAttribute(schema, el.name))
3016
- continue;
3017
- const { hasFieldSize } = getService$1("field-sizes");
3314
+ if (!hasEditableAttribute(schema, el.name)) continue;
3315
+ const { hasFieldSize } = getService$2("field-sizes");
3018
3316
  const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
3019
3317
  if (!isAllowedFieldSize(fieldType, el.size)) {
3020
3318
  elementsToReAppend.push(el.name);
@@ -3044,8 +3342,7 @@ function syncLayouts(configuration, schema) {
3044
3342
  };
3045
3343
  }
3046
3344
  const appendToEditLayout = (layout = [], keysToAppend, schema) => {
3047
- if (keysToAppend.length === 0)
3048
- return layout;
3345
+ if (keysToAppend.length === 0) return layout;
3049
3346
  let currentRowIndex = Math.max(layout.length - 1, 0);
3050
3347
  if (!layout[currentRowIndex]) {
3051
3348
  layout[currentRowIndex] = [];
@@ -3154,17 +3451,17 @@ const configurationService$1 = createConfigurationService({
3154
3451
  isComponent: true,
3155
3452
  prefix: STORE_KEY_PREFIX,
3156
3453
  getModels() {
3157
- const { toContentManagerModel } = getService$1("data-mapper");
3454
+ const { toContentManagerModel } = getService$2("data-mapper");
3158
3455
  return mapValues(toContentManagerModel, strapi.components);
3159
3456
  }
3160
3457
  });
3161
3458
  const components = ({ strapi: strapi2 }) => ({
3162
3459
  findAllComponents() {
3163
- const { toContentManagerModel } = getService$1("data-mapper");
3460
+ const { toContentManagerModel } = getService$2("data-mapper");
3164
3461
  return Object.values(strapi2.components).map(toContentManagerModel);
3165
3462
  },
3166
3463
  findComponent(uid2) {
3167
- const { toContentManagerModel } = getService$1("data-mapper");
3464
+ const { toContentManagerModel } = getService$2("data-mapper");
3168
3465
  const component = strapi2.components[uid2];
3169
3466
  return isNil$1(component) ? component : toContentManagerModel(component);
3170
3467
  },
@@ -3215,17 +3512,17 @@ const configurationService = createConfigurationService({
3215
3512
  storeUtils,
3216
3513
  prefix: "content_types",
3217
3514
  getModels() {
3218
- const { toContentManagerModel } = getService$1("data-mapper");
3515
+ const { toContentManagerModel } = getService$2("data-mapper");
3219
3516
  return mapValues(toContentManagerModel, strapi.contentTypes);
3220
3517
  }
3221
3518
  });
3222
3519
  const service = ({ strapi: strapi2 }) => ({
3223
3520
  findAllContentTypes() {
3224
- const { toContentManagerModel } = getService$1("data-mapper");
3521
+ const { toContentManagerModel } = getService$2("data-mapper");
3225
3522
  return Object.values(strapi2.contentTypes).map(toContentManagerModel);
3226
3523
  },
3227
3524
  findContentType(uid2) {
3228
- const { toContentManagerModel } = getService$1("data-mapper");
3525
+ const { toContentManagerModel } = getService$2("data-mapper");
3229
3526
  const contentType = strapi2.contentTypes[uid2];
3230
3527
  return isNil$1(contentType) ? contentType : toContentManagerModel(contentType);
3231
3528
  },
@@ -3254,7 +3551,7 @@ const service = ({ strapi: strapi2 }) => ({
3254
3551
  return this.findConfiguration(contentType);
3255
3552
  },
3256
3553
  findComponentsConfigurations(contentType) {
3257
- return getService$1("components").findComponentsConfigurations(contentType);
3554
+ return getService$2("components").findComponentsConfigurations(contentType);
3258
3555
  },
3259
3556
  syncConfigurations() {
3260
3557
  return configurationService.syncConfigurations();
@@ -3435,12 +3732,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
3435
3732
  ability: userAbility,
3436
3733
  model
3437
3734
  });
3438
- const toSubject = (entity) => entity ? permissionsManager.toSubject(entity, model) : model;
3735
+ const { actionProvider } = strapi2.service("admin::permission");
3736
+ const toSubject = (entity) => {
3737
+ return entity ? permissionsManager.toSubject(entity, model) : model;
3738
+ };
3439
3739
  const can = (action, entity, field) => {
3440
- return userAbility.can(action, toSubject(entity), field);
3740
+ const subject = toSubject(entity);
3741
+ const aliases = actionProvider.unstable_aliases(action, model);
3742
+ return (
3743
+ // Test the original action to see if it passes
3744
+ userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
3745
+ aliases.some((alias) => userAbility.can(alias, subject, field))
3746
+ );
3441
3747
  };
3442
3748
  const cannot = (action, entity, field) => {
3443
- return userAbility.cannot(action, toSubject(entity), field);
3749
+ const subject = toSubject(entity);
3750
+ const aliases = actionProvider.unstable_aliases(action, model);
3751
+ return (
3752
+ // Test both the original action
3753
+ userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
3754
+ aliases.every((alias) => userAbility.cannot(alias, subject, field))
3755
+ );
3444
3756
  };
3445
3757
  const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
3446
3758
  return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
@@ -3511,7 +3823,7 @@ const permission = ({ strapi: strapi2 }) => ({
3511
3823
  return userAbility.can(action);
3512
3824
  },
3513
3825
  async registerPermissions() {
3514
- const displayedContentTypes = getService$1("content-types").findDisplayedContentTypes();
3826
+ const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
3515
3827
  const contentTypesUids = displayedContentTypes.map(prop("uid"));
3516
3828
  const actions = [
3517
3829
  {
@@ -3717,6 +4029,10 @@ const getDeepPopulateDraftCount = (uid2) => {
3717
4029
  const attribute = model.attributes[attributeName];
3718
4030
  switch (attribute.type) {
3719
4031
  case "relation": {
4032
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
4033
+ if (isMorphRelation) {
4034
+ break;
4035
+ }
3720
4036
  if (isVisibleAttribute$1(model, attributeName)) {
3721
4037
  populateAcc[attributeName] = {
3722
4038
  count: true,
@@ -3783,7 +4099,7 @@ const getQueryPopulate = async (uid2, query) => {
3783
4099
  return populateQuery;
3784
4100
  };
3785
4101
  const buildDeepPopulate = (uid2) => {
3786
- return getService$1("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
4102
+ return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
3787
4103
  };
3788
4104
  const populateBuilder = (uid2) => {
3789
4105
  let getInitialPopulate = async () => {
@@ -3968,7 +4284,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3968
4284
  */
3969
4285
  async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
3970
4286
  const versionsByLocale = groupBy("locale", allVersions);
3971
- delete versionsByLocale[version.locale];
4287
+ if (version.locale) {
4288
+ delete versionsByLocale[version.locale];
4289
+ }
3972
4290
  const model = strapi2.getModel(uid2);
3973
4291
  const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
3974
4292
  const traversalFunction = async (localeVersion) => traverseEntity(
@@ -4015,8 +4333,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4015
4333
  const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
4016
4334
  return matchLocale && matchStatus;
4017
4335
  });
4018
- if (!availableStatus)
4019
- return availableStatus;
4336
+ if (!availableStatus) return availableStatus;
4020
4337
  return pick(AVAILABLE_STATUS_FIELDS, availableStatus);
4021
4338
  },
4022
4339
  /**
@@ -4026,8 +4343,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4026
4343
  * @returns
4027
4344
  */
4028
4345
  async getManyAvailableStatus(uid2, documents) {
4029
- if (!documents.length)
4030
- return [];
4346
+ if (!documents.length) return [];
4031
4347
  const status = documents[0].publishedAt !== null ? "published" : "draft";
4032
4348
  const locale = documents[0]?.locale;
4033
4349
  const otherStatus = status === "published" ? "draft" : "published";
@@ -4054,10 +4370,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4054
4370
  } else if (otherVersion) {
4055
4371
  draftVersion = otherVersion;
4056
4372
  }
4057
- if (!draftVersion)
4058
- return CONTENT_MANAGER_STATUS.PUBLISHED;
4059
- if (!publishedVersion)
4060
- return CONTENT_MANAGER_STATUS.DRAFT;
4373
+ if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
4374
+ if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
4061
4375
  const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
4062
4376
  return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
4063
4377
  },
@@ -4094,7 +4408,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4094
4408
  */
4095
4409
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
4096
4410
  if (!document) {
4097
- return document;
4411
+ return {
4412
+ data: document,
4413
+ meta: {
4414
+ availableLocales: [],
4415
+ availableStatus: []
4416
+ }
4417
+ };
4098
4418
  }
4099
4419
  const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
4100
4420
  if (!hasDraftAndPublish) {
@@ -4202,10 +4522,7 @@ const documentManager = ({ strapi: strapi2 }) => {
4202
4522
  async clone(id, body, uid2) {
4203
4523
  const populate = await buildDeepPopulate(uid2);
4204
4524
  const params = {
4205
- data: {
4206
- ...omitIdField(body),
4207
- [PUBLISHED_AT_ATTRIBUTE]: null
4208
- },
4525
+ data: omitIdField(body),
4209
4526
  populate
4210
4527
  };
4211
4528
  return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
@@ -4321,7 +4638,8 @@ const services = {
4321
4638
  permission,
4322
4639
  "populate-builder": populateBuilder$1,
4323
4640
  uid,
4324
- ...history.services ? history.services : {}
4641
+ ...history.services ? history.services : {},
4642
+ ...preview.services ? preview.services : {}
4325
4643
  };
4326
4644
  const index = () => {
4327
4645
  return {