@strapi/content-manager 0.0.0-experimental.d53e940834bf72ddc725f1d2fd36dac9abec30cb → 0.0.0-experimental.d6bba97c7ed8309e57888e84d4788fa279d473fd

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 (220) 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-DmwmiFQy.mjs → ComponentConfigurationPage-D4J64ny7.mjs} +4 -4
  5. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-D4J64ny7.mjs.map} +1 -1
  6. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-DHV8IFbd.js} +5 -6
  7. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-DHV8IFbd.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-JT3E7NZy.mjs → EditConfigurationPage-DMnf8orh.mjs} +4 -4
  12. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-DMnf8orh.mjs.map} +1 -1
  13. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-q76oeVU1.js} +5 -6
  14. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-q76oeVU1.js.map} +1 -1
  15. package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-BXoY-ITh.js} +63 -13
  16. package/dist/_chunks/EditViewPage-BXoY-ITh.js.map +1 -0
  17. package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-COVXj9bh.mjs} +63 -12
  18. package/dist/_chunks/EditViewPage-COVXj9bh.mjs.map +1 -0
  19. package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-CcppsFQR.mjs} +300 -203
  20. package/dist/_chunks/Field-CcppsFQR.mjs.map +1 -0
  21. package/dist/_chunks/{Field-Boxf9Ajp.js → Field-Dj1nOvt8.js} +303 -207
  22. package/dist/_chunks/Field-Dj1nOvt8.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-DHrru2AV.mjs → Form-DbWwH0-A.mjs} +37 -18
  26. package/dist/_chunks/Form-DbWwH0-A.mjs.map +1 -0
  27. package/dist/_chunks/{Form-y5g1SRsh.js → Form-aTchNxab.js} +39 -21
  28. package/dist/_chunks/Form-aTchNxab.js.map +1 -0
  29. package/dist/_chunks/{History-CqN6K7SX.js → History-Cs6XM6EU.js} +81 -114
  30. package/dist/_chunks/History-Cs6XM6EU.js.map +1 -0
  31. package/dist/_chunks/{History-Bru_KoeP.mjs → History-tU567_hc.mjs} +82 -114
  32. package/dist/_chunks/History-tU567_hc.mjs.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-7LeytuFD.js} +25 -13
  34. package/dist/_chunks/ListConfigurationPage-7LeytuFD.js.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-DQryo_4i.mjs} +25 -12
  36. package/dist/_chunks/ListConfigurationPage-DQryo_4i.mjs.map +1 -0
  37. package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-B50esy_x.mjs} +118 -77
  38. package/dist/_chunks/ListViewPage-B50esy_x.mjs.map +1 -0
  39. package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-CaGBu5H5.js} +121 -81
  40. package/dist/_chunks/ListViewPage-CaGBu5H5.js.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-BaBE00IO.js} +2 -2
  42. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-BaBE00IO.js.map} +1 -1
  43. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-CiPP8cLx.mjs} +2 -2
  44. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-CiPP8cLx.mjs.map} +1 -1
  45. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-0-CW106p.mjs} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-0-CW106p.mjs.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-DQn5cqZz.js} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-DQn5cqZz.js.map} +1 -1
  49. package/dist/_chunks/Preview-C1dBkhXf.mjs +272 -0
  50. package/dist/_chunks/Preview-C1dBkhXf.mjs.map +1 -0
  51. package/dist/_chunks/Preview-DH1h7kJ6.js +290 -0
  52. package/dist/_chunks/Preview-DH1h7kJ6.js.map +1 -0
  53. package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-Bvne4TvU.mjs} +76 -42
  54. package/dist/_chunks/Relations-Bvne4TvU.mjs.map +1 -0
  55. package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-CkECnBOd.js} +76 -43
  56. package/dist/_chunks/Relations-CkECnBOd.js.map +1 -0
  57. package/dist/_chunks/{en-fbKQxLGn.js → en-BK8Xyl5I.js} +32 -18
  58. package/dist/_chunks/{en-fbKQxLGn.js.map → en-BK8Xyl5I.js.map} +1 -1
  59. package/dist/_chunks/{en-Ux26r5pl.mjs → en-Dtk_ot79.mjs} +32 -18
  60. package/dist/_chunks/{en-Ux26r5pl.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-DVPWZkbS.js → index-BN1pPa5v.js} +1135 -693
  71. package/dist/_chunks/index-BN1pPa5v.js.map +1 -0
  72. package/dist/_chunks/{index-DJXJw9V5.mjs → index-ByPZ754U.mjs} +1156 -714
  73. package/dist/_chunks/index-ByPZ754U.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-Bau7ZfLV.mjs → layout-CUTOYU8I.mjs} +26 -13
  79. package/dist/_chunks/layout-CUTOYU8I.mjs.map +1 -0
  80. package/dist/_chunks/{layout-Dm6fbiQj.js → layout-nBPDlXjr.js} +26 -14
  81. package/dist/_chunks/layout-nBPDlXjr.js.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-CKnpRgrN.js → relations-B6B-b7lI.js} +6 -7
  87. package/dist/_chunks/relations-B6B-b7lI.js.map +1 -0
  88. package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-CBc5HYHC.mjs} +6 -7
  89. package/dist/_chunks/relations-CBc5HYHC.mjs.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 +5 -4
  101. package/dist/admin/src/content-manager.d.ts +3 -2
  102. package/dist/admin/src/exports.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 +2 -1
  109. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
  110. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  111. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  112. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  113. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  114. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  115. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  116. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  117. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  118. package/dist/admin/src/preview/constants.d.ts +1 -0
  119. package/dist/admin/src/preview/index.d.ts +4 -0
  120. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  121. package/dist/admin/src/preview/routes.d.ts +3 -0
  122. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  123. package/dist/admin/src/router.d.ts +1 -1
  124. package/dist/admin/src/services/api.d.ts +1 -1
  125. package/dist/admin/src/services/components.d.ts +2 -2
  126. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  127. package/dist/admin/src/services/documents.d.ts +19 -20
  128. package/dist/admin/src/services/init.d.ts +1 -1
  129. package/dist/admin/src/services/relations.d.ts +2 -2
  130. package/dist/admin/src/services/uid.d.ts +3 -3
  131. package/dist/admin/src/utils/validation.d.ts +4 -1
  132. package/dist/server/index.js +615 -299
  133. package/dist/server/index.js.map +1 -1
  134. package/dist/server/index.mjs +615 -298
  135. package/dist/server/index.mjs.map +1 -1
  136. package/dist/server/src/bootstrap.d.ts.map +1 -1
  137. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  138. package/dist/server/src/controllers/index.d.ts.map +1 -1
  139. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  140. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  141. package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
  142. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  143. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  144. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  145. package/dist/server/src/history/services/history.d.ts.map +1 -1
  146. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  147. package/dist/server/src/history/services/utils.d.ts +4 -4
  148. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  149. package/dist/server/src/index.d.ts +4 -4
  150. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  151. package/dist/server/src/preview/constants.d.ts +2 -0
  152. package/dist/server/src/preview/constants.d.ts.map +1 -0
  153. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  154. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  155. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  156. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  157. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  158. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  159. package/dist/server/src/preview/index.d.ts +4 -0
  160. package/dist/server/src/preview/index.d.ts.map +1 -0
  161. package/dist/server/src/preview/routes/index.d.ts +8 -0
  162. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  163. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  164. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  165. package/dist/server/src/preview/services/index.d.ts +16 -0
  166. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  167. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  168. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  169. package/dist/server/src/preview/services/preview.d.ts +12 -0
  170. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  171. package/dist/server/src/preview/utils.d.ts +19 -0
  172. package/dist/server/src/preview/utils.d.ts.map +1 -0
  173. package/dist/server/src/register.d.ts.map +1 -1
  174. package/dist/server/src/routes/index.d.ts.map +1 -1
  175. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  176. package/dist/server/src/services/document-metadata.d.ts +8 -8
  177. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  178. package/dist/server/src/services/index.d.ts +4 -4
  179. package/dist/server/src/services/index.d.ts.map +1 -1
  180. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  181. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  182. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  183. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  184. package/dist/server/src/utils/index.d.ts +2 -0
  185. package/dist/server/src/utils/index.d.ts.map +1 -1
  186. package/dist/shared/contracts/collection-types.d.ts +3 -1
  187. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  188. package/dist/shared/contracts/index.d.ts +1 -0
  189. package/dist/shared/contracts/index.d.ts.map +1 -1
  190. package/dist/shared/contracts/preview.d.ts +27 -0
  191. package/dist/shared/contracts/preview.d.ts.map +1 -0
  192. package/dist/shared/index.js +4 -0
  193. package/dist/shared/index.js.map +1 -1
  194. package/dist/shared/index.mjs +4 -0
  195. package/dist/shared/index.mjs.map +1 -1
  196. package/package.json +15 -15
  197. package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
  198. package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
  199. package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
  200. package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
  201. package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
  202. package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
  203. package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
  204. package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
  205. package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
  206. package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
  207. package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
  208. package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
  209. package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
  210. package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
  211. package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
  212. package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
  213. package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
  214. package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
  215. package/dist/_chunks/relations-BH_kBSJ0.mjs.map +0 -1
  216. package/dist/_chunks/relations-CKnpRgrN.js.map +0 -1
  217. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  218. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  219. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  220. package/strapi-server.js +0 -3
@@ -10,8 +10,7 @@ const qs = require("qs");
10
10
  const slugify = require("@sindresorhus/slugify");
11
11
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
12
12
  function _interopNamespace(e) {
13
- if (e && e.__esModule)
14
- return e;
13
+ if (e && e.__esModule) return e;
15
14
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
16
15
  if (e) {
17
16
  for (const k in e) {
@@ -33,10 +32,10 @@ const isNil__default = /* @__PURE__ */ _interopDefault(isNil);
33
32
  const ___default = /* @__PURE__ */ _interopDefault(_);
34
33
  const qs__default = /* @__PURE__ */ _interopDefault(qs);
35
34
  const slugify__default = /* @__PURE__ */ _interopDefault(slugify);
36
- const getService$1 = (name) => {
35
+ const getService$2 = (name) => {
37
36
  return strapi.plugin("content-manager").service(name);
38
37
  };
39
- function getService(strapi2, name) {
38
+ function getService$1(strapi2, name) {
40
39
  return strapi2.service(`plugin::content-manager.${name}`);
41
40
  }
42
41
  const historyRestoreVersionSchema = yup__namespace.object().shape({
@@ -72,7 +71,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
72
71
  if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
73
72
  throw new strapiUtils.errors.ForbiddenError("contentType and documentId are required");
74
73
  }
75
- const permissionChecker2 = getService$1("permission-checker").create({
74
+ const permissionChecker2 = getService$2("permission-checker").create({
76
75
  userAbility: ctx.state.userAbility,
77
76
  model: ctx.query.contentType
78
77
  });
@@ -80,7 +79,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
80
79
  return ctx.forbidden();
81
80
  }
82
81
  const query = await permissionChecker2.sanitizeQuery(ctx.query);
83
- const { results, pagination } = await getService(strapi2, "history").findVersionsPage({
82
+ const { results, pagination } = await getService$1(strapi2, "history").findVersionsPage({
84
83
  query: {
85
84
  ...query,
86
85
  ...getValidPagination({ page: query.page, pageSize: query.pageSize })
@@ -105,14 +104,14 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
105
104
  async restoreVersion(ctx) {
106
105
  const request = ctx.request;
107
106
  await validateRestoreVersion(request.body, "contentType is required");
108
- const permissionChecker2 = getService$1("permission-checker").create({
107
+ const permissionChecker2 = getService$2("permission-checker").create({
109
108
  userAbility: ctx.state.userAbility,
110
109
  model: request.body.contentType
111
110
  });
112
111
  if (permissionChecker2.cannot.update()) {
113
112
  throw new strapiUtils.errors.ForbiddenError();
114
113
  }
115
- const restoredDocument = await getService(strapi2, "history").restoreVersion(
114
+ const restoredDocument = await getService$1(strapi2, "history").restoreVersion(
116
115
  request.params.versionId
117
116
  );
118
117
  return {
@@ -121,7 +120,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
121
120
  }
122
121
  };
123
122
  };
124
- const controllers$1 = {
123
+ const controllers$2 = {
125
124
  "history-version": createHistoryVersionController
126
125
  /**
127
126
  * Casting is needed because the types aren't aware that Strapi supports
@@ -167,8 +166,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
167
166
  };
168
167
  const getRelationRestoreValue = async (versionRelationData, attribute) => {
169
168
  if (Array.isArray(versionRelationData)) {
170
- if (versionRelationData.length === 0)
171
- return versionRelationData;
169
+ if (versionRelationData.length === 0) return versionRelationData;
172
170
  const existingAndMissingRelations = await Promise.all(
173
171
  versionRelationData.map((relation) => {
174
172
  return strapi2.documents(attribute.target).findOne({
@@ -199,10 +197,11 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
199
197
  return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
200
198
  };
201
199
  const localesService = strapi2.plugin("i18n")?.service("locales");
200
+ const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
202
201
  const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
202
+ const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
203
203
  const getLocaleDictionary = async () => {
204
- if (!localesService)
205
- return {};
204
+ if (!localesService) return {};
206
205
  const locales = await localesService.find() || [];
207
206
  return locales.reduce(
208
207
  (acc, locale) => {
@@ -226,31 +225,53 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
226
225
  const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
227
226
  return documentMetadataService.getStatus(document, meta.availableStatus);
228
227
  };
229
- const getDeepPopulate2 = (uid2) => {
228
+ const getComponentFields = (componentUID) => {
229
+ return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
230
+ (fieldsAcc, [key, attribute]) => {
231
+ if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
232
+ fieldsAcc.push(key);
233
+ }
234
+ return fieldsAcc;
235
+ },
236
+ []
237
+ );
238
+ };
239
+ const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
230
240
  const model = strapi2.getModel(uid2);
231
241
  const attributes = Object.entries(model.attributes);
242
+ const fieldSelector = useDatabaseSyntax ? "select" : "fields";
232
243
  return attributes.reduce((acc, [attributeName, attribute]) => {
233
244
  switch (attribute.type) {
234
245
  case "relation": {
246
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
247
+ if (isMorphRelation) {
248
+ break;
249
+ }
235
250
  const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
236
251
  if (isVisible2) {
237
- acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
252
+ acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
238
253
  }
239
254
  break;
240
255
  }
241
256
  case "media": {
242
- acc[attributeName] = { fields: ["id"] };
257
+ acc[attributeName] = { [fieldSelector]: ["id"] };
243
258
  break;
244
259
  }
245
260
  case "component": {
246
261
  const populate = getDeepPopulate2(attribute.component);
247
- acc[attributeName] = { populate };
262
+ acc[attributeName] = {
263
+ populate,
264
+ [fieldSelector]: getComponentFields(attribute.component)
265
+ };
248
266
  break;
249
267
  }
250
268
  case "dynamiczone": {
251
269
  const populatedComponents = (attribute.components || []).reduce(
252
270
  (acc2, componentUID) => {
253
- acc2[componentUID] = { populate: getDeepPopulate2(componentUID) };
271
+ acc2[componentUID] = {
272
+ populate: getDeepPopulate2(componentUID),
273
+ [fieldSelector]: getComponentFields(componentUID)
274
+ };
254
275
  return acc2;
255
276
  },
256
277
  {}
@@ -312,6 +333,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
312
333
  getRelationRestoreValue,
313
334
  getMediaRestoreValue,
314
335
  getDefaultLocale,
336
+ isLocalizedContentType,
315
337
  getLocaleDictionary,
316
338
  getRetentionDays,
317
339
  getVersionStatus,
@@ -334,7 +356,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
334
356
  });
335
357
  },
336
358
  async findVersionsPage(params) {
337
- const locale = params.query.locale || await serviceUtils.getDefaultLocale();
359
+ const model = strapi2.getModel(params.query.contentType);
360
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
361
+ const defaultLocale = await serviceUtils.getDefaultLocale();
362
+ let locale = null;
363
+ if (isLocalizedContentType) {
364
+ locale = params.query.locale || defaultLocale;
365
+ }
338
366
  const [{ results, pagination }, localeDictionary] = await Promise.all([
339
367
  query.findPage({
340
368
  ...params.query,
@@ -356,7 +384,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
356
384
  const attributeValue = entry.data[attributeKey];
357
385
  const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
358
386
  if (attributeSchema.type === "media") {
359
- const permissionChecker2 = getService$1("permission-checker").create({
387
+ const permissionChecker2 = getService$2("permission-checker").create({
360
388
  userAbility: params.state.userAbility,
361
389
  model: "plugin::upload.file"
362
390
  });
@@ -379,7 +407,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
379
407
  if (userToPopulate == null) {
380
408
  return null;
381
409
  }
382
- return strapi2.query("admin::user").findOne({ where: { id: userToPopulate.id } });
410
+ return strapi2.query("admin::user").findOne({
411
+ where: {
412
+ ...userToPopulate.id ? { id: userToPopulate.id } : {},
413
+ ...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
414
+ }
415
+ });
383
416
  })
384
417
  );
385
418
  return {
@@ -392,7 +425,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
392
425
  [attributeKey]: adminUsers
393
426
  };
394
427
  }
395
- const permissionChecker2 = getService$1("permission-checker").create({
428
+ const permissionChecker2 = getService$2("permission-checker").create({
396
429
  userAbility: params.state.userAbility,
397
430
  model: attributeSchema.target
398
431
  });
@@ -490,6 +523,42 @@ const createHistoryService = ({ strapi: strapi2 }) => {
490
523
  }
491
524
  };
492
525
  };
526
+ const shouldCreateHistoryVersion = (context) => {
527
+ if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
528
+ return false;
529
+ }
530
+ if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
531
+ return false;
532
+ }
533
+ if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
534
+ return false;
535
+ }
536
+ if (!context.contentType.uid.startsWith("api::")) {
537
+ return false;
538
+ }
539
+ return true;
540
+ };
541
+ const getSchemas = (uid2) => {
542
+ const attributesSchema = strapi.getModel(uid2).attributes;
543
+ const componentsSchemas = Object.keys(attributesSchema).reduce(
544
+ (currentComponentSchemas, key) => {
545
+ const fieldSchema = attributesSchema[key];
546
+ if (fieldSchema.type === "component") {
547
+ const componentSchema = strapi.getModel(fieldSchema.component).attributes;
548
+ return {
549
+ ...currentComponentSchemas,
550
+ [fieldSchema.component]: componentSchema
551
+ };
552
+ }
553
+ return currentComponentSchemas;
554
+ },
555
+ {}
556
+ );
557
+ return {
558
+ schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
559
+ componentsSchemas
560
+ };
561
+ };
493
562
  const createLifecyclesService = ({ strapi: strapi2 }) => {
494
563
  const state = {
495
564
  deleteExpiredJob: null,
@@ -502,76 +571,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
502
571
  return;
503
572
  }
504
573
  strapi2.documents.use(async (context, next) => {
505
- if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
506
- return next();
507
- }
508
- if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
509
- return next();
510
- }
511
- if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
512
- return next();
513
- }
514
- const contentTypeUid = context.contentType.uid;
515
- if (!contentTypeUid.startsWith("api::")) {
516
- return next();
517
- }
518
574
  const result = await next();
519
- const documentContext = {
520
- documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
521
- locale: context.params?.locale
522
- };
575
+ if (!shouldCreateHistoryVersion(context)) {
576
+ return result;
577
+ }
578
+ const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
523
579
  const defaultLocale = await serviceUtils.getDefaultLocale();
524
- const locale = documentContext.locale || defaultLocale;
525
- if (Array.isArray(locale)) {
526
- strapi2.log.warn(
527
- "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
528
- );
529
- return next();
580
+ const locales = fp.castArray(context.params?.locale || defaultLocale);
581
+ if (!locales.length) {
582
+ return result;
530
583
  }
531
- const document = await strapi2.documents(contentTypeUid).findOne({
532
- documentId: documentContext.documentId,
533
- locale,
534
- populate: serviceUtils.getDeepPopulate(contentTypeUid)
584
+ const uid2 = context.contentType.uid;
585
+ const schemas = getSchemas(uid2);
586
+ const model = strapi2.getModel(uid2);
587
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
588
+ const localeEntries = await strapi2.db.query(uid2).findMany({
589
+ where: {
590
+ documentId,
591
+ ...isLocalizedContentType ? { locale: { $in: locales } } : {},
592
+ ...strapiUtils.contentTypes.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
593
+ },
594
+ populate: serviceUtils.getDeepPopulate(
595
+ uid2,
596
+ true
597
+ /* use database syntax */
598
+ )
535
599
  });
536
- const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
537
- const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
538
- const componentsSchemas = Object.keys(
539
- attributesSchema
540
- ).reduce((currentComponentSchemas, key) => {
541
- const fieldSchema = attributesSchema[key];
542
- if (fieldSchema.type === "component") {
543
- const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
544
- return {
545
- ...currentComponentSchemas,
546
- [fieldSchema.component]: componentSchema
547
- };
548
- }
549
- return currentComponentSchemas;
550
- }, {});
551
600
  await strapi2.db.transaction(async ({ onCommit }) => {
552
- onCommit(() => {
553
- getService(strapi2, "history").createVersion({
554
- contentType: contentTypeUid,
555
- data: fp.omit(FIELDS_TO_IGNORE, document),
556
- schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
557
- componentsSchemas,
558
- relatedDocumentId: documentContext.documentId,
559
- locale,
560
- status
561
- });
601
+ onCommit(async () => {
602
+ for (const entry of localeEntries) {
603
+ const status = await serviceUtils.getVersionStatus(uid2, entry);
604
+ await getService$1(strapi2, "history").createVersion({
605
+ contentType: uid2,
606
+ data: fp.omit(FIELDS_TO_IGNORE, entry),
607
+ relatedDocumentId: documentId,
608
+ locale: entry.locale,
609
+ status,
610
+ ...schemas
611
+ });
612
+ }
562
613
  });
563
614
  });
564
615
  return result;
565
616
  });
566
- state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
617
+ state.deleteExpiredJob = nodeSchedule.scheduleJob("historyDaily", "0 0 * * *", () => {
567
618
  const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
568
619
  const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
569
620
  strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
570
621
  where: {
571
622
  created_at: {
572
- $lt: expirationDate.toISOString()
623
+ $lt: expirationDate
573
624
  }
574
625
  }
626
+ }).catch((error) => {
627
+ if (error instanceof Error) {
628
+ strapi2.log.error("Error deleting expired history versions", error.message);
629
+ }
575
630
  });
576
631
  });
577
632
  state.isInitialized = true;
@@ -583,17 +638,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
583
638
  }
584
639
  };
585
640
  };
586
- const services$1 = {
641
+ const services$2 = {
587
642
  history: createHistoryService,
588
643
  lifecycles: createLifecyclesService
589
644
  };
590
- const info = { pluginName: "content-manager", type: "admin" };
645
+ const info$1 = { pluginName: "content-manager", type: "admin" };
591
646
  const historyVersionRouter = {
592
647
  type: "admin",
593
648
  routes: [
594
649
  {
595
650
  method: "GET",
596
- info,
651
+ info: info$1,
597
652
  path: "/history-versions",
598
653
  handler: "history-version.findMany",
599
654
  config: {
@@ -602,7 +657,7 @@ const historyVersionRouter = {
602
657
  },
603
658
  {
604
659
  method: "PUT",
605
- info,
660
+ info: info$1,
606
661
  path: "/history-versions/:versionId/restore",
607
662
  handler: "history-version.restoreVersion",
608
663
  config: {
@@ -611,7 +666,7 @@ const historyVersionRouter = {
611
666
  }
612
667
  ]
613
668
  };
614
- const routes$1 = {
669
+ const routes$2 = {
615
670
  "history-version": historyVersionRouter
616
671
  };
617
672
  const historyVersion = {
@@ -658,21 +713,21 @@ const historyVersion = {
658
713
  }
659
714
  }
660
715
  };
661
- const getFeature = () => {
716
+ const getFeature$1 = () => {
662
717
  if (strapi.ee.features.isEnabled("cms-content-history")) {
663
718
  return {
664
719
  register({ strapi: strapi2 }) {
665
720
  strapi2.get("models").add(historyVersion);
666
721
  },
667
722
  bootstrap({ strapi: strapi2 }) {
668
- getService(strapi2, "lifecycles").bootstrap();
723
+ getService$1(strapi2, "lifecycles").bootstrap();
669
724
  },
670
725
  destroy({ strapi: strapi2 }) {
671
- getService(strapi2, "lifecycles").destroy();
726
+ getService$1(strapi2, "lifecycles").destroy();
672
727
  },
673
- controllers: controllers$1,
674
- services: services$1,
675
- routes: routes$1
728
+ controllers: controllers$2,
729
+ services: services$2,
730
+ routes: routes$2
676
731
  };
677
732
  }
678
733
  return {
@@ -681,9 +736,205 @@ const getFeature = () => {
681
736
  }
682
737
  };
683
738
  };
684
- const history = getFeature();
739
+ const history = getFeature$1();
740
+ const FEATURE_ID = "preview";
741
+ const info = { pluginName: "content-manager", type: "admin" };
742
+ const previewRouter = {
743
+ type: "admin",
744
+ routes: [
745
+ {
746
+ method: "GET",
747
+ info,
748
+ path: "/preview/url/:contentType",
749
+ handler: "preview.getPreviewUrl",
750
+ config: {
751
+ policies: ["admin::isAuthenticatedAdmin"]
752
+ }
753
+ }
754
+ ]
755
+ };
756
+ const routes$1 = {
757
+ preview: previewRouter
758
+ };
759
+ function getService(strapi2, name) {
760
+ return strapi2.service(`plugin::content-manager.${name}`);
761
+ }
762
+ const getPreviewUrlSchema = yup__namespace.object().shape({
763
+ // Will be undefined for single types
764
+ documentId: yup__namespace.string(),
765
+ locale: yup__namespace.string().nullable(),
766
+ status: yup__namespace.string()
767
+ }).required();
768
+ const validatePreviewUrl = async (strapi2, uid2, params) => {
769
+ await strapiUtils.validateYupSchema(getPreviewUrlSchema)(params);
770
+ const newParams = fp.pick(["documentId", "locale", "status"], params);
771
+ const model = strapi2.getModel(uid2);
772
+ if (!model || model.modelType !== "contentType") {
773
+ throw new strapiUtils.errors.ValidationError("Invalid content type");
774
+ }
775
+ const isSingleType = model?.kind === "singleType";
776
+ if (!isSingleType && !params.documentId) {
777
+ throw new strapiUtils.errors.ValidationError("documentId is required for Collection Types");
778
+ }
779
+ if (isSingleType) {
780
+ const doc = await strapi2.documents(uid2).findFirst();
781
+ if (!doc) {
782
+ throw new strapiUtils.errors.NotFoundError("Document not found");
783
+ }
784
+ newParams.documentId = doc?.documentId;
785
+ }
786
+ if (!newParams.status) {
787
+ const isDPEnabled = model?.options?.draftAndPublish;
788
+ newParams.status = isDPEnabled ? "draft" : "published";
789
+ }
790
+ return newParams;
791
+ };
792
+ const createPreviewController = () => {
793
+ return {
794
+ /**
795
+ * Transforms an entry into a preview URL, so that it can be previewed
796
+ * in the Content Manager.
797
+ */
798
+ async getPreviewUrl(ctx) {
799
+ const uid2 = ctx.params.contentType;
800
+ const query = ctx.request.query;
801
+ const params = await validatePreviewUrl(strapi, uid2, query);
802
+ const previewService = getService(strapi, "preview");
803
+ const url = await previewService.getPreviewUrl(uid2, params);
804
+ if (!url) {
805
+ ctx.status = 204;
806
+ }
807
+ return {
808
+ data: { url }
809
+ };
810
+ }
811
+ };
812
+ };
813
+ const controllers$1 = {
814
+ preview: createPreviewController
815
+ /**
816
+ * Casting is needed because the types aren't aware that Strapi supports
817
+ * passing a controller factory as the value, instead of a controller object directly
818
+ */
819
+ };
820
+ const createPreviewService = ({ strapi: strapi2 }) => {
821
+ const config = getService(strapi2, "preview-config");
822
+ return {
823
+ async getPreviewUrl(uid2, params) {
824
+ const handler = config.getPreviewHandler();
825
+ try {
826
+ return handler(uid2, params);
827
+ } catch (error) {
828
+ strapi2.log.error(`Failed to get preview URL: ${error}`);
829
+ throw new strapiUtils.errors.ApplicationError("Failed to get preview URL");
830
+ }
831
+ return;
832
+ }
833
+ };
834
+ };
835
+ const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
836
+ const middlewares = strapi.config.get("middlewares");
837
+ const configuredMiddlewares = middlewares.map((currentMiddleware) => {
838
+ if (currentMiddleware === middleware.name) {
839
+ return middleware;
840
+ }
841
+ if (currentMiddleware.name === middleware.name) {
842
+ return fp.mergeWith(
843
+ (objValue, srcValue) => {
844
+ if (Array.isArray(objValue)) {
845
+ return objValue.concat(srcValue);
846
+ }
847
+ return void 0;
848
+ },
849
+ currentMiddleware,
850
+ middleware
851
+ );
852
+ }
853
+ return currentMiddleware;
854
+ });
855
+ strapi.config.set("middlewares", configuredMiddlewares);
856
+ };
857
+ const createPreviewConfigService = ({ strapi: strapi2 }) => {
858
+ return {
859
+ register() {
860
+ if (!this.isEnabled()) {
861
+ return;
862
+ }
863
+ const config = strapi2.config.get("admin.preview");
864
+ if (config.config?.allowedOrigins) {
865
+ extendMiddlewareConfiguration({
866
+ name: "strapi::security",
867
+ config: {
868
+ contentSecurityPolicy: {
869
+ directives: {
870
+ "frame-src": config.config.allowedOrigins
871
+ }
872
+ }
873
+ }
874
+ });
875
+ }
876
+ },
877
+ isEnabled() {
878
+ const config = strapi2.config.get("admin.preview");
879
+ if (!config) {
880
+ return false;
881
+ }
882
+ return config?.enabled ?? true;
883
+ },
884
+ /**
885
+ * Validate if the configuration is valid
886
+ */
887
+ validate() {
888
+ if (!this.isEnabled()) {
889
+ return;
890
+ }
891
+ const handler = this.getPreviewHandler();
892
+ if (typeof handler !== "function") {
893
+ throw new strapiUtils.errors.ValidationError(
894
+ "Preview configuration is invalid. Handler must be a function"
895
+ );
896
+ }
897
+ },
898
+ /**
899
+ * Utility to get the preview handler from the configuration
900
+ */
901
+ getPreviewHandler() {
902
+ const config = strapi2.config.get("admin.preview");
903
+ const emptyHandler = () => {
904
+ return void 0;
905
+ };
906
+ if (!this.isEnabled()) {
907
+ return emptyHandler;
908
+ }
909
+ return config?.config?.handler || emptyHandler;
910
+ }
911
+ };
912
+ };
913
+ const services$1 = {
914
+ preview: createPreviewService,
915
+ "preview-config": createPreviewConfigService
916
+ };
917
+ const getFeature = () => {
918
+ if (!strapi.features.future.isEnabled(FEATURE_ID)) {
919
+ return {};
920
+ }
921
+ return {
922
+ register() {
923
+ const config = getService(strapi, "preview-config");
924
+ config.validate();
925
+ config.register();
926
+ },
927
+ bootstrap() {
928
+ },
929
+ routes: routes$1,
930
+ controllers: controllers$1,
931
+ services: services$1
932
+ };
933
+ };
934
+ const preview = getFeature();
685
935
  const register = async ({ strapi: strapi2 }) => {
686
936
  await history.register?.({ strapi: strapi2 });
937
+ await preview.register?.({ strapi: strapi2 });
687
938
  };
688
939
  const ALLOWED_WEBHOOK_EVENTS = {
689
940
  ENTRY_PUBLISH: "entry.publish",
@@ -693,11 +944,12 @@ const bootstrap = async () => {
693
944
  Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
694
945
  strapi.get("webhookStore").addAllowedEvent(key, value);
695
946
  });
696
- getService$1("field-sizes").setCustomFieldInputSizes();
697
- await getService$1("components").syncConfigurations();
698
- await getService$1("content-types").syncConfigurations();
699
- await getService$1("permission").registerPermissions();
947
+ getService$2("field-sizes").setCustomFieldInputSizes();
948
+ await getService$2("components").syncConfigurations();
949
+ await getService$2("content-types").syncConfigurations();
950
+ await getService$2("permission").registerPermissions();
700
951
  await history.bootstrap?.({ strapi });
952
+ await preview.bootstrap?.({ strapi });
701
953
  };
702
954
  const destroy = async ({ strapi: strapi2 }) => {
703
955
  await history.destroy?.({ strapi: strapi2 });
@@ -1187,7 +1439,8 @@ const admin = {
1187
1439
  };
1188
1440
  const routes = {
1189
1441
  admin,
1190
- ...history.routes ? history.routes : {}
1442
+ ...history.routes ? history.routes : {},
1443
+ ...preview.routes ? preview.routes : {}
1191
1444
  };
1192
1445
  const hasPermissionsSchema = strapiUtils.yup.object({
1193
1446
  actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
@@ -1198,6 +1451,11 @@ const { createPolicy } = strapiUtils.policy;
1198
1451
  const hasPermissions = createPolicy({
1199
1452
  name: "plugin::content-manager.hasPermissions",
1200
1453
  validator: validateHasPermissionsInput,
1454
+ /**
1455
+ * NOTE: Action aliases are currently not checked at this level (policy).
1456
+ * This is currently the intended behavior to avoid changing the behavior of API related permissions.
1457
+ * If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
1458
+ */
1201
1459
  handler(ctx, config = {}) {
1202
1460
  const { actions = [], hasAtLeastOne = false } = config;
1203
1461
  const { userAbility } = ctx.state;
@@ -1245,8 +1503,7 @@ const isSortable = (schema, name) => {
1245
1503
  if (!___default.default.has(schema.attributes, name)) {
1246
1504
  return false;
1247
1505
  }
1248
- if (schema.modelType === "component" && name === "id")
1249
- return false;
1506
+ if (schema.modelType === "component" && name === "id") return false;
1250
1507
  const attribute = schema.attributes[name];
1251
1508
  if (NON_SORTABLES.includes(attribute.type)) {
1252
1509
  return false;
@@ -1391,8 +1648,7 @@ const createDefaultSettings = async (schema) => {
1391
1648
  };
1392
1649
  };
1393
1650
  const syncSettings = async (configuration, schema) => {
1394
- if (fp.isEmpty(configuration.settings))
1395
- return createDefaultSettings(schema);
1651
+ if (fp.isEmpty(configuration.settings)) return createDefaultSettings(schema);
1396
1652
  const defaultField = getDefaultMainField(schema);
1397
1653
  const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
1398
1654
  return {
@@ -1439,7 +1695,7 @@ const createMetadasSchema = (schema) => {
1439
1695
  if (!value) {
1440
1696
  return strapiUtils.yup.string();
1441
1697
  }
1442
- const targetSchema = getService$1("content-types").findContentType(
1698
+ const targetSchema = getService$2("content-types").findContentType(
1443
1699
  schema.attributes[key].targetModel
1444
1700
  );
1445
1701
  if (!targetSchema) {
@@ -1568,8 +1824,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
1568
1824
  }
1569
1825
  switch (attribute.type) {
1570
1826
  case "relation": {
1571
- if (canCreate(attributePath))
1572
- return body2;
1827
+ if (canCreate(attributePath)) return body2;
1573
1828
  return fp.set(attributePath, { set: [] }, body2);
1574
1829
  }
1575
1830
  case "component": {
@@ -1579,8 +1834,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
1579
1834
  ]);
1580
1835
  }
1581
1836
  default: {
1582
- if (canCreate(attributePath))
1583
- return body2;
1837
+ if (canCreate(attributePath)) return body2;
1584
1838
  return fp.set(attributePath, null, body2);
1585
1839
  }
1586
1840
  }
@@ -1591,9 +1845,11 @@ const multipleLocaleSchema = strapiUtils.yup.lazy(
1591
1845
  (value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
1592
1846
  );
1593
1847
  const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
1594
- const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
1848
+ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
1595
1849
  const { allowMultipleLocales } = opts;
1596
- const { locale, status, ...rest } = request || {};
1850
+ const { locale, status: providedStatus, ...rest } = request || {};
1851
+ const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
1852
+ const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
1597
1853
  const schema = strapiUtils.yup.object().shape({
1598
1854
  locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
1599
1855
  status: statusSchema
@@ -1606,7 +1862,7 @@ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales
1606
1862
  }
1607
1863
  };
1608
1864
  const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
1609
- const documentMetadata2 = getService$1("document-metadata");
1865
+ const documentMetadata2 = getService$2("document-metadata");
1610
1866
  const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
1611
1867
  let {
1612
1868
  meta: { availableLocales, availableStatus }
@@ -1632,8 +1888,8 @@ const createDocument = async (ctx, opts) => {
1632
1888
  const { userAbility, user } = ctx.state;
1633
1889
  const { model } = ctx.params;
1634
1890
  const { body } = ctx.request;
1635
- const documentManager2 = getService$1("document-manager");
1636
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1891
+ const documentManager2 = getService$2("document-manager");
1892
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1637
1893
  if (permissionChecker2.cannot.create()) {
1638
1894
  throw new strapiUtils.errors.ForbiddenError();
1639
1895
  }
@@ -1641,7 +1897,7 @@ const createDocument = async (ctx, opts) => {
1641
1897
  const setCreator = strapiUtils.setCreatorFields({ user });
1642
1898
  const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1643
1899
  const sanitizedBody = await sanitizeFn(body);
1644
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
1900
+ const { locale, status } = await getDocumentLocaleAndStatus(body, model);
1645
1901
  return documentManager2.create(model, {
1646
1902
  data: sanitizedBody,
1647
1903
  locale,
@@ -1653,14 +1909,14 @@ const updateDocument = async (ctx, opts) => {
1653
1909
  const { userAbility, user } = ctx.state;
1654
1910
  const { id, model } = ctx.params;
1655
1911
  const { body } = ctx.request;
1656
- const documentManager2 = getService$1("document-manager");
1657
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1912
+ const documentManager2 = getService$2("document-manager");
1913
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1658
1914
  if (permissionChecker2.cannot.update()) {
1659
1915
  throw new strapiUtils.errors.ForbiddenError();
1660
1916
  }
1661
1917
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1662
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1663
- const { locale } = await getDocumentLocaleAndStatus(body);
1918
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
1919
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1664
1920
  const [documentVersion, documentExists] = await Promise.all([
1665
1921
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1666
1922
  documentManager2.exists(model, id)
@@ -1676,7 +1932,7 @@ const updateDocument = async (ctx, opts) => {
1676
1932
  throw new strapiUtils.errors.ForbiddenError();
1677
1933
  }
1678
1934
  const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
1679
- const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
1935
+ const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
1680
1936
  const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1681
1937
  const sanitizedBody = await sanitizeFn(body);
1682
1938
  return documentManager2.update(documentVersion?.documentId || id, model, {
@@ -1690,15 +1946,15 @@ const collectionTypes = {
1690
1946
  const { userAbility } = ctx.state;
1691
1947
  const { model } = ctx.params;
1692
1948
  const { query } = ctx.request;
1693
- const documentMetadata2 = getService$1("document-metadata");
1694
- const documentManager2 = getService$1("document-manager");
1695
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1949
+ const documentMetadata2 = getService$2("document-metadata");
1950
+ const documentManager2 = getService$2("document-manager");
1951
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1696
1952
  if (permissionChecker2.cannot.read()) {
1697
1953
  return ctx.forbidden();
1698
1954
  }
1699
1955
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1700
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1701
- const { locale, status } = await getDocumentLocaleAndStatus(query);
1956
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1957
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
1702
1958
  const { results: documents, pagination } = await documentManager2.findPage(
1703
1959
  { ...permissionQuery, populate, locale, status },
1704
1960
  model
@@ -1726,14 +1982,14 @@ const collectionTypes = {
1726
1982
  async findOne(ctx) {
1727
1983
  const { userAbility } = ctx.state;
1728
1984
  const { model, id } = ctx.params;
1729
- const documentManager2 = getService$1("document-manager");
1730
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1985
+ const documentManager2 = getService$2("document-manager");
1986
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1731
1987
  if (permissionChecker2.cannot.read()) {
1732
1988
  return ctx.forbidden();
1733
1989
  }
1734
1990
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1735
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1736
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
1991
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1992
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
1737
1993
  const version = await documentManager2.findOne(id, model, {
1738
1994
  populate,
1739
1995
  locale,
@@ -1748,7 +2004,7 @@ const collectionTypes = {
1748
2004
  permissionChecker2,
1749
2005
  model,
1750
2006
  // @ts-expect-error TODO: fix
1751
- { id, locale, publishedAt: null },
2007
+ { documentId: id, locale, publishedAt: null },
1752
2008
  { availableLocales: true, availableStatus: false }
1753
2009
  );
1754
2010
  ctx.body = { data: {}, meta };
@@ -1763,7 +2019,7 @@ const collectionTypes = {
1763
2019
  async create(ctx) {
1764
2020
  const { userAbility } = ctx.state;
1765
2021
  const { model } = ctx.params;
1766
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2022
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1767
2023
  const [totalEntries, document] = await Promise.all([
1768
2024
  strapi.db.query(model).count(),
1769
2025
  createDocument(ctx)
@@ -1784,7 +2040,7 @@ const collectionTypes = {
1784
2040
  async update(ctx) {
1785
2041
  const { userAbility } = ctx.state;
1786
2042
  const { model } = ctx.params;
1787
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2043
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1788
2044
  const updatedVersion = await updateDocument(ctx);
1789
2045
  const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
1790
2046
  ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
@@ -1793,14 +2049,14 @@ const collectionTypes = {
1793
2049
  const { userAbility, user } = ctx.state;
1794
2050
  const { model, sourceId: id } = ctx.params;
1795
2051
  const { body } = ctx.request;
1796
- const documentManager2 = getService$1("document-manager");
1797
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2052
+ const documentManager2 = getService$2("document-manager");
2053
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1798
2054
  if (permissionChecker2.cannot.create()) {
1799
2055
  return ctx.forbidden();
1800
2056
  }
1801
2057
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1802
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1803
- const { locale } = await getDocumentLocaleAndStatus(body);
2058
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2059
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1804
2060
  const document = await documentManager2.findOne(id, model, {
1805
2061
  populate,
1806
2062
  locale,
@@ -1838,14 +2094,14 @@ const collectionTypes = {
1838
2094
  async delete(ctx) {
1839
2095
  const { userAbility } = ctx.state;
1840
2096
  const { id, model } = ctx.params;
1841
- const documentManager2 = getService$1("document-manager");
1842
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2097
+ const documentManager2 = getService$2("document-manager");
2098
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1843
2099
  if (permissionChecker2.cannot.delete()) {
1844
2100
  return ctx.forbidden();
1845
2101
  }
1846
2102
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1847
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1848
- const { locale } = await getDocumentLocaleAndStatus(ctx.query);
2103
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2104
+ const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
1849
2105
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1850
2106
  if (documentLocales.length === 0) {
1851
2107
  return ctx.notFound();
@@ -1866,19 +2122,42 @@ const collectionTypes = {
1866
2122
  const { userAbility } = ctx.state;
1867
2123
  const { id, model } = ctx.params;
1868
2124
  const { body } = ctx.request;
1869
- const documentManager2 = getService$1("document-manager");
1870
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2125
+ const documentManager2 = getService$2("document-manager");
2126
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1871
2127
  if (permissionChecker2.cannot.publish()) {
1872
2128
  return ctx.forbidden();
1873
2129
  }
1874
2130
  const publishedDocument = await strapi.db.transaction(async () => {
1875
2131
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1876
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1877
- const document = id ? await updateDocument(ctx, { populate }) : await createDocument(ctx, { populate });
2132
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
2133
+ let document;
2134
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2135
+ const isCreate = fp.isNil(id);
2136
+ if (isCreate) {
2137
+ if (permissionChecker2.cannot.create()) {
2138
+ throw new strapiUtils.errors.ForbiddenError();
2139
+ }
2140
+ document = await createDocument(ctx, { populate });
2141
+ }
2142
+ const isUpdate = !isCreate;
2143
+ if (isUpdate) {
2144
+ const documentExists = documentManager2.exists(model, id);
2145
+ if (!documentExists) {
2146
+ throw new strapiUtils.errors.NotFoundError("Document not found");
2147
+ }
2148
+ document = await documentManager2.findOne(id, model, { populate, locale });
2149
+ if (!document) {
2150
+ if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
2151
+ throw new strapiUtils.errors.ForbiddenError();
2152
+ }
2153
+ document = await updateDocument(ctx);
2154
+ } else if (permissionChecker2.can.update(document)) {
2155
+ await updateDocument(ctx);
2156
+ }
2157
+ }
1878
2158
  if (permissionChecker2.cannot.publish(document)) {
1879
2159
  throw new strapiUtils.errors.ForbiddenError();
1880
2160
  }
1881
- const { locale } = await getDocumentLocaleAndStatus(body);
1882
2161
  const publishResult = await documentManager2.publish(document.documentId, model, {
1883
2162
  locale
1884
2163
  // TODO: Allow setting creator fields on publish
@@ -1898,14 +2177,16 @@ const collectionTypes = {
1898
2177
  const { body } = ctx.request;
1899
2178
  const { documentIds } = body;
1900
2179
  await validateBulkActionInput(body);
1901
- const documentManager2 = getService$1("document-manager");
1902
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2180
+ const documentManager2 = getService$2("document-manager");
2181
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1903
2182
  if (permissionChecker2.cannot.publish()) {
1904
2183
  return ctx.forbidden();
1905
2184
  }
1906
2185
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1907
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1908
- const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
2186
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
2187
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
2188
+ allowMultipleLocales: true
2189
+ });
1909
2190
  const entityPromises = documentIds.map(
1910
2191
  (documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
1911
2192
  );
@@ -1927,12 +2208,14 @@ const collectionTypes = {
1927
2208
  const { body } = ctx.request;
1928
2209
  const { documentIds } = body;
1929
2210
  await validateBulkActionInput(body);
1930
- const documentManager2 = getService$1("document-manager");
1931
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2211
+ const documentManager2 = getService$2("document-manager");
2212
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1932
2213
  if (permissionChecker2.cannot.unpublish()) {
1933
2214
  return ctx.forbidden();
1934
2215
  }
1935
- const { locale } = await getDocumentLocaleAndStatus(body);
2216
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
2217
+ allowMultipleLocales: true
2218
+ });
1936
2219
  const entityPromises = documentIds.map(
1937
2220
  (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1938
2221
  );
@@ -1955,8 +2238,8 @@ const collectionTypes = {
1955
2238
  const {
1956
2239
  body: { discardDraft, ...body }
1957
2240
  } = ctx.request;
1958
- const documentManager2 = getService$1("document-manager");
1959
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2241
+ const documentManager2 = getService$2("document-manager");
2242
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1960
2243
  if (permissionChecker2.cannot.unpublish()) {
1961
2244
  return ctx.forbidden();
1962
2245
  }
@@ -1964,8 +2247,8 @@ const collectionTypes = {
1964
2247
  return ctx.forbidden();
1965
2248
  }
1966
2249
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1967
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1968
- const { locale } = await getDocumentLocaleAndStatus(body);
2250
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2251
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1969
2252
  const document = await documentManager2.findOne(id, model, {
1970
2253
  populate,
1971
2254
  locale,
@@ -1995,14 +2278,14 @@ const collectionTypes = {
1995
2278
  const { userAbility } = ctx.state;
1996
2279
  const { id, model } = ctx.params;
1997
2280
  const { body } = ctx.request;
1998
- const documentManager2 = getService$1("document-manager");
1999
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2281
+ const documentManager2 = getService$2("document-manager");
2282
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2000
2283
  if (permissionChecker2.cannot.discard()) {
2001
2284
  return ctx.forbidden();
2002
2285
  }
2003
2286
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
2004
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2005
- const { locale } = await getDocumentLocaleAndStatus(body);
2287
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2288
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2006
2289
  const document = await documentManager2.findOne(id, model, {
2007
2290
  populate,
2008
2291
  locale,
@@ -2026,14 +2309,14 @@ const collectionTypes = {
2026
2309
  const { query, body } = ctx.request;
2027
2310
  const { documentIds } = body;
2028
2311
  await validateBulkActionInput(body);
2029
- const documentManager2 = getService$1("document-manager");
2030
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2312
+ const documentManager2 = getService$2("document-manager");
2313
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2031
2314
  if (permissionChecker2.cannot.delete()) {
2032
2315
  return ctx.forbidden();
2033
2316
  }
2034
2317
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
2035
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2036
- const { locale } = await getDocumentLocaleAndStatus(body);
2318
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2319
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2037
2320
  const documentLocales = await documentManager2.findLocales(documentIds, model, {
2038
2321
  populate,
2039
2322
  locale
@@ -2053,14 +2336,14 @@ const collectionTypes = {
2053
2336
  async countDraftRelations(ctx) {
2054
2337
  const { userAbility } = ctx.state;
2055
2338
  const { model, id } = ctx.params;
2056
- const documentManager2 = getService$1("document-manager");
2057
- 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 });
2058
2341
  if (permissionChecker2.cannot.read()) {
2059
2342
  return ctx.forbidden();
2060
2343
  }
2061
2344
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2062
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2063
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
2345
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2346
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
2064
2347
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
2065
2348
  if (!entity) {
2066
2349
  return ctx.notFound();
@@ -2078,12 +2361,12 @@ const collectionTypes = {
2078
2361
  const ids = ctx.request.query.documentIds;
2079
2362
  const locale = ctx.request.query.locale;
2080
2363
  const { model } = ctx.params;
2081
- const documentManager2 = getService$1("document-manager");
2082
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2364
+ const documentManager2 = getService$2("document-manager");
2365
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2083
2366
  if (permissionChecker2.cannot.read()) {
2084
2367
  return ctx.forbidden();
2085
2368
  }
2086
- const entities = await documentManager2.findMany(
2369
+ const documents = await documentManager2.findMany(
2087
2370
  {
2088
2371
  filters: {
2089
2372
  documentId: ids
@@ -2092,7 +2375,7 @@ const collectionTypes = {
2092
2375
  },
2093
2376
  model
2094
2377
  );
2095
- if (!entities) {
2378
+ if (!documents) {
2096
2379
  return ctx.notFound();
2097
2380
  }
2098
2381
  const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
@@ -2103,13 +2386,13 @@ const collectionTypes = {
2103
2386
  };
2104
2387
  const components$1 = {
2105
2388
  findComponents(ctx) {
2106
- const components2 = getService$1("components").findAllComponents();
2107
- const { toDto } = getService$1("data-mapper");
2389
+ const components2 = getService$2("components").findAllComponents();
2390
+ const { toDto } = getService$2("data-mapper");
2108
2391
  ctx.body = { data: components2.map(toDto) };
2109
2392
  },
2110
2393
  async findComponentConfiguration(ctx) {
2111
2394
  const { uid: uid2 } = ctx.params;
2112
- const componentService = getService$1("components");
2395
+ const componentService = getService$2("components");
2113
2396
  const component = componentService.findComponent(uid2);
2114
2397
  if (!component) {
2115
2398
  return ctx.notFound("component.notFound");
@@ -2126,7 +2409,7 @@ const components$1 = {
2126
2409
  async updateComponentConfiguration(ctx) {
2127
2410
  const { uid: uid2 } = ctx.params;
2128
2411
  const { body } = ctx.request;
2129
- const componentService = getService$1("components");
2412
+ const componentService = getService$2("components");
2130
2413
  const component = componentService.findComponent(uid2);
2131
2414
  if (!component) {
2132
2415
  return ctx.notFound("component.notFound");
@@ -2160,12 +2443,12 @@ const contentTypes = {
2160
2443
  } catch (error) {
2161
2444
  return ctx.send({ error }, 400);
2162
2445
  }
2163
- const contentTypes2 = getService$1("content-types").findContentTypesByKind(kind);
2164
- const { toDto } = getService$1("data-mapper");
2446
+ const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
2447
+ const { toDto } = getService$2("data-mapper");
2165
2448
  ctx.body = { data: contentTypes2.map(toDto) };
2166
2449
  },
2167
2450
  async findContentTypesSettings(ctx) {
2168
- const { findAllContentTypes, findConfiguration } = getService$1("content-types");
2451
+ const { findAllContentTypes, findConfiguration } = getService$2("content-types");
2169
2452
  const contentTypes2 = await findAllContentTypes();
2170
2453
  const configurations = await Promise.all(
2171
2454
  contentTypes2.map(async (contentType) => {
@@ -2179,7 +2462,7 @@ const contentTypes = {
2179
2462
  },
2180
2463
  async findContentTypeConfiguration(ctx) {
2181
2464
  const { uid: uid2 } = ctx.params;
2182
- const contentTypeService = getService$1("content-types");
2465
+ const contentTypeService = getService$2("content-types");
2183
2466
  const contentType = await contentTypeService.findContentType(uid2);
2184
2467
  if (!contentType) {
2185
2468
  return ctx.notFound("contentType.notFound");
@@ -2201,13 +2484,13 @@ const contentTypes = {
2201
2484
  const { userAbility } = ctx.state;
2202
2485
  const { uid: uid2 } = ctx.params;
2203
2486
  const { body } = ctx.request;
2204
- const contentTypeService = getService$1("content-types");
2205
- const metricsService = getService$1("metrics");
2487
+ const contentTypeService = getService$2("content-types");
2488
+ const metricsService = getService$2("metrics");
2206
2489
  const contentType = await contentTypeService.findContentType(uid2);
2207
2490
  if (!contentType) {
2208
2491
  return ctx.notFound("contentType.notFound");
2209
2492
  }
2210
- if (!getService$1("permission").canConfigureContentType({ userAbility, contentType })) {
2493
+ if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
2211
2494
  return ctx.forbidden();
2212
2495
  }
2213
2496
  let input;
@@ -2240,10 +2523,10 @@ const contentTypes = {
2240
2523
  };
2241
2524
  const init = {
2242
2525
  getInitData(ctx) {
2243
- const { toDto } = getService$1("data-mapper");
2244
- const { findAllComponents } = getService$1("components");
2245
- const { getAllFieldSizes } = getService$1("field-sizes");
2246
- const { findAllContentTypes } = getService$1("content-types");
2526
+ const { toDto } = getService$2("data-mapper");
2527
+ const { findAllComponents } = getService$2("components");
2528
+ const { getAllFieldSizes } = getService$2("field-sizes");
2529
+ const { findAllContentTypes } = getService$2("content-types");
2247
2530
  ctx.body = {
2248
2531
  data: {
2249
2532
  fieldSizes: getAllFieldSizes(),
@@ -2279,36 +2562,41 @@ const addFiltersClause = (params, filtersClause) => {
2279
2562
  params.filters.$and.push(filtersClause);
2280
2563
  };
2281
2564
  const sanitizeMainField = (model, mainField, userAbility) => {
2282
- const permissionChecker2 = getService$1("permission-checker").create({
2565
+ const permissionChecker2 = getService$2("permission-checker").create({
2283
2566
  userAbility,
2284
2567
  model: model.uid
2285
2568
  });
2286
- if (!isListable(model, mainField)) {
2569
+ const isMainFieldListable = isListable(model, mainField);
2570
+ const canReadMainField = permissionChecker2.can.read(null, mainField);
2571
+ if (!isMainFieldListable || !canReadMainField) {
2287
2572
  return "id";
2288
2573
  }
2289
- if (permissionChecker2.cannot.read(null, mainField)) {
2290
- if (model.uid === "plugin::users-permissions.role") {
2291
- const userPermissionChecker = getService$1("permission-checker").create({
2292
- userAbility,
2293
- model: "plugin::users-permissions.user"
2294
- });
2295
- if (userPermissionChecker.can.read()) {
2296
- return "name";
2297
- }
2298
- }
2299
- return "id";
2574
+ if (model.uid === "plugin::users-permissions.role") {
2575
+ return "name";
2300
2576
  }
2301
2577
  return mainField;
2302
2578
  };
2303
- const addStatusToRelations = async (uid2, relations2) => {
2304
- if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.contentTypes[uid2])) {
2579
+ const addStatusToRelations = async (targetUid, relations2) => {
2580
+ if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {
2305
2581
  return relations2;
2306
2582
  }
2307
- const documentMetadata2 = getService$1("document-metadata");
2308
- const documentsAvailableStatus = await documentMetadata2.getManyAvailableStatus(uid2, relations2);
2583
+ const documentMetadata2 = getService$2("document-metadata");
2584
+ if (!relations2.length) {
2585
+ return relations2;
2586
+ }
2587
+ const firstRelation = relations2[0];
2588
+ const filters = {
2589
+ documentId: { $in: relations2.map((r) => r.documentId) },
2590
+ // NOTE: find the "opposite" status
2591
+ publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
2592
+ };
2593
+ const availableStatus = await strapi.query(targetUid).findMany({
2594
+ select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
2595
+ filters
2596
+ });
2309
2597
  return relations2.map((relation) => {
2310
- const availableStatuses = documentsAvailableStatus.filter(
2311
- (availableDocument) => availableDocument.documentId === relation.documentId
2598
+ const availableStatuses = availableStatus.filter(
2599
+ (availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
2312
2600
  );
2313
2601
  return {
2314
2602
  ...relation,
@@ -2329,11 +2617,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
2329
2617
  const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
2330
2618
  const isSourceLocalized = isLocalized(sourceModel);
2331
2619
  const isTargetLocalized = isLocalized(targetModel);
2332
- let validatedLocale = locale;
2333
- if (!targetModel || !isTargetLocalized)
2334
- validatedLocale = void 0;
2335
2620
  return {
2336
- locale: validatedLocale,
2621
+ locale,
2337
2622
  isSourceLocalized,
2338
2623
  isTargetLocalized
2339
2624
  };
@@ -2342,8 +2627,7 @@ const validateStatus = (sourceUid, status) => {
2342
2627
  const sourceModel = strapi.getModel(sourceUid);
2343
2628
  const isDP = strapiUtils.contentTypes.hasDraftAndPublish;
2344
2629
  const isSourceDP = isDP(sourceModel);
2345
- if (!isSourceDP)
2346
- return { status: void 0 };
2630
+ if (!isSourceDP) return { status: void 0 };
2347
2631
  switch (status) {
2348
2632
  case "published":
2349
2633
  return { status: "published" };
@@ -2373,7 +2657,7 @@ const relations = {
2373
2657
  ctx.request?.query?.locale
2374
2658
  );
2375
2659
  const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
2376
- const permissionChecker2 = getService$1("permission-checker").create({
2660
+ const permissionChecker2 = getService$2("permission-checker").create({
2377
2661
  userAbility,
2378
2662
  model
2379
2663
  });
@@ -2398,7 +2682,7 @@ const relations = {
2398
2682
  where.id = id;
2399
2683
  }
2400
2684
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2401
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2685
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2402
2686
  const currentEntity = await strapi.db.query(model).findOne({
2403
2687
  where,
2404
2688
  populate
@@ -2413,7 +2697,7 @@ const relations = {
2413
2697
  }
2414
2698
  entryId = currentEntity.id;
2415
2699
  }
2416
- const modelConfig = isComponent2 ? await getService$1("components").findConfiguration(sourceSchema) : await getService$1("content-types").findConfiguration(sourceSchema);
2700
+ const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
2417
2701
  const targetSchema = strapi.getModel(targetUid);
2418
2702
  const mainField = fp.flow(
2419
2703
  fp.prop(`metadatas.${targetField}.edit.mainField`),
@@ -2436,7 +2720,7 @@ const relations = {
2436
2720
  attribute,
2437
2721
  fieldsToSelect,
2438
2722
  mainField,
2439
- source: { schema: sourceSchema },
2723
+ source: { schema: sourceSchema, isLocalized: isSourceLocalized },
2440
2724
  target: { schema: targetSchema, isLocalized: isTargetLocalized },
2441
2725
  sourceSchema,
2442
2726
  targetSchema,
@@ -2458,7 +2742,8 @@ const relations = {
2458
2742
  fieldsToSelect,
2459
2743
  mainField,
2460
2744
  source: {
2461
- schema: { uid: sourceUid, modelType: sourceModelType }
2745
+ schema: { uid: sourceUid, modelType: sourceModelType },
2746
+ isLocalized: isSourceLocalized
2462
2747
  },
2463
2748
  target: {
2464
2749
  schema: { uid: targetUid },
@@ -2466,7 +2751,7 @@ const relations = {
2466
2751
  }
2467
2752
  } = await this.extractAndValidateRequestInfo(ctx, id);
2468
2753
  const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
2469
- const permissionChecker2 = getService$1("permission-checker").create({
2754
+ const permissionChecker2 = getService$2("permission-checker").create({
2470
2755
  userAbility: ctx.state.userAbility,
2471
2756
  model: targetUid
2472
2757
  });
@@ -2496,12 +2781,16 @@ const relations = {
2496
2781
  } else {
2497
2782
  where.id = id;
2498
2783
  }
2499
- if (status) {
2500
- where[`${alias}.published_at`] = getPublishedAtClause(status, targetUid);
2784
+ const publishedAt = getPublishedAtClause(status, targetUid);
2785
+ if (!fp.isEmpty(publishedAt)) {
2786
+ where[`${alias}.published_at`] = publishedAt;
2501
2787
  }
2502
- if (filterByLocale) {
2788
+ if (isTargetLocalized && locale) {
2503
2789
  where[`${alias}.locale`] = locale;
2504
2790
  }
2791
+ if (isSourceLocalized && locale) {
2792
+ where.locale = locale;
2793
+ }
2505
2794
  if ((idsToInclude?.length ?? 0) !== 0) {
2506
2795
  where[`${alias}.id`].$notIn = idsToInclude;
2507
2796
  }
@@ -2519,7 +2808,8 @@ const relations = {
2519
2808
  id: { $notIn: fp.uniq(idsToOmit) }
2520
2809
  });
2521
2810
  }
2522
- const res = await strapi.db.query(targetUid).findPage(strapi.get("query-params").transform(targetUid, queryParams));
2811
+ const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
2812
+ const res = await strapi.db.query(targetUid).findPage(dbQuery);
2523
2813
  ctx.body = {
2524
2814
  ...res,
2525
2815
  results: await addStatusToRelations(targetUid, res.results)
@@ -2534,29 +2824,39 @@ const relations = {
2534
2824
  attribute,
2535
2825
  targetField,
2536
2826
  fieldsToSelect,
2537
- source: {
2538
- schema: { uid: sourceUid }
2539
- },
2540
- target: {
2541
- schema: { uid: targetUid }
2542
- }
2827
+ status,
2828
+ source: { schema: sourceSchema },
2829
+ target: { schema: targetSchema }
2543
2830
  } = await this.extractAndValidateRequestInfo(ctx, id);
2544
- const permissionQuery = await getService$1("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
2831
+ const { uid: sourceUid } = sourceSchema;
2832
+ const { uid: targetUid } = targetSchema;
2833
+ const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
2545
2834
  const dbQuery = strapi.db.query(sourceUid);
2546
2835
  const loadRelations = strapiUtils.relations.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
2836
+ const filters = {};
2837
+ if (sourceSchema?.options?.draftAndPublish) {
2838
+ if (targetSchema?.options?.draftAndPublish) {
2839
+ if (status === "published") {
2840
+ filters.publishedAt = { $notNull: true };
2841
+ } else {
2842
+ filters.publishedAt = { $null: true };
2843
+ }
2844
+ }
2845
+ } else if (targetSchema?.options?.draftAndPublish) {
2846
+ filters.publishedAt = { $null: true };
2847
+ }
2547
2848
  const res = await loadRelations({ id: entryId }, targetField, {
2548
- select: ["id", "documentId", "locale", "publishedAt"],
2849
+ select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
2549
2850
  ordering: "desc",
2550
2851
  page: ctx.request.query.page,
2551
- pageSize: ctx.request.query.pageSize
2852
+ pageSize: ctx.request.query.pageSize,
2853
+ filters
2552
2854
  });
2553
2855
  const loadedIds = res.results.map((item) => item.id);
2554
2856
  addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
2555
2857
  const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
2556
2858
  ...strapi.get("query-params").transform(targetUid, permissionQuery),
2557
- ordering: "desc",
2558
- page: ctx.request.query.page,
2559
- pageSize: ctx.request.query.pageSize
2859
+ ordering: "desc"
2560
2860
  });
2561
2861
  const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
2562
2862
  ctx.body = {
@@ -2571,10 +2871,10 @@ const relations = {
2571
2871
  }
2572
2872
  };
2573
2873
  const buildPopulateFromQuery = async (query, model) => {
2574
- return getService$1("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
2874
+ return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
2575
2875
  };
2576
2876
  const findDocument = async (query, uid2, opts = {}) => {
2577
- const documentManager2 = getService$1("document-manager");
2877
+ const documentManager2 = getService$2("document-manager");
2578
2878
  const populate = await buildPopulateFromQuery(query, uid2);
2579
2879
  return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
2580
2880
  };
@@ -2582,13 +2882,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
2582
2882
  const { user, userAbility } = ctx.state;
2583
2883
  const { model } = ctx.params;
2584
2884
  const { body, query } = ctx.request;
2585
- const documentManager2 = getService$1("document-manager");
2586
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2885
+ const documentManager2 = getService$2("document-manager");
2886
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2587
2887
  if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
2588
2888
  throw new strapiUtils.errors.ForbiddenError();
2589
2889
  }
2590
2890
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2591
- const { locale } = await getDocumentLocaleAndStatus(body);
2891
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2592
2892
  const [documentVersion, otherDocumentVersion] = await Promise.all([
2593
2893
  findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2594
2894
  // Find the first document to check if it exists
@@ -2624,12 +2924,12 @@ const singleTypes = {
2624
2924
  const { userAbility } = ctx.state;
2625
2925
  const { model } = ctx.params;
2626
2926
  const { query = {} } = ctx.request;
2627
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2927
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2628
2928
  if (permissionChecker2.cannot.read()) {
2629
2929
  return ctx.forbidden();
2630
2930
  }
2631
2931
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2632
- const { locale, status } = await getDocumentLocaleAndStatus(query);
2932
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
2633
2933
  const version = await findDocument(permissionQuery, model, { locale, status });
2634
2934
  if (!version) {
2635
2935
  if (permissionChecker2.cannot.create()) {
@@ -2643,7 +2943,7 @@ const singleTypes = {
2643
2943
  permissionChecker2,
2644
2944
  model,
2645
2945
  // @ts-expect-error - fix types
2646
- { id: document.documentId, locale, publishedAt: null },
2946
+ { documentId: document.documentId, locale, publishedAt: null },
2647
2947
  { availableLocales: true, availableStatus: false }
2648
2948
  );
2649
2949
  ctx.body = { data: {}, meta };
@@ -2658,7 +2958,7 @@ const singleTypes = {
2658
2958
  async createOrUpdate(ctx) {
2659
2959
  const { userAbility } = ctx.state;
2660
2960
  const { model } = ctx.params;
2661
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2961
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2662
2962
  const document = await createOrUpdateDocument(ctx);
2663
2963
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
2664
2964
  ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
@@ -2667,14 +2967,14 @@ const singleTypes = {
2667
2967
  const { userAbility } = ctx.state;
2668
2968
  const { model } = ctx.params;
2669
2969
  const { query = {} } = ctx.request;
2670
- const documentManager2 = getService$1("document-manager");
2671
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2970
+ const documentManager2 = getService$2("document-manager");
2971
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2672
2972
  if (permissionChecker2.cannot.delete()) {
2673
2973
  return ctx.forbidden();
2674
2974
  }
2675
2975
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2676
2976
  const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2677
- const { locale } = await getDocumentLocaleAndStatus(query);
2977
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2678
2978
  const documentLocales = await documentManager2.findLocales(void 0, model, {
2679
2979
  populate,
2680
2980
  locale
@@ -2696,8 +2996,8 @@ const singleTypes = {
2696
2996
  const { userAbility } = ctx.state;
2697
2997
  const { model } = ctx.params;
2698
2998
  const { query = {} } = ctx.request;
2699
- const documentManager2 = getService$1("document-manager");
2700
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2999
+ const documentManager2 = getService$2("document-manager");
3000
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2701
3001
  if (permissionChecker2.cannot.publish()) {
2702
3002
  return ctx.forbidden();
2703
3003
  }
@@ -2711,7 +3011,7 @@ const singleTypes = {
2711
3011
  if (permissionChecker2.cannot.publish(document)) {
2712
3012
  throw new strapiUtils.errors.ForbiddenError();
2713
3013
  }
2714
- const { locale } = await getDocumentLocaleAndStatus(document);
3014
+ const { locale } = await getDocumentLocaleAndStatus(document, model);
2715
3015
  const publishResult = await documentManager2.publish(document.documentId, model, { locale });
2716
3016
  return publishResult.at(0);
2717
3017
  });
@@ -2725,8 +3025,8 @@ const singleTypes = {
2725
3025
  body: { discardDraft, ...body },
2726
3026
  query = {}
2727
3027
  } = ctx.request;
2728
- const documentManager2 = getService$1("document-manager");
2729
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
3028
+ const documentManager2 = getService$2("document-manager");
3029
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2730
3030
  if (permissionChecker2.cannot.unpublish()) {
2731
3031
  return ctx.forbidden();
2732
3032
  }
@@ -2734,7 +3034,7 @@ const singleTypes = {
2734
3034
  return ctx.forbidden();
2735
3035
  }
2736
3036
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2737
- const { locale } = await getDocumentLocaleAndStatus(body);
3037
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2738
3038
  const document = await findDocument(sanitizedQuery, model, { locale });
2739
3039
  if (!document) {
2740
3040
  return ctx.notFound();
@@ -2760,13 +3060,13 @@ const singleTypes = {
2760
3060
  const { userAbility } = ctx.state;
2761
3061
  const { model } = ctx.params;
2762
3062
  const { body, query = {} } = ctx.request;
2763
- const documentManager2 = getService$1("document-manager");
2764
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
3063
+ const documentManager2 = getService$2("document-manager");
3064
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2765
3065
  if (permissionChecker2.cannot.discard()) {
2766
3066
  return ctx.forbidden();
2767
3067
  }
2768
3068
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2769
- const { locale } = await getDocumentLocaleAndStatus(body);
3069
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2770
3070
  const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2771
3071
  if (!document) {
2772
3072
  return ctx.notFound();
@@ -2784,9 +3084,9 @@ const singleTypes = {
2784
3084
  const { userAbility } = ctx.state;
2785
3085
  const { model } = ctx.params;
2786
3086
  const { query } = ctx.request;
2787
- const documentManager2 = getService$1("document-manager");
2788
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2789
- const { locale } = await getDocumentLocaleAndStatus(query);
3087
+ const documentManager2 = getService$2("document-manager");
3088
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
3089
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2790
3090
  if (permissionChecker2.cannot.read()) {
2791
3091
  return ctx.forbidden();
2792
3092
  }
@@ -2807,9 +3107,9 @@ const uid$1 = {
2807
3107
  async generateUID(ctx) {
2808
3108
  const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2809
3109
  const { query = {} } = ctx.request;
2810
- const { locale } = await getDocumentLocaleAndStatus(query);
3110
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2811
3111
  await validateUIDField(contentTypeUID, field);
2812
- const uidService = getService$1("uid");
3112
+ const uidService = getService$2("uid");
2813
3113
  ctx.body = {
2814
3114
  data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
2815
3115
  };
@@ -2819,9 +3119,9 @@ const uid$1 = {
2819
3119
  ctx.request.body
2820
3120
  );
2821
3121
  const { query = {} } = ctx.request;
2822
- const { locale } = await getDocumentLocaleAndStatus(query);
3122
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2823
3123
  await validateUIDField(contentTypeUID, field);
2824
- const uidService = getService$1("uid");
3124
+ const uidService = getService$2("uid");
2825
3125
  const isAvailable = await uidService.checkUIDAvailability({
2826
3126
  contentTypeUID,
2827
3127
  field,
@@ -2842,7 +3142,8 @@ const controllers = {
2842
3142
  relations,
2843
3143
  "single-types": singleTypes,
2844
3144
  uid: uid$1,
2845
- ...history.controllers ? history.controllers : {}
3145
+ ...history.controllers ? history.controllers : {},
3146
+ ...preview.controllers ? preview.controllers : {}
2846
3147
  };
2847
3148
  const keys = {
2848
3149
  CONFIGURATION: "configuration"
@@ -2971,18 +3272,15 @@ async function syncMetadatas(configuration, schema) {
2971
3272
  ___default.default.set(updatedMeta, ["list", "searchable"], false);
2972
3273
  ___default.default.set(acc, [key], updatedMeta);
2973
3274
  }
2974
- if (!___default.default.has(edit, "mainField"))
2975
- return acc;
3275
+ if (!___default.default.has(edit, "mainField")) return acc;
2976
3276
  if (!isRelation$1(attr)) {
2977
3277
  ___default.default.set(updatedMeta, "edit", ___default.default.omit(edit, ["mainField"]));
2978
3278
  ___default.default.set(acc, [key], updatedMeta);
2979
3279
  return acc;
2980
3280
  }
2981
- if (edit.mainField === "id")
2982
- return acc;
3281
+ if (edit.mainField === "id") return acc;
2983
3282
  const targetSchema = getTargetSchema(attr.targetModel);
2984
- if (!targetSchema)
2985
- return acc;
3283
+ if (!targetSchema) return acc;
2986
3284
  if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
2987
3285
  ___default.default.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
2988
3286
  ___default.default.set(acc, [key], updatedMeta);
@@ -2993,12 +3291,12 @@ async function syncMetadatas(configuration, schema) {
2993
3291
  return ___default.default.assign(metasWithDefaults, updatedMetas);
2994
3292
  }
2995
3293
  const getTargetSchema = (targetModel) => {
2996
- return getService$1("content-types").findContentType(targetModel);
3294
+ return getService$2("content-types").findContentType(targetModel);
2997
3295
  };
2998
3296
  const DEFAULT_LIST_LENGTH = 4;
2999
3297
  const MAX_ROW_SIZE = 12;
3000
3298
  const isAllowedFieldSize = (type, size) => {
3001
- const { getFieldSize } = getService$1("field-sizes");
3299
+ const { getFieldSize } = getService$2("field-sizes");
3002
3300
  const fieldSize = getFieldSize(type);
3003
3301
  if (!fieldSize.isResizable && size !== fieldSize.default) {
3004
3302
  return false;
@@ -3006,7 +3304,7 @@ const isAllowedFieldSize = (type, size) => {
3006
3304
  return size <= MAX_ROW_SIZE;
3007
3305
  };
3008
3306
  const getDefaultFieldSize = (attribute) => {
3009
- const { hasFieldSize, getFieldSize } = getService$1("field-sizes");
3307
+ const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
3010
3308
  return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
3011
3309
  };
3012
3310
  async function createDefaultLayouts(schema) {
@@ -3027,8 +3325,7 @@ function createDefaultEditLayout(schema) {
3027
3325
  return appendToEditLayout([], keys2, schema);
3028
3326
  }
3029
3327
  function syncLayouts(configuration, schema) {
3030
- if (___default.default.isEmpty(configuration.layouts))
3031
- return createDefaultLayouts(schema);
3328
+ if (___default.default.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
3032
3329
  const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
3033
3330
  let cleanList = list.filter((attr) => isListable(schema, attr));
3034
3331
  const cleanEditRelations = editRelations.filter(
@@ -3039,9 +3336,8 @@ function syncLayouts(configuration, schema) {
3039
3336
  for (const row of edit) {
3040
3337
  const newRow = [];
3041
3338
  for (const el of row) {
3042
- if (!hasEditableAttribute(schema, el.name))
3043
- continue;
3044
- const { hasFieldSize } = getService$1("field-sizes");
3339
+ if (!hasEditableAttribute(schema, el.name)) continue;
3340
+ const { hasFieldSize } = getService$2("field-sizes");
3045
3341
  const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
3046
3342
  if (!isAllowedFieldSize(fieldType, el.size)) {
3047
3343
  elementsToReAppend.push(el.name);
@@ -3071,8 +3367,7 @@ function syncLayouts(configuration, schema) {
3071
3367
  };
3072
3368
  }
3073
3369
  const appendToEditLayout = (layout = [], keysToAppend, schema) => {
3074
- if (keysToAppend.length === 0)
3075
- return layout;
3370
+ if (keysToAppend.length === 0) return layout;
3076
3371
  let currentRowIndex = Math.max(layout.length - 1, 0);
3077
3372
  if (!layout[currentRowIndex]) {
3078
3373
  layout[currentRowIndex] = [];
@@ -3181,17 +3476,17 @@ const configurationService$1 = createConfigurationService({
3181
3476
  isComponent: true,
3182
3477
  prefix: STORE_KEY_PREFIX,
3183
3478
  getModels() {
3184
- const { toContentManagerModel } = getService$1("data-mapper");
3479
+ const { toContentManagerModel } = getService$2("data-mapper");
3185
3480
  return fp.mapValues(toContentManagerModel, strapi.components);
3186
3481
  }
3187
3482
  });
3188
3483
  const components = ({ strapi: strapi2 }) => ({
3189
3484
  findAllComponents() {
3190
- const { toContentManagerModel } = getService$1("data-mapper");
3485
+ const { toContentManagerModel } = getService$2("data-mapper");
3191
3486
  return Object.values(strapi2.components).map(toContentManagerModel);
3192
3487
  },
3193
3488
  findComponent(uid2) {
3194
- const { toContentManagerModel } = getService$1("data-mapper");
3489
+ const { toContentManagerModel } = getService$2("data-mapper");
3195
3490
  const component = strapi2.components[uid2];
3196
3491
  return fp.isNil(component) ? component : toContentManagerModel(component);
3197
3492
  },
@@ -3242,17 +3537,17 @@ const configurationService = createConfigurationService({
3242
3537
  storeUtils,
3243
3538
  prefix: "content_types",
3244
3539
  getModels() {
3245
- const { toContentManagerModel } = getService$1("data-mapper");
3540
+ const { toContentManagerModel } = getService$2("data-mapper");
3246
3541
  return fp.mapValues(toContentManagerModel, strapi.contentTypes);
3247
3542
  }
3248
3543
  });
3249
3544
  const service = ({ strapi: strapi2 }) => ({
3250
3545
  findAllContentTypes() {
3251
- const { toContentManagerModel } = getService$1("data-mapper");
3546
+ const { toContentManagerModel } = getService$2("data-mapper");
3252
3547
  return Object.values(strapi2.contentTypes).map(toContentManagerModel);
3253
3548
  },
3254
3549
  findContentType(uid2) {
3255
- const { toContentManagerModel } = getService$1("data-mapper");
3550
+ const { toContentManagerModel } = getService$2("data-mapper");
3256
3551
  const contentType = strapi2.contentTypes[uid2];
3257
3552
  return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
3258
3553
  },
@@ -3281,7 +3576,7 @@ const service = ({ strapi: strapi2 }) => ({
3281
3576
  return this.findConfiguration(contentType);
3282
3577
  },
3283
3578
  findComponentsConfigurations(contentType) {
3284
- return getService$1("components").findComponentsConfigurations(contentType);
3579
+ return getService$2("components").findComponentsConfigurations(contentType);
3285
3580
  },
3286
3581
  syncConfigurations() {
3287
3582
  return configurationService.syncConfigurations();
@@ -3462,12 +3757,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
3462
3757
  ability: userAbility,
3463
3758
  model
3464
3759
  });
3465
- const toSubject = (entity) => entity ? permissionsManager.toSubject(entity, model) : model;
3760
+ const { actionProvider } = strapi2.service("admin::permission");
3761
+ const toSubject = (entity) => {
3762
+ return entity ? permissionsManager.toSubject(entity, model) : model;
3763
+ };
3466
3764
  const can = (action, entity, field) => {
3467
- return userAbility.can(action, toSubject(entity), field);
3765
+ const subject = toSubject(entity);
3766
+ const aliases = actionProvider.unstable_aliases(action, model);
3767
+ return (
3768
+ // Test the original action to see if it passes
3769
+ userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
3770
+ aliases.some((alias) => userAbility.can(alias, subject, field))
3771
+ );
3468
3772
  };
3469
3773
  const cannot = (action, entity, field) => {
3470
- return userAbility.cannot(action, toSubject(entity), field);
3774
+ const subject = toSubject(entity);
3775
+ const aliases = actionProvider.unstable_aliases(action, model);
3776
+ return (
3777
+ // Test both the original action
3778
+ userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
3779
+ aliases.every((alias) => userAbility.cannot(alias, subject, field))
3780
+ );
3471
3781
  };
3472
3782
  const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
3473
3783
  return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
@@ -3538,7 +3848,7 @@ const permission = ({ strapi: strapi2 }) => ({
3538
3848
  return userAbility.can(action);
3539
3849
  },
3540
3850
  async registerPermissions() {
3541
- const displayedContentTypes = getService$1("content-types").findDisplayedContentTypes();
3851
+ const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
3542
3852
  const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
3543
3853
  const actions = [
3544
3854
  {
@@ -3744,6 +4054,10 @@ const getDeepPopulateDraftCount = (uid2) => {
3744
4054
  const attribute = model.attributes[attributeName];
3745
4055
  switch (attribute.type) {
3746
4056
  case "relation": {
4057
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
4058
+ if (isMorphRelation) {
4059
+ break;
4060
+ }
3747
4061
  if (isVisibleAttribute$1(model, attributeName)) {
3748
4062
  populateAcc[attributeName] = {
3749
4063
  count: true,
@@ -3810,7 +4124,7 @@ const getQueryPopulate = async (uid2, query) => {
3810
4124
  return populateQuery;
3811
4125
  };
3812
4126
  const buildDeepPopulate = (uid2) => {
3813
- return getService$1("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
4127
+ return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
3814
4128
  };
3815
4129
  const populateBuilder = (uid2) => {
3816
4130
  let getInitialPopulate = async () => {
@@ -3995,7 +4309,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3995
4309
  */
3996
4310
  async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
3997
4311
  const versionsByLocale = fp.groupBy("locale", allVersions);
3998
- delete versionsByLocale[version.locale];
4312
+ if (version.locale) {
4313
+ delete versionsByLocale[version.locale];
4314
+ }
3999
4315
  const model = strapi2.getModel(uid2);
4000
4316
  const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
4001
4317
  const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
@@ -4042,8 +4358,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4042
4358
  const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
4043
4359
  return matchLocale && matchStatus;
4044
4360
  });
4045
- if (!availableStatus)
4046
- return availableStatus;
4361
+ if (!availableStatus) return availableStatus;
4047
4362
  return fp.pick(AVAILABLE_STATUS_FIELDS, availableStatus);
4048
4363
  },
4049
4364
  /**
@@ -4053,8 +4368,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4053
4368
  * @returns
4054
4369
  */
4055
4370
  async getManyAvailableStatus(uid2, documents) {
4056
- if (!documents.length)
4057
- return [];
4371
+ if (!documents.length) return [];
4058
4372
  const status = documents[0].publishedAt !== null ? "published" : "draft";
4059
4373
  const locale = documents[0]?.locale;
4060
4374
  const otherStatus = status === "published" ? "draft" : "published";
@@ -4081,10 +4395,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4081
4395
  } else if (otherVersion) {
4082
4396
  draftVersion = otherVersion;
4083
4397
  }
4084
- if (!draftVersion)
4085
- return CONTENT_MANAGER_STATUS.PUBLISHED;
4086
- if (!publishedVersion)
4087
- return CONTENT_MANAGER_STATUS.DRAFT;
4398
+ if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
4399
+ if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
4088
4400
  const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
4089
4401
  return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
4090
4402
  },
@@ -4121,7 +4433,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4121
4433
  */
4122
4434
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
4123
4435
  if (!document) {
4124
- return document;
4436
+ return {
4437
+ data: document,
4438
+ meta: {
4439
+ availableLocales: [],
4440
+ availableStatus: []
4441
+ }
4442
+ };
4125
4443
  }
4126
4444
  const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
4127
4445
  if (!hasDraftAndPublish) {
@@ -4229,10 +4547,7 @@ const documentManager = ({ strapi: strapi2 }) => {
4229
4547
  async clone(id, body, uid2) {
4230
4548
  const populate = await buildDeepPopulate(uid2);
4231
4549
  const params = {
4232
- data: {
4233
- ...omitIdField(body),
4234
- [PUBLISHED_AT_ATTRIBUTE]: null
4235
- },
4550
+ data: omitIdField(body),
4236
4551
  populate
4237
4552
  };
4238
4553
  return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
@@ -4348,7 +4663,8 @@ const services = {
4348
4663
  permission,
4349
4664
  "populate-builder": populateBuilder$1,
4350
4665
  uid,
4351
- ...history.services ? history.services : {}
4666
+ ...history.services ? history.services : {},
4667
+ ...preview.services ? preview.services : {}
4352
4668
  };
4353
4669
  const index = () => {
4354
4670
  return {