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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
  3. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-CR5XdR33.mjs → ComponentConfigurationPage-BgCLcjXO.mjs} +4 -4
  5. package/dist/_chunks/{ComponentConfigurationPage-CR5XdR33.mjs.map → ComponentConfigurationPage-BgCLcjXO.mjs.map} +1 -1
  6. package/dist/_chunks/{ComponentConfigurationPage-DJcn1DrO.js → ComponentConfigurationPage-DywpTZeV.js} +5 -6
  7. package/dist/_chunks/{ComponentConfigurationPage-DJcn1DrO.js.map → ComponentConfigurationPage-DywpTZeV.js.map} +1 -1
  8. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
  9. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
  10. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
  11. package/dist/_chunks/{EditConfigurationPage-DmCIb4kD.mjs → EditConfigurationPage-BNjOAHNS.mjs} +4 -4
  12. package/dist/_chunks/{EditConfigurationPage-DmCIb4kD.mjs.map → EditConfigurationPage-BNjOAHNS.mjs.map} +1 -1
  13. package/dist/_chunks/{EditConfigurationPage-tDtWj7R2.js → EditConfigurationPage-CxRlP5if.js} +5 -6
  14. package/dist/_chunks/{EditConfigurationPage-tDtWj7R2.js.map → EditConfigurationPage-CxRlP5if.js.map} +1 -1
  15. package/dist/_chunks/{EditViewPage-CoQEnFlC.js → EditViewPage-BRewdTqE.js} +101 -51
  16. package/dist/_chunks/EditViewPage-BRewdTqE.js.map +1 -0
  17. package/dist/_chunks/{EditViewPage-DvaV7U9b.mjs → EditViewPage-CD_hqc1J.mjs} +102 -51
  18. package/dist/_chunks/EditViewPage-CD_hqc1J.mjs.map +1 -0
  19. package/dist/_chunks/{Field-Cz_J9551.mjs → Field-BPkQ-3Ku.mjs} +631 -279
  20. package/dist/_chunks/Field-BPkQ-3Ku.mjs.map +1 -0
  21. package/dist/_chunks/{Field-ZdrmmQ4Y.js → Field-DwvmENVf.js} +634 -283
  22. package/dist/_chunks/Field-DwvmENVf.js.map +1 -0
  23. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
  24. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
  25. package/dist/_chunks/{Form-Bpig5rch.js → Form-C_Gwv8P_.js} +55 -38
  26. package/dist/_chunks/Form-C_Gwv8P_.js.map +1 -0
  27. package/dist/_chunks/{Form-Dxmihyw8.mjs → Form-Czi0cf_2.mjs} +55 -37
  28. package/dist/_chunks/Form-Czi0cf_2.mjs.map +1 -0
  29. package/dist/_chunks/{History-BfX6XmZK.js → History-C1TKAig-.js} +175 -129
  30. package/dist/_chunks/History-C1TKAig-.js.map +1 -0
  31. package/dist/_chunks/{History-BZP8n7KT.mjs → History-CIQHyi4T.mjs} +176 -129
  32. package/dist/_chunks/History-CIQHyi4T.mjs.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-B3CXj8PY.js → ListConfigurationPage-D-NGRLYu.js} +62 -51
  34. package/dist/_chunks/ListConfigurationPage-D-NGRLYu.js.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-DxKuVkKz.mjs → ListConfigurationPage-DcZsfyEL.mjs} +63 -52
  36. package/dist/_chunks/ListConfigurationPage-DcZsfyEL.mjs.map +1 -0
  37. package/dist/_chunks/{ListViewPage-D5D3tVPq.mjs → ListViewPage-C10McTK1.mjs} +152 -128
  38. package/dist/_chunks/ListViewPage-C10McTK1.mjs.map +1 -0
  39. package/dist/_chunks/{ListViewPage-Bk9VO__I.js → ListViewPage-xv5IQoZp.js} +155 -132
  40. package/dist/_chunks/ListViewPage-xv5IQoZp.js.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-DnMeuQCj.mjs → NoContentTypePage-CPc0Cd3S.mjs} +2 -2
  42. package/dist/_chunks/{NoContentTypePage-DnMeuQCj.mjs.map → NoContentTypePage-CPc0Cd3S.mjs.map} +1 -1
  43. package/dist/_chunks/{NoContentTypePage-DsB2F7Z1.js → NoContentTypePage-Dzw5Yj5u.js} +2 -2
  44. package/dist/_chunks/{NoContentTypePage-DsB2F7Z1.js.map → NoContentTypePage-Dzw5Yj5u.js.map} +1 -1
  45. package/dist/_chunks/{NoPermissionsPage-BQDM64_b.js → NoPermissionsPage-DAe5CDCC.js} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-BQDM64_b.js.map → NoPermissionsPage-DAe5CDCC.js.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-OyoME_Tf.mjs → NoPermissionsPage-wfPBh2_0.mjs} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-OyoME_Tf.mjs.map → NoPermissionsPage-wfPBh2_0.mjs.map} +1 -1
  49. package/dist/_chunks/Preview-B7LyGT_b.js +290 -0
  50. package/dist/_chunks/Preview-B7LyGT_b.js.map +1 -0
  51. package/dist/_chunks/Preview-BVFFm7uB.mjs +272 -0
  52. package/dist/_chunks/Preview-BVFFm7uB.mjs.map +1 -0
  53. package/dist/_chunks/{Relations-B6B3A3mb.js → Relations-BmYR1AjY.js} +76 -43
  54. package/dist/_chunks/Relations-BmYR1AjY.js.map +1 -0
  55. package/dist/_chunks/{Relations-BOYZmuWy.mjs → Relations-JPhWxk-s.mjs} +76 -42
  56. package/dist/_chunks/Relations-JPhWxk-s.mjs.map +1 -0
  57. package/dist/_chunks/{en-BN1bvFK7.js → en-BK8Xyl5I.js} +35 -18
  58. package/dist/_chunks/{en-BN1bvFK7.js.map → en-BK8Xyl5I.js.map} +1 -1
  59. package/dist/_chunks/{en-Dzv55oQw.mjs → en-Dtk_ot79.mjs} +35 -18
  60. package/dist/_chunks/{en-Dzv55oQw.mjs.map → en-Dtk_ot79.mjs.map} +1 -1
  61. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  62. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  63. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  64. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  65. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
  66. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
  67. package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
  68. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
  69. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
  70. package/dist/_chunks/{index-DzN3kBgx.js → index-C2Q_PLWj.js} +1165 -880
  71. package/dist/_chunks/index-C2Q_PLWj.js.map +1 -0
  72. package/dist/_chunks/{index-VHviNMeW.mjs → index-DLIkNVnQ.mjs} +1185 -900
  73. package/dist/_chunks/index-DLIkNVnQ.mjs.map +1 -0
  74. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  75. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  76. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  77. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  78. package/dist/_chunks/{layout-b91XRlD2.js → layout-7AsWJzZJ.js} +41 -24
  79. package/dist/_chunks/layout-7AsWJzZJ.js.map +1 -0
  80. package/dist/_chunks/{layout-CPn1PM6x.mjs → layout-qE8qkNH_.mjs} +42 -24
  81. package/dist/_chunks/layout-qE8qkNH_.mjs.map +1 -0
  82. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  83. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  84. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  85. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  86. package/dist/_chunks/{relations-BsqxS6tR.mjs → relations-BjHH_1Am.mjs} +6 -7
  87. package/dist/_chunks/relations-BjHH_1Am.mjs.map +1 -0
  88. package/dist/_chunks/{relations-CA7IYmcP.js → relations-EifVzf_2.js} +6 -7
  89. package/dist/_chunks/relations-EifVzf_2.js.map +1 -0
  90. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  91. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  92. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  93. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  94. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
  95. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
  96. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
  97. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
  98. package/dist/admin/index.js +2 -1
  99. package/dist/admin/index.js.map +1 -1
  100. package/dist/admin/index.mjs +8 -7
  101. package/dist/admin/src/exports.d.ts +1 -1
  102. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  103. package/dist/admin/src/history/index.d.ts +3 -0
  104. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  105. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  106. package/dist/admin/src/index.d.ts +1 -0
  107. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  108. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +8 -3
  109. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
  110. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  111. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  112. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  113. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  114. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +6 -58
  115. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  116. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  117. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  118. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  119. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  120. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  121. package/dist/admin/src/preview/constants.d.ts +1 -0
  122. package/dist/admin/src/preview/index.d.ts +4 -0
  123. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  124. package/dist/admin/src/preview/routes.d.ts +3 -0
  125. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  126. package/dist/admin/src/router.d.ts +1 -1
  127. package/dist/admin/src/services/api.d.ts +1 -1
  128. package/dist/admin/src/services/components.d.ts +2 -2
  129. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  130. package/dist/admin/src/services/documents.d.ts +19 -20
  131. package/dist/admin/src/services/init.d.ts +1 -1
  132. package/dist/admin/src/services/relations.d.ts +2 -2
  133. package/dist/admin/src/services/uid.d.ts +3 -3
  134. package/dist/admin/src/utils/validation.d.ts +4 -1
  135. package/dist/server/index.js +616 -299
  136. package/dist/server/index.js.map +1 -1
  137. package/dist/server/index.mjs +616 -298
  138. package/dist/server/index.mjs.map +1 -1
  139. package/dist/server/src/bootstrap.d.ts.map +1 -1
  140. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  141. package/dist/server/src/controllers/index.d.ts.map +1 -1
  142. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  143. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  144. package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
  145. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  146. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  147. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  148. package/dist/server/src/history/services/history.d.ts.map +1 -1
  149. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  150. package/dist/server/src/history/services/utils.d.ts +4 -4
  151. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  152. package/dist/server/src/index.d.ts +4 -4
  153. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  154. package/dist/server/src/preview/constants.d.ts +2 -0
  155. package/dist/server/src/preview/constants.d.ts.map +1 -0
  156. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  157. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  158. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  159. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  160. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  161. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  162. package/dist/server/src/preview/index.d.ts +4 -0
  163. package/dist/server/src/preview/index.d.ts.map +1 -0
  164. package/dist/server/src/preview/routes/index.d.ts +8 -0
  165. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  166. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  167. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  168. package/dist/server/src/preview/services/index.d.ts +16 -0
  169. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  170. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  171. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  172. package/dist/server/src/preview/services/preview.d.ts +12 -0
  173. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  174. package/dist/server/src/preview/utils.d.ts +19 -0
  175. package/dist/server/src/preview/utils.d.ts.map +1 -0
  176. package/dist/server/src/register.d.ts.map +1 -1
  177. package/dist/server/src/routes/index.d.ts.map +1 -1
  178. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  179. package/dist/server/src/services/document-metadata.d.ts +8 -8
  180. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  181. package/dist/server/src/services/index.d.ts +4 -4
  182. package/dist/server/src/services/index.d.ts.map +1 -1
  183. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  184. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  185. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  186. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  187. package/dist/server/src/utils/index.d.ts +2 -0
  188. package/dist/server/src/utils/index.d.ts.map +1 -1
  189. package/dist/shared/contracts/collection-types.d.ts +3 -1
  190. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  191. package/dist/shared/contracts/index.d.ts +1 -0
  192. package/dist/shared/contracts/index.d.ts.map +1 -1
  193. package/dist/shared/contracts/preview.d.ts +27 -0
  194. package/dist/shared/contracts/preview.d.ts.map +1 -0
  195. package/dist/shared/index.js +4 -0
  196. package/dist/shared/index.js.map +1 -1
  197. package/dist/shared/index.mjs +4 -0
  198. package/dist/shared/index.mjs.map +1 -1
  199. package/package.json +15 -15
  200. package/dist/_chunks/EditViewPage-CoQEnFlC.js.map +0 -1
  201. package/dist/_chunks/EditViewPage-DvaV7U9b.mjs.map +0 -1
  202. package/dist/_chunks/Field-Cz_J9551.mjs.map +0 -1
  203. package/dist/_chunks/Field-ZdrmmQ4Y.js.map +0 -1
  204. package/dist/_chunks/Form-Bpig5rch.js.map +0 -1
  205. package/dist/_chunks/Form-Dxmihyw8.mjs.map +0 -1
  206. package/dist/_chunks/History-BZP8n7KT.mjs.map +0 -1
  207. package/dist/_chunks/History-BfX6XmZK.js.map +0 -1
  208. package/dist/_chunks/ListConfigurationPage-B3CXj8PY.js.map +0 -1
  209. package/dist/_chunks/ListConfigurationPage-DxKuVkKz.mjs.map +0 -1
  210. package/dist/_chunks/ListViewPage-Bk9VO__I.js.map +0 -1
  211. package/dist/_chunks/ListViewPage-D5D3tVPq.mjs.map +0 -1
  212. package/dist/_chunks/Relations-B6B3A3mb.js.map +0 -1
  213. package/dist/_chunks/Relations-BOYZmuWy.mjs.map +0 -1
  214. package/dist/_chunks/index-DzN3kBgx.js.map +0 -1
  215. package/dist/_chunks/index-VHviNMeW.mjs.map +0 -1
  216. package/dist/_chunks/layout-CPn1PM6x.mjs.map +0 -1
  217. package/dist/_chunks/layout-b91XRlD2.js.map +0 -1
  218. package/dist/_chunks/relations-BsqxS6tR.mjs.map +0 -1
  219. package/dist/_chunks/relations-CA7IYmcP.js.map +0 -1
  220. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  221. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  222. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  223. package/strapi-server.js +0 -3
@@ -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,13 +523,47 @@ 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,
496
565
  isInitialized: false
497
566
  };
498
- const query = strapi2.db.query(HISTORY_VERSION_UID);
499
- const historyService = getService(strapi2, "history");
500
567
  const serviceUtils = createServiceUtils({ strapi: strapi2 });
501
568
  return {
502
569
  async bootstrap() {
@@ -504,73 +571,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
504
571
  return;
505
572
  }
506
573
  strapi2.documents.use(async (context, next) => {
507
- if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
508
- return next();
509
- }
510
- if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
511
- return next();
512
- }
513
- const contentTypeUid = context.contentType.uid;
514
- if (!contentTypeUid.startsWith("api::")) {
515
- return next();
516
- }
517
574
  const result = await next();
518
- const documentContext = {
519
- documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
520
- locale: context.params?.locale
521
- };
575
+ if (!shouldCreateHistoryVersion(context)) {
576
+ return result;
577
+ }
578
+ const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
522
579
  const defaultLocale = await serviceUtils.getDefaultLocale();
523
- const locale = documentContext.locale || defaultLocale;
524
- if (Array.isArray(locale)) {
525
- strapi2.log.warn(
526
- "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
527
- );
528
- return next();
580
+ const locales = fp.castArray(context.params?.locale || defaultLocale);
581
+ if (!locales.length) {
582
+ return result;
529
583
  }
530
- const document = await strapi2.documents(contentTypeUid).findOne({
531
- documentId: documentContext.documentId,
532
- locale,
533
- 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
+ )
534
599
  });
535
- const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
536
- const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
537
- const componentsSchemas = Object.keys(
538
- attributesSchema
539
- ).reduce((currentComponentSchemas, key) => {
540
- const fieldSchema = attributesSchema[key];
541
- if (fieldSchema.type === "component") {
542
- const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
543
- return {
544
- ...currentComponentSchemas,
545
- [fieldSchema.component]: componentSchema
546
- };
547
- }
548
- return currentComponentSchemas;
549
- }, {});
550
600
  await strapi2.db.transaction(async ({ onCommit }) => {
551
- onCommit(() => {
552
- historyService.createVersion({
553
- contentType: contentTypeUid,
554
- data: fp.omit(FIELDS_TO_IGNORE, document),
555
- schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
556
- componentsSchemas,
557
- relatedDocumentId: documentContext.documentId,
558
- locale,
559
- status
560
- });
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
+ }
561
613
  });
562
614
  });
563
615
  return result;
564
616
  });
565
- state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
617
+ state.deleteExpiredJob = nodeSchedule.scheduleJob("historyDaily", "0 0 * * *", () => {
566
618
  const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
567
619
  const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
568
- query.deleteMany({
620
+ strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
569
621
  where: {
570
622
  created_at: {
571
- $lt: expirationDate.toISOString()
623
+ $lt: expirationDate
572
624
  }
573
625
  }
626
+ }).catch((error) => {
627
+ if (error instanceof Error) {
628
+ strapi2.log.error("Error deleting expired history versions", error.message);
629
+ }
574
630
  });
575
631
  });
576
632
  state.isInitialized = true;
@@ -582,17 +638,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
582
638
  }
583
639
  };
584
640
  };
585
- const services$1 = {
641
+ const services$2 = {
586
642
  history: createHistoryService,
587
643
  lifecycles: createLifecyclesService
588
644
  };
589
- const info = { pluginName: "content-manager", type: "admin" };
645
+ const info$1 = { pluginName: "content-manager", type: "admin" };
590
646
  const historyVersionRouter = {
591
647
  type: "admin",
592
648
  routes: [
593
649
  {
594
650
  method: "GET",
595
- info,
651
+ info: info$1,
596
652
  path: "/history-versions",
597
653
  handler: "history-version.findMany",
598
654
  config: {
@@ -601,7 +657,7 @@ const historyVersionRouter = {
601
657
  },
602
658
  {
603
659
  method: "PUT",
604
- info,
660
+ info: info$1,
605
661
  path: "/history-versions/:versionId/restore",
606
662
  handler: "history-version.restoreVersion",
607
663
  config: {
@@ -610,7 +666,7 @@ const historyVersionRouter = {
610
666
  }
611
667
  ]
612
668
  };
613
- const routes$1 = {
669
+ const routes$2 = {
614
670
  "history-version": historyVersionRouter
615
671
  };
616
672
  const historyVersion = {
@@ -657,21 +713,21 @@ const historyVersion = {
657
713
  }
658
714
  }
659
715
  };
660
- const getFeature = () => {
716
+ const getFeature$1 = () => {
661
717
  if (strapi.ee.features.isEnabled("cms-content-history")) {
662
718
  return {
663
719
  register({ strapi: strapi2 }) {
664
720
  strapi2.get("models").add(historyVersion);
665
721
  },
666
722
  bootstrap({ strapi: strapi2 }) {
667
- getService(strapi2, "lifecycles").bootstrap();
723
+ getService$1(strapi2, "lifecycles").bootstrap();
668
724
  },
669
725
  destroy({ strapi: strapi2 }) {
670
- getService(strapi2, "lifecycles").destroy();
726
+ getService$1(strapi2, "lifecycles").destroy();
671
727
  },
672
- controllers: controllers$1,
673
- services: services$1,
674
- routes: routes$1
728
+ controllers: controllers$2,
729
+ services: services$2,
730
+ routes: routes$2
675
731
  };
676
732
  }
677
733
  return {
@@ -680,9 +736,205 @@ const getFeature = () => {
680
736
  }
681
737
  };
682
738
  };
683
- 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();
684
935
  const register = async ({ strapi: strapi2 }) => {
685
936
  await history.register?.({ strapi: strapi2 });
937
+ await preview.register?.({ strapi: strapi2 });
686
938
  };
687
939
  const ALLOWED_WEBHOOK_EVENTS = {
688
940
  ENTRY_PUBLISH: "entry.publish",
@@ -692,11 +944,12 @@ const bootstrap = async () => {
692
944
  Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
693
945
  strapi.get("webhookStore").addAllowedEvent(key, value);
694
946
  });
695
- getService$1("field-sizes").setCustomFieldInputSizes();
696
- await getService$1("components").syncConfigurations();
697
- await getService$1("content-types").syncConfigurations();
698
- 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();
699
951
  await history.bootstrap?.({ strapi });
952
+ await preview.bootstrap?.({ strapi });
700
953
  };
701
954
  const destroy = async ({ strapi: strapi2 }) => {
702
955
  await history.destroy?.({ strapi: strapi2 });
@@ -1186,7 +1439,8 @@ const admin = {
1186
1439
  };
1187
1440
  const routes = {
1188
1441
  admin,
1189
- ...history.routes ? history.routes : {}
1442
+ ...history.routes ? history.routes : {},
1443
+ ...preview.routes ? preview.routes : {}
1190
1444
  };
1191
1445
  const hasPermissionsSchema = strapiUtils.yup.object({
1192
1446
  actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
@@ -1197,6 +1451,11 @@ const { createPolicy } = strapiUtils.policy;
1197
1451
  const hasPermissions = createPolicy({
1198
1452
  name: "plugin::content-manager.hasPermissions",
1199
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
+ */
1200
1459
  handler(ctx, config = {}) {
1201
1460
  const { actions = [], hasAtLeastOne = false } = config;
1202
1461
  const { userAbility } = ctx.state;
@@ -1244,8 +1503,7 @@ const isSortable = (schema, name) => {
1244
1503
  if (!___default.default.has(schema.attributes, name)) {
1245
1504
  return false;
1246
1505
  }
1247
- if (schema.modelType === "component" && name === "id")
1248
- return false;
1506
+ if (schema.modelType === "component" && name === "id") return false;
1249
1507
  const attribute = schema.attributes[name];
1250
1508
  if (NON_SORTABLES.includes(attribute.type)) {
1251
1509
  return false;
@@ -1390,8 +1648,7 @@ const createDefaultSettings = async (schema) => {
1390
1648
  };
1391
1649
  };
1392
1650
  const syncSettings = async (configuration, schema) => {
1393
- if (fp.isEmpty(configuration.settings))
1394
- return createDefaultSettings(schema);
1651
+ if (fp.isEmpty(configuration.settings)) return createDefaultSettings(schema);
1395
1652
  const defaultField = getDefaultMainField(schema);
1396
1653
  const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
1397
1654
  return {
@@ -1438,7 +1695,7 @@ const createMetadasSchema = (schema) => {
1438
1695
  if (!value) {
1439
1696
  return strapiUtils.yup.string();
1440
1697
  }
1441
- const targetSchema = getService$1("content-types").findContentType(
1698
+ const targetSchema = getService$2("content-types").findContentType(
1442
1699
  schema.attributes[key].targetModel
1443
1700
  );
1444
1701
  if (!targetSchema) {
@@ -1567,8 +1824,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
1567
1824
  }
1568
1825
  switch (attribute.type) {
1569
1826
  case "relation": {
1570
- if (canCreate(attributePath))
1571
- return body2;
1827
+ if (canCreate(attributePath)) return body2;
1572
1828
  return fp.set(attributePath, { set: [] }, body2);
1573
1829
  }
1574
1830
  case "component": {
@@ -1578,8 +1834,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
1578
1834
  ]);
1579
1835
  }
1580
1836
  default: {
1581
- if (canCreate(attributePath))
1582
- return body2;
1837
+ if (canCreate(attributePath)) return body2;
1583
1838
  return fp.set(attributePath, null, body2);
1584
1839
  }
1585
1840
  }
@@ -1590,9 +1845,11 @@ const multipleLocaleSchema = strapiUtils.yup.lazy(
1590
1845
  (value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
1591
1846
  );
1592
1847
  const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
1593
- const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
1848
+ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
1594
1849
  const { allowMultipleLocales } = opts;
1595
- 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;
1596
1853
  const schema = strapiUtils.yup.object().shape({
1597
1854
  locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
1598
1855
  status: statusSchema
@@ -1605,7 +1862,7 @@ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales
1605
1862
  }
1606
1863
  };
1607
1864
  const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
1608
- const documentMetadata2 = getService$1("document-metadata");
1865
+ const documentMetadata2 = getService$2("document-metadata");
1609
1866
  const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
1610
1867
  let {
1611
1868
  meta: { availableLocales, availableStatus }
@@ -1631,8 +1888,8 @@ const createDocument = async (ctx, opts) => {
1631
1888
  const { userAbility, user } = ctx.state;
1632
1889
  const { model } = ctx.params;
1633
1890
  const { body } = ctx.request;
1634
- const documentManager2 = getService$1("document-manager");
1635
- 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 });
1636
1893
  if (permissionChecker2.cannot.create()) {
1637
1894
  throw new strapiUtils.errors.ForbiddenError();
1638
1895
  }
@@ -1640,7 +1897,7 @@ const createDocument = async (ctx, opts) => {
1640
1897
  const setCreator = strapiUtils.setCreatorFields({ user });
1641
1898
  const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1642
1899
  const sanitizedBody = await sanitizeFn(body);
1643
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
1900
+ const { locale, status } = await getDocumentLocaleAndStatus(body, model);
1644
1901
  return documentManager2.create(model, {
1645
1902
  data: sanitizedBody,
1646
1903
  locale,
@@ -1652,14 +1909,14 @@ const updateDocument = async (ctx, opts) => {
1652
1909
  const { userAbility, user } = ctx.state;
1653
1910
  const { id, model } = ctx.params;
1654
1911
  const { body } = ctx.request;
1655
- const documentManager2 = getService$1("document-manager");
1656
- 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 });
1657
1914
  if (permissionChecker2.cannot.update()) {
1658
1915
  throw new strapiUtils.errors.ForbiddenError();
1659
1916
  }
1660
1917
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1661
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1662
- const { locale } = await getDocumentLocaleAndStatus(body);
1918
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
1919
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1663
1920
  const [documentVersion, documentExists] = await Promise.all([
1664
1921
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1665
1922
  documentManager2.exists(model, id)
@@ -1675,7 +1932,7 @@ const updateDocument = async (ctx, opts) => {
1675
1932
  throw new strapiUtils.errors.ForbiddenError();
1676
1933
  }
1677
1934
  const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
1678
- const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
1935
+ const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
1679
1936
  const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1680
1937
  const sanitizedBody = await sanitizeFn(body);
1681
1938
  return documentManager2.update(documentVersion?.documentId || id, model, {
@@ -1689,15 +1946,15 @@ const collectionTypes = {
1689
1946
  const { userAbility } = ctx.state;
1690
1947
  const { model } = ctx.params;
1691
1948
  const { query } = ctx.request;
1692
- const documentMetadata2 = getService$1("document-metadata");
1693
- const documentManager2 = getService$1("document-manager");
1694
- 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 });
1695
1952
  if (permissionChecker2.cannot.read()) {
1696
1953
  return ctx.forbidden();
1697
1954
  }
1698
1955
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1699
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1700
- 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);
1701
1958
  const { results: documents, pagination } = await documentManager2.findPage(
1702
1959
  { ...permissionQuery, populate, locale, status },
1703
1960
  model
@@ -1725,14 +1982,14 @@ const collectionTypes = {
1725
1982
  async findOne(ctx) {
1726
1983
  const { userAbility } = ctx.state;
1727
1984
  const { model, id } = ctx.params;
1728
- const documentManager2 = getService$1("document-manager");
1729
- 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 });
1730
1987
  if (permissionChecker2.cannot.read()) {
1731
1988
  return ctx.forbidden();
1732
1989
  }
1733
1990
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1734
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1735
- 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);
1736
1993
  const version = await documentManager2.findOne(id, model, {
1737
1994
  populate,
1738
1995
  locale,
@@ -1747,7 +2004,7 @@ const collectionTypes = {
1747
2004
  permissionChecker2,
1748
2005
  model,
1749
2006
  // @ts-expect-error TODO: fix
1750
- { id, locale, publishedAt: null },
2007
+ { documentId: id, locale, publishedAt: null },
1751
2008
  { availableLocales: true, availableStatus: false }
1752
2009
  );
1753
2010
  ctx.body = { data: {}, meta };
@@ -1762,7 +2019,7 @@ const collectionTypes = {
1762
2019
  async create(ctx) {
1763
2020
  const { userAbility } = ctx.state;
1764
2021
  const { model } = ctx.params;
1765
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2022
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1766
2023
  const [totalEntries, document] = await Promise.all([
1767
2024
  strapi.db.query(model).count(),
1768
2025
  createDocument(ctx)
@@ -1783,7 +2040,7 @@ const collectionTypes = {
1783
2040
  async update(ctx) {
1784
2041
  const { userAbility } = ctx.state;
1785
2042
  const { model } = ctx.params;
1786
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2043
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1787
2044
  const updatedVersion = await updateDocument(ctx);
1788
2045
  const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
1789
2046
  ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
@@ -1792,14 +2049,14 @@ const collectionTypes = {
1792
2049
  const { userAbility, user } = ctx.state;
1793
2050
  const { model, sourceId: id } = ctx.params;
1794
2051
  const { body } = ctx.request;
1795
- const documentManager2 = getService$1("document-manager");
1796
- 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 });
1797
2054
  if (permissionChecker2.cannot.create()) {
1798
2055
  return ctx.forbidden();
1799
2056
  }
1800
2057
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1801
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1802
- const { locale } = await getDocumentLocaleAndStatus(body);
2058
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2059
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1803
2060
  const document = await documentManager2.findOne(id, model, {
1804
2061
  populate,
1805
2062
  locale,
@@ -1837,14 +2094,14 @@ const collectionTypes = {
1837
2094
  async delete(ctx) {
1838
2095
  const { userAbility } = ctx.state;
1839
2096
  const { id, model } = ctx.params;
1840
- const documentManager2 = getService$1("document-manager");
1841
- 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 });
1842
2099
  if (permissionChecker2.cannot.delete()) {
1843
2100
  return ctx.forbidden();
1844
2101
  }
1845
2102
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1846
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1847
- 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);
1848
2105
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1849
2106
  if (documentLocales.length === 0) {
1850
2107
  return ctx.notFound();
@@ -1865,19 +2122,42 @@ const collectionTypes = {
1865
2122
  const { userAbility } = ctx.state;
1866
2123
  const { id, model } = ctx.params;
1867
2124
  const { body } = ctx.request;
1868
- const documentManager2 = getService$1("document-manager");
1869
- 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 });
1870
2127
  if (permissionChecker2.cannot.publish()) {
1871
2128
  return ctx.forbidden();
1872
2129
  }
1873
2130
  const publishedDocument = await strapi.db.transaction(async () => {
1874
2131
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1875
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1876
- 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
+ }
1877
2158
  if (permissionChecker2.cannot.publish(document)) {
1878
2159
  throw new strapiUtils.errors.ForbiddenError();
1879
2160
  }
1880
- const { locale } = await getDocumentLocaleAndStatus(body);
1881
2161
  const publishResult = await documentManager2.publish(document.documentId, model, {
1882
2162
  locale
1883
2163
  // TODO: Allow setting creator fields on publish
@@ -1897,14 +2177,16 @@ const collectionTypes = {
1897
2177
  const { body } = ctx.request;
1898
2178
  const { documentIds } = body;
1899
2179
  await validateBulkActionInput(body);
1900
- const documentManager2 = getService$1("document-manager");
1901
- 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 });
1902
2182
  if (permissionChecker2.cannot.publish()) {
1903
2183
  return ctx.forbidden();
1904
2184
  }
1905
2185
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1906
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1907
- 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
+ });
1908
2190
  const entityPromises = documentIds.map(
1909
2191
  (documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
1910
2192
  );
@@ -1926,12 +2208,14 @@ const collectionTypes = {
1926
2208
  const { body } = ctx.request;
1927
2209
  const { documentIds } = body;
1928
2210
  await validateBulkActionInput(body);
1929
- const documentManager2 = getService$1("document-manager");
1930
- 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 });
1931
2213
  if (permissionChecker2.cannot.unpublish()) {
1932
2214
  return ctx.forbidden();
1933
2215
  }
1934
- const { locale } = await getDocumentLocaleAndStatus(body);
2216
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
2217
+ allowMultipleLocales: true
2218
+ });
1935
2219
  const entityPromises = documentIds.map(
1936
2220
  (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1937
2221
  );
@@ -1954,8 +2238,8 @@ const collectionTypes = {
1954
2238
  const {
1955
2239
  body: { discardDraft, ...body }
1956
2240
  } = ctx.request;
1957
- const documentManager2 = getService$1("document-manager");
1958
- 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 });
1959
2243
  if (permissionChecker2.cannot.unpublish()) {
1960
2244
  return ctx.forbidden();
1961
2245
  }
@@ -1963,8 +2247,8 @@ const collectionTypes = {
1963
2247
  return ctx.forbidden();
1964
2248
  }
1965
2249
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1966
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1967
- const { locale } = await getDocumentLocaleAndStatus(body);
2250
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2251
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1968
2252
  const document = await documentManager2.findOne(id, model, {
1969
2253
  populate,
1970
2254
  locale,
@@ -1994,14 +2278,14 @@ const collectionTypes = {
1994
2278
  const { userAbility } = ctx.state;
1995
2279
  const { id, model } = ctx.params;
1996
2280
  const { body } = ctx.request;
1997
- const documentManager2 = getService$1("document-manager");
1998
- 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 });
1999
2283
  if (permissionChecker2.cannot.discard()) {
2000
2284
  return ctx.forbidden();
2001
2285
  }
2002
2286
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
2003
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2004
- const { locale } = await getDocumentLocaleAndStatus(body);
2287
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2288
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2005
2289
  const document = await documentManager2.findOne(id, model, {
2006
2290
  populate,
2007
2291
  locale,
@@ -2025,14 +2309,14 @@ const collectionTypes = {
2025
2309
  const { query, body } = ctx.request;
2026
2310
  const { documentIds } = body;
2027
2311
  await validateBulkActionInput(body);
2028
- const documentManager2 = getService$1("document-manager");
2029
- 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 });
2030
2314
  if (permissionChecker2.cannot.delete()) {
2031
2315
  return ctx.forbidden();
2032
2316
  }
2033
2317
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
2034
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2035
- const { locale } = await getDocumentLocaleAndStatus(body);
2318
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2319
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2036
2320
  const documentLocales = await documentManager2.findLocales(documentIds, model, {
2037
2321
  populate,
2038
2322
  locale
@@ -2052,14 +2336,14 @@ const collectionTypes = {
2052
2336
  async countDraftRelations(ctx) {
2053
2337
  const { userAbility } = ctx.state;
2054
2338
  const { model, id } = ctx.params;
2055
- const documentManager2 = getService$1("document-manager");
2056
- 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 });
2057
2341
  if (permissionChecker2.cannot.read()) {
2058
2342
  return ctx.forbidden();
2059
2343
  }
2060
2344
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2061
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2062
- 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);
2063
2347
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
2064
2348
  if (!entity) {
2065
2349
  return ctx.notFound();
@@ -2077,12 +2361,12 @@ const collectionTypes = {
2077
2361
  const ids = ctx.request.query.documentIds;
2078
2362
  const locale = ctx.request.query.locale;
2079
2363
  const { model } = ctx.params;
2080
- const documentManager2 = getService$1("document-manager");
2081
- 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 });
2082
2366
  if (permissionChecker2.cannot.read()) {
2083
2367
  return ctx.forbidden();
2084
2368
  }
2085
- const entities = await documentManager2.findMany(
2369
+ const documents = await documentManager2.findMany(
2086
2370
  {
2087
2371
  filters: {
2088
2372
  documentId: ids
@@ -2091,7 +2375,7 @@ const collectionTypes = {
2091
2375
  },
2092
2376
  model
2093
2377
  );
2094
- if (!entities) {
2378
+ if (!documents) {
2095
2379
  return ctx.notFound();
2096
2380
  }
2097
2381
  const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
@@ -2102,13 +2386,13 @@ const collectionTypes = {
2102
2386
  };
2103
2387
  const components$1 = {
2104
2388
  findComponents(ctx) {
2105
- const components2 = getService$1("components").findAllComponents();
2106
- const { toDto } = getService$1("data-mapper");
2389
+ const components2 = getService$2("components").findAllComponents();
2390
+ const { toDto } = getService$2("data-mapper");
2107
2391
  ctx.body = { data: components2.map(toDto) };
2108
2392
  },
2109
2393
  async findComponentConfiguration(ctx) {
2110
2394
  const { uid: uid2 } = ctx.params;
2111
- const componentService = getService$1("components");
2395
+ const componentService = getService$2("components");
2112
2396
  const component = componentService.findComponent(uid2);
2113
2397
  if (!component) {
2114
2398
  return ctx.notFound("component.notFound");
@@ -2125,7 +2409,7 @@ const components$1 = {
2125
2409
  async updateComponentConfiguration(ctx) {
2126
2410
  const { uid: uid2 } = ctx.params;
2127
2411
  const { body } = ctx.request;
2128
- const componentService = getService$1("components");
2412
+ const componentService = getService$2("components");
2129
2413
  const component = componentService.findComponent(uid2);
2130
2414
  if (!component) {
2131
2415
  return ctx.notFound("component.notFound");
@@ -2159,12 +2443,12 @@ const contentTypes = {
2159
2443
  } catch (error) {
2160
2444
  return ctx.send({ error }, 400);
2161
2445
  }
2162
- const contentTypes2 = getService$1("content-types").findContentTypesByKind(kind);
2163
- const { toDto } = getService$1("data-mapper");
2446
+ const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
2447
+ const { toDto } = getService$2("data-mapper");
2164
2448
  ctx.body = { data: contentTypes2.map(toDto) };
2165
2449
  },
2166
2450
  async findContentTypesSettings(ctx) {
2167
- const { findAllContentTypes, findConfiguration } = getService$1("content-types");
2451
+ const { findAllContentTypes, findConfiguration } = getService$2("content-types");
2168
2452
  const contentTypes2 = await findAllContentTypes();
2169
2453
  const configurations = await Promise.all(
2170
2454
  contentTypes2.map(async (contentType) => {
@@ -2178,7 +2462,7 @@ const contentTypes = {
2178
2462
  },
2179
2463
  async findContentTypeConfiguration(ctx) {
2180
2464
  const { uid: uid2 } = ctx.params;
2181
- const contentTypeService = getService$1("content-types");
2465
+ const contentTypeService = getService$2("content-types");
2182
2466
  const contentType = await contentTypeService.findContentType(uid2);
2183
2467
  if (!contentType) {
2184
2468
  return ctx.notFound("contentType.notFound");
@@ -2200,13 +2484,13 @@ const contentTypes = {
2200
2484
  const { userAbility } = ctx.state;
2201
2485
  const { uid: uid2 } = ctx.params;
2202
2486
  const { body } = ctx.request;
2203
- const contentTypeService = getService$1("content-types");
2204
- const metricsService = getService$1("metrics");
2487
+ const contentTypeService = getService$2("content-types");
2488
+ const metricsService = getService$2("metrics");
2205
2489
  const contentType = await contentTypeService.findContentType(uid2);
2206
2490
  if (!contentType) {
2207
2491
  return ctx.notFound("contentType.notFound");
2208
2492
  }
2209
- if (!getService$1("permission").canConfigureContentType({ userAbility, contentType })) {
2493
+ if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
2210
2494
  return ctx.forbidden();
2211
2495
  }
2212
2496
  let input;
@@ -2239,10 +2523,10 @@ const contentTypes = {
2239
2523
  };
2240
2524
  const init = {
2241
2525
  getInitData(ctx) {
2242
- const { toDto } = getService$1("data-mapper");
2243
- const { findAllComponents } = getService$1("components");
2244
- const { getAllFieldSizes } = getService$1("field-sizes");
2245
- 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");
2246
2530
  ctx.body = {
2247
2531
  data: {
2248
2532
  fieldSizes: getAllFieldSizes(),
@@ -2278,36 +2562,41 @@ const addFiltersClause = (params, filtersClause) => {
2278
2562
  params.filters.$and.push(filtersClause);
2279
2563
  };
2280
2564
  const sanitizeMainField = (model, mainField, userAbility) => {
2281
- const permissionChecker2 = getService$1("permission-checker").create({
2565
+ const permissionChecker2 = getService$2("permission-checker").create({
2282
2566
  userAbility,
2283
2567
  model: model.uid
2284
2568
  });
2285
- if (!isListable(model, mainField)) {
2569
+ const isMainFieldListable = isListable(model, mainField);
2570
+ const canReadMainField = permissionChecker2.can.read(null, mainField);
2571
+ if (!isMainFieldListable || !canReadMainField) {
2286
2572
  return "id";
2287
2573
  }
2288
- if (permissionChecker2.cannot.read(null, mainField)) {
2289
- if (model.uid === "plugin::users-permissions.role") {
2290
- const userPermissionChecker = getService$1("permission-checker").create({
2291
- userAbility,
2292
- model: "plugin::users-permissions.user"
2293
- });
2294
- if (userPermissionChecker.can.read()) {
2295
- return "name";
2296
- }
2297
- }
2298
- return "id";
2574
+ if (model.uid === "plugin::users-permissions.role") {
2575
+ return "name";
2299
2576
  }
2300
2577
  return mainField;
2301
2578
  };
2302
- const addStatusToRelations = async (uid2, relations2) => {
2303
- if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.contentTypes[uid2])) {
2579
+ const addStatusToRelations = async (targetUid, relations2) => {
2580
+ if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {
2304
2581
  return relations2;
2305
2582
  }
2306
- const documentMetadata2 = getService$1("document-metadata");
2307
- 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
+ });
2308
2597
  return relations2.map((relation) => {
2309
- const availableStatuses = documentsAvailableStatus.filter(
2310
- (availableDocument) => availableDocument.documentId === relation.documentId
2598
+ const availableStatuses = availableStatus.filter(
2599
+ (availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
2311
2600
  );
2312
2601
  return {
2313
2602
  ...relation,
@@ -2328,11 +2617,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
2328
2617
  const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
2329
2618
  const isSourceLocalized = isLocalized(sourceModel);
2330
2619
  const isTargetLocalized = isLocalized(targetModel);
2331
- let validatedLocale = locale;
2332
- if (!targetModel || !isTargetLocalized)
2333
- validatedLocale = void 0;
2334
2620
  return {
2335
- locale: validatedLocale,
2621
+ locale,
2336
2622
  isSourceLocalized,
2337
2623
  isTargetLocalized
2338
2624
  };
@@ -2341,8 +2627,7 @@ const validateStatus = (sourceUid, status) => {
2341
2627
  const sourceModel = strapi.getModel(sourceUid);
2342
2628
  const isDP = strapiUtils.contentTypes.hasDraftAndPublish;
2343
2629
  const isSourceDP = isDP(sourceModel);
2344
- if (!isSourceDP)
2345
- return { status: void 0 };
2630
+ if (!isSourceDP) return { status: void 0 };
2346
2631
  switch (status) {
2347
2632
  case "published":
2348
2633
  return { status: "published" };
@@ -2372,7 +2657,7 @@ const relations = {
2372
2657
  ctx.request?.query?.locale
2373
2658
  );
2374
2659
  const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
2375
- const permissionChecker2 = getService$1("permission-checker").create({
2660
+ const permissionChecker2 = getService$2("permission-checker").create({
2376
2661
  userAbility,
2377
2662
  model
2378
2663
  });
@@ -2397,7 +2682,7 @@ const relations = {
2397
2682
  where.id = id;
2398
2683
  }
2399
2684
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2400
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2685
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2401
2686
  const currentEntity = await strapi.db.query(model).findOne({
2402
2687
  where,
2403
2688
  populate
@@ -2412,7 +2697,7 @@ const relations = {
2412
2697
  }
2413
2698
  entryId = currentEntity.id;
2414
2699
  }
2415
- 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);
2416
2701
  const targetSchema = strapi.getModel(targetUid);
2417
2702
  const mainField = fp.flow(
2418
2703
  fp.prop(`metadatas.${targetField}.edit.mainField`),
@@ -2435,7 +2720,7 @@ const relations = {
2435
2720
  attribute,
2436
2721
  fieldsToSelect,
2437
2722
  mainField,
2438
- source: { schema: sourceSchema },
2723
+ source: { schema: sourceSchema, isLocalized: isSourceLocalized },
2439
2724
  target: { schema: targetSchema, isLocalized: isTargetLocalized },
2440
2725
  sourceSchema,
2441
2726
  targetSchema,
@@ -2457,7 +2742,8 @@ const relations = {
2457
2742
  fieldsToSelect,
2458
2743
  mainField,
2459
2744
  source: {
2460
- schema: { uid: sourceUid, modelType: sourceModelType }
2745
+ schema: { uid: sourceUid, modelType: sourceModelType },
2746
+ isLocalized: isSourceLocalized
2461
2747
  },
2462
2748
  target: {
2463
2749
  schema: { uid: targetUid },
@@ -2465,7 +2751,7 @@ const relations = {
2465
2751
  }
2466
2752
  } = await this.extractAndValidateRequestInfo(ctx, id);
2467
2753
  const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
2468
- const permissionChecker2 = getService$1("permission-checker").create({
2754
+ const permissionChecker2 = getService$2("permission-checker").create({
2469
2755
  userAbility: ctx.state.userAbility,
2470
2756
  model: targetUid
2471
2757
  });
@@ -2495,12 +2781,16 @@ const relations = {
2495
2781
  } else {
2496
2782
  where.id = id;
2497
2783
  }
2498
- if (status) {
2499
- where[`${alias}.published_at`] = getPublishedAtClause(status, targetUid);
2784
+ const publishedAt = getPublishedAtClause(status, targetUid);
2785
+ if (!fp.isEmpty(publishedAt)) {
2786
+ where[`${alias}.published_at`] = publishedAt;
2500
2787
  }
2501
- if (filterByLocale) {
2788
+ if (isTargetLocalized && locale) {
2502
2789
  where[`${alias}.locale`] = locale;
2503
2790
  }
2791
+ if (isSourceLocalized && locale) {
2792
+ where.locale = locale;
2793
+ }
2504
2794
  if ((idsToInclude?.length ?? 0) !== 0) {
2505
2795
  where[`${alias}.id`].$notIn = idsToInclude;
2506
2796
  }
@@ -2518,7 +2808,8 @@ const relations = {
2518
2808
  id: { $notIn: fp.uniq(idsToOmit) }
2519
2809
  });
2520
2810
  }
2521
- 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);
2522
2813
  ctx.body = {
2523
2814
  ...res,
2524
2815
  results: await addStatusToRelations(targetUid, res.results)
@@ -2533,29 +2824,39 @@ const relations = {
2533
2824
  attribute,
2534
2825
  targetField,
2535
2826
  fieldsToSelect,
2536
- source: {
2537
- schema: { uid: sourceUid }
2538
- },
2539
- target: {
2540
- schema: { uid: targetUid }
2541
- }
2827
+ status,
2828
+ source: { schema: sourceSchema },
2829
+ target: { schema: targetSchema }
2542
2830
  } = await this.extractAndValidateRequestInfo(ctx, id);
2543
- 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 });
2544
2834
  const dbQuery = strapi.db.query(sourceUid);
2545
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
+ }
2546
2848
  const res = await loadRelations({ id: entryId }, targetField, {
2547
- select: ["id", "documentId", "locale", "publishedAt"],
2849
+ select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
2548
2850
  ordering: "desc",
2549
2851
  page: ctx.request.query.page,
2550
- pageSize: ctx.request.query.pageSize
2852
+ pageSize: ctx.request.query.pageSize,
2853
+ filters
2551
2854
  });
2552
2855
  const loadedIds = res.results.map((item) => item.id);
2553
2856
  addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
2554
2857
  const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
2555
2858
  ...strapi.get("query-params").transform(targetUid, permissionQuery),
2556
- ordering: "desc",
2557
- page: ctx.request.query.page,
2558
- pageSize: ctx.request.query.pageSize
2859
+ ordering: "desc"
2559
2860
  });
2560
2861
  const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
2561
2862
  ctx.body = {
@@ -2570,10 +2871,10 @@ const relations = {
2570
2871
  }
2571
2872
  };
2572
2873
  const buildPopulateFromQuery = async (query, model) => {
2573
- 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();
2574
2875
  };
2575
2876
  const findDocument = async (query, uid2, opts = {}) => {
2576
- const documentManager2 = getService$1("document-manager");
2877
+ const documentManager2 = getService$2("document-manager");
2577
2878
  const populate = await buildPopulateFromQuery(query, uid2);
2578
2879
  return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
2579
2880
  };
@@ -2581,13 +2882,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
2581
2882
  const { user, userAbility } = ctx.state;
2582
2883
  const { model } = ctx.params;
2583
2884
  const { body, query } = ctx.request;
2584
- const documentManager2 = getService$1("document-manager");
2585
- 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 });
2586
2887
  if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
2587
2888
  throw new strapiUtils.errors.ForbiddenError();
2588
2889
  }
2589
2890
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2590
- const { locale } = await getDocumentLocaleAndStatus(body);
2891
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2591
2892
  const [documentVersion, otherDocumentVersion] = await Promise.all([
2592
2893
  findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2593
2894
  // Find the first document to check if it exists
@@ -2623,12 +2924,12 @@ const singleTypes = {
2623
2924
  const { userAbility } = ctx.state;
2624
2925
  const { model } = ctx.params;
2625
2926
  const { query = {} } = ctx.request;
2626
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2927
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2627
2928
  if (permissionChecker2.cannot.read()) {
2628
2929
  return ctx.forbidden();
2629
2930
  }
2630
2931
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2631
- const { locale, status } = await getDocumentLocaleAndStatus(query);
2932
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
2632
2933
  const version = await findDocument(permissionQuery, model, { locale, status });
2633
2934
  if (!version) {
2634
2935
  if (permissionChecker2.cannot.create()) {
@@ -2642,7 +2943,7 @@ const singleTypes = {
2642
2943
  permissionChecker2,
2643
2944
  model,
2644
2945
  // @ts-expect-error - fix types
2645
- { id: document.documentId, locale, publishedAt: null },
2946
+ { documentId: document.documentId, locale, publishedAt: null },
2646
2947
  { availableLocales: true, availableStatus: false }
2647
2948
  );
2648
2949
  ctx.body = { data: {}, meta };
@@ -2657,7 +2958,7 @@ const singleTypes = {
2657
2958
  async createOrUpdate(ctx) {
2658
2959
  const { userAbility } = ctx.state;
2659
2960
  const { model } = ctx.params;
2660
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2961
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2661
2962
  const document = await createOrUpdateDocument(ctx);
2662
2963
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
2663
2964
  ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
@@ -2666,14 +2967,14 @@ const singleTypes = {
2666
2967
  const { userAbility } = ctx.state;
2667
2968
  const { model } = ctx.params;
2668
2969
  const { query = {} } = ctx.request;
2669
- const documentManager2 = getService$1("document-manager");
2670
- 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 });
2671
2972
  if (permissionChecker2.cannot.delete()) {
2672
2973
  return ctx.forbidden();
2673
2974
  }
2674
2975
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2675
2976
  const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2676
- const { locale } = await getDocumentLocaleAndStatus(query);
2977
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2677
2978
  const documentLocales = await documentManager2.findLocales(void 0, model, {
2678
2979
  populate,
2679
2980
  locale
@@ -2695,8 +2996,8 @@ const singleTypes = {
2695
2996
  const { userAbility } = ctx.state;
2696
2997
  const { model } = ctx.params;
2697
2998
  const { query = {} } = ctx.request;
2698
- const documentManager2 = getService$1("document-manager");
2699
- 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 });
2700
3001
  if (permissionChecker2.cannot.publish()) {
2701
3002
  return ctx.forbidden();
2702
3003
  }
@@ -2710,7 +3011,7 @@ const singleTypes = {
2710
3011
  if (permissionChecker2.cannot.publish(document)) {
2711
3012
  throw new strapiUtils.errors.ForbiddenError();
2712
3013
  }
2713
- const { locale } = await getDocumentLocaleAndStatus(document);
3014
+ const { locale } = await getDocumentLocaleAndStatus(document, model);
2714
3015
  const publishResult = await documentManager2.publish(document.documentId, model, { locale });
2715
3016
  return publishResult.at(0);
2716
3017
  });
@@ -2724,8 +3025,8 @@ const singleTypes = {
2724
3025
  body: { discardDraft, ...body },
2725
3026
  query = {}
2726
3027
  } = ctx.request;
2727
- const documentManager2 = getService$1("document-manager");
2728
- 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 });
2729
3030
  if (permissionChecker2.cannot.unpublish()) {
2730
3031
  return ctx.forbidden();
2731
3032
  }
@@ -2733,7 +3034,7 @@ const singleTypes = {
2733
3034
  return ctx.forbidden();
2734
3035
  }
2735
3036
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2736
- const { locale } = await getDocumentLocaleAndStatus(body);
3037
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2737
3038
  const document = await findDocument(sanitizedQuery, model, { locale });
2738
3039
  if (!document) {
2739
3040
  return ctx.notFound();
@@ -2759,13 +3060,13 @@ const singleTypes = {
2759
3060
  const { userAbility } = ctx.state;
2760
3061
  const { model } = ctx.params;
2761
3062
  const { body, query = {} } = ctx.request;
2762
- const documentManager2 = getService$1("document-manager");
2763
- 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 });
2764
3065
  if (permissionChecker2.cannot.discard()) {
2765
3066
  return ctx.forbidden();
2766
3067
  }
2767
3068
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2768
- const { locale } = await getDocumentLocaleAndStatus(body);
3069
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2769
3070
  const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2770
3071
  if (!document) {
2771
3072
  return ctx.notFound();
@@ -2783,9 +3084,9 @@ const singleTypes = {
2783
3084
  const { userAbility } = ctx.state;
2784
3085
  const { model } = ctx.params;
2785
3086
  const { query } = ctx.request;
2786
- const documentManager2 = getService$1("document-manager");
2787
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2788
- 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);
2789
3090
  if (permissionChecker2.cannot.read()) {
2790
3091
  return ctx.forbidden();
2791
3092
  }
@@ -2806,9 +3107,9 @@ const uid$1 = {
2806
3107
  async generateUID(ctx) {
2807
3108
  const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2808
3109
  const { query = {} } = ctx.request;
2809
- const { locale } = await getDocumentLocaleAndStatus(query);
3110
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2810
3111
  await validateUIDField(contentTypeUID, field);
2811
- const uidService = getService$1("uid");
3112
+ const uidService = getService$2("uid");
2812
3113
  ctx.body = {
2813
3114
  data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
2814
3115
  };
@@ -2818,9 +3119,9 @@ const uid$1 = {
2818
3119
  ctx.request.body
2819
3120
  );
2820
3121
  const { query = {} } = ctx.request;
2821
- const { locale } = await getDocumentLocaleAndStatus(query);
3122
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2822
3123
  await validateUIDField(contentTypeUID, field);
2823
- const uidService = getService$1("uid");
3124
+ const uidService = getService$2("uid");
2824
3125
  const isAvailable = await uidService.checkUIDAvailability({
2825
3126
  contentTypeUID,
2826
3127
  field,
@@ -2841,7 +3142,8 @@ const controllers = {
2841
3142
  relations,
2842
3143
  "single-types": singleTypes,
2843
3144
  uid: uid$1,
2844
- ...history.controllers ? history.controllers : {}
3145
+ ...history.controllers ? history.controllers : {},
3146
+ ...preview.controllers ? preview.controllers : {}
2845
3147
  };
2846
3148
  const keys = {
2847
3149
  CONFIGURATION: "configuration"
@@ -2970,18 +3272,15 @@ async function syncMetadatas(configuration, schema) {
2970
3272
  ___default.default.set(updatedMeta, ["list", "searchable"], false);
2971
3273
  ___default.default.set(acc, [key], updatedMeta);
2972
3274
  }
2973
- if (!___default.default.has(edit, "mainField"))
2974
- return acc;
3275
+ if (!___default.default.has(edit, "mainField")) return acc;
2975
3276
  if (!isRelation$1(attr)) {
2976
3277
  ___default.default.set(updatedMeta, "edit", ___default.default.omit(edit, ["mainField"]));
2977
3278
  ___default.default.set(acc, [key], updatedMeta);
2978
3279
  return acc;
2979
3280
  }
2980
- if (edit.mainField === "id")
2981
- return acc;
3281
+ if (edit.mainField === "id") return acc;
2982
3282
  const targetSchema = getTargetSchema(attr.targetModel);
2983
- if (!targetSchema)
2984
- return acc;
3283
+ if (!targetSchema) return acc;
2985
3284
  if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
2986
3285
  ___default.default.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
2987
3286
  ___default.default.set(acc, [key], updatedMeta);
@@ -2992,12 +3291,12 @@ async function syncMetadatas(configuration, schema) {
2992
3291
  return ___default.default.assign(metasWithDefaults, updatedMetas);
2993
3292
  }
2994
3293
  const getTargetSchema = (targetModel) => {
2995
- return getService$1("content-types").findContentType(targetModel);
3294
+ return getService$2("content-types").findContentType(targetModel);
2996
3295
  };
2997
3296
  const DEFAULT_LIST_LENGTH = 4;
2998
3297
  const MAX_ROW_SIZE = 12;
2999
3298
  const isAllowedFieldSize = (type, size) => {
3000
- const { getFieldSize } = getService$1("field-sizes");
3299
+ const { getFieldSize } = getService$2("field-sizes");
3001
3300
  const fieldSize = getFieldSize(type);
3002
3301
  if (!fieldSize.isResizable && size !== fieldSize.default) {
3003
3302
  return false;
@@ -3005,7 +3304,7 @@ const isAllowedFieldSize = (type, size) => {
3005
3304
  return size <= MAX_ROW_SIZE;
3006
3305
  };
3007
3306
  const getDefaultFieldSize = (attribute) => {
3008
- const { hasFieldSize, getFieldSize } = getService$1("field-sizes");
3307
+ const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
3009
3308
  return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
3010
3309
  };
3011
3310
  async function createDefaultLayouts(schema) {
@@ -3026,8 +3325,7 @@ function createDefaultEditLayout(schema) {
3026
3325
  return appendToEditLayout([], keys2, schema);
3027
3326
  }
3028
3327
  function syncLayouts(configuration, schema) {
3029
- if (___default.default.isEmpty(configuration.layouts))
3030
- return createDefaultLayouts(schema);
3328
+ if (___default.default.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
3031
3329
  const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
3032
3330
  let cleanList = list.filter((attr) => isListable(schema, attr));
3033
3331
  const cleanEditRelations = editRelations.filter(
@@ -3038,9 +3336,8 @@ function syncLayouts(configuration, schema) {
3038
3336
  for (const row of edit) {
3039
3337
  const newRow = [];
3040
3338
  for (const el of row) {
3041
- if (!hasEditableAttribute(schema, el.name))
3042
- continue;
3043
- const { hasFieldSize } = getService$1("field-sizes");
3339
+ if (!hasEditableAttribute(schema, el.name)) continue;
3340
+ const { hasFieldSize } = getService$2("field-sizes");
3044
3341
  const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
3045
3342
  if (!isAllowedFieldSize(fieldType, el.size)) {
3046
3343
  elementsToReAppend.push(el.name);
@@ -3070,8 +3367,7 @@ function syncLayouts(configuration, schema) {
3070
3367
  };
3071
3368
  }
3072
3369
  const appendToEditLayout = (layout = [], keysToAppend, schema) => {
3073
- if (keysToAppend.length === 0)
3074
- return layout;
3370
+ if (keysToAppend.length === 0) return layout;
3075
3371
  let currentRowIndex = Math.max(layout.length - 1, 0);
3076
3372
  if (!layout[currentRowIndex]) {
3077
3373
  layout[currentRowIndex] = [];
@@ -3180,17 +3476,17 @@ const configurationService$1 = createConfigurationService({
3180
3476
  isComponent: true,
3181
3477
  prefix: STORE_KEY_PREFIX,
3182
3478
  getModels() {
3183
- const { toContentManagerModel } = getService$1("data-mapper");
3479
+ const { toContentManagerModel } = getService$2("data-mapper");
3184
3480
  return fp.mapValues(toContentManagerModel, strapi.components);
3185
3481
  }
3186
3482
  });
3187
3483
  const components = ({ strapi: strapi2 }) => ({
3188
3484
  findAllComponents() {
3189
- const { toContentManagerModel } = getService$1("data-mapper");
3485
+ const { toContentManagerModel } = getService$2("data-mapper");
3190
3486
  return Object.values(strapi2.components).map(toContentManagerModel);
3191
3487
  },
3192
3488
  findComponent(uid2) {
3193
- const { toContentManagerModel } = getService$1("data-mapper");
3489
+ const { toContentManagerModel } = getService$2("data-mapper");
3194
3490
  const component = strapi2.components[uid2];
3195
3491
  return fp.isNil(component) ? component : toContentManagerModel(component);
3196
3492
  },
@@ -3241,17 +3537,17 @@ const configurationService = createConfigurationService({
3241
3537
  storeUtils,
3242
3538
  prefix: "content_types",
3243
3539
  getModels() {
3244
- const { toContentManagerModel } = getService$1("data-mapper");
3540
+ const { toContentManagerModel } = getService$2("data-mapper");
3245
3541
  return fp.mapValues(toContentManagerModel, strapi.contentTypes);
3246
3542
  }
3247
3543
  });
3248
3544
  const service = ({ strapi: strapi2 }) => ({
3249
3545
  findAllContentTypes() {
3250
- const { toContentManagerModel } = getService$1("data-mapper");
3546
+ const { toContentManagerModel } = getService$2("data-mapper");
3251
3547
  return Object.values(strapi2.contentTypes).map(toContentManagerModel);
3252
3548
  },
3253
3549
  findContentType(uid2) {
3254
- const { toContentManagerModel } = getService$1("data-mapper");
3550
+ const { toContentManagerModel } = getService$2("data-mapper");
3255
3551
  const contentType = strapi2.contentTypes[uid2];
3256
3552
  return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
3257
3553
  },
@@ -3280,7 +3576,7 @@ const service = ({ strapi: strapi2 }) => ({
3280
3576
  return this.findConfiguration(contentType);
3281
3577
  },
3282
3578
  findComponentsConfigurations(contentType) {
3283
- return getService$1("components").findComponentsConfigurations(contentType);
3579
+ return getService$2("components").findComponentsConfigurations(contentType);
3284
3580
  },
3285
3581
  syncConfigurations() {
3286
3582
  return configurationService.syncConfigurations();
@@ -3461,12 +3757,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
3461
3757
  ability: userAbility,
3462
3758
  model
3463
3759
  });
3464
- 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
+ };
3465
3764
  const can = (action, entity, field) => {
3466
- 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
+ );
3467
3772
  };
3468
3773
  const cannot = (action, entity, field) => {
3469
- 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
+ );
3470
3781
  };
3471
3782
  const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
3472
3783
  return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
@@ -3537,7 +3848,7 @@ const permission = ({ strapi: strapi2 }) => ({
3537
3848
  return userAbility.can(action);
3538
3849
  },
3539
3850
  async registerPermissions() {
3540
- const displayedContentTypes = getService$1("content-types").findDisplayedContentTypes();
3851
+ const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
3541
3852
  const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
3542
3853
  const actions = [
3543
3854
  {
@@ -3743,6 +4054,10 @@ const getDeepPopulateDraftCount = (uid2) => {
3743
4054
  const attribute = model.attributes[attributeName];
3744
4055
  switch (attribute.type) {
3745
4056
  case "relation": {
4057
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
4058
+ if (isMorphRelation) {
4059
+ break;
4060
+ }
3746
4061
  if (isVisibleAttribute$1(model, attributeName)) {
3747
4062
  populateAcc[attributeName] = {
3748
4063
  count: true,
@@ -3809,7 +4124,7 @@ const getQueryPopulate = async (uid2, query) => {
3809
4124
  return populateQuery;
3810
4125
  };
3811
4126
  const buildDeepPopulate = (uid2) => {
3812
- return getService$1("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
4127
+ return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
3813
4128
  };
3814
4129
  const populateBuilder = (uid2) => {
3815
4130
  let getInitialPopulate = async () => {
@@ -3994,7 +4309,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
3994
4309
  */
3995
4310
  async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
3996
4311
  const versionsByLocale = fp.groupBy("locale", allVersions);
3997
- delete versionsByLocale[version.locale];
4312
+ if (version.locale) {
4313
+ delete versionsByLocale[version.locale];
4314
+ }
3998
4315
  const model = strapi2.getModel(uid2);
3999
4316
  const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
4000
4317
  const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
@@ -4041,8 +4358,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4041
4358
  const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
4042
4359
  return matchLocale && matchStatus;
4043
4360
  });
4044
- if (!availableStatus)
4045
- return availableStatus;
4361
+ if (!availableStatus) return availableStatus;
4046
4362
  return fp.pick(AVAILABLE_STATUS_FIELDS, availableStatus);
4047
4363
  },
4048
4364
  /**
@@ -4052,8 +4368,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4052
4368
  * @returns
4053
4369
  */
4054
4370
  async getManyAvailableStatus(uid2, documents) {
4055
- if (!documents.length)
4056
- return [];
4371
+ if (!documents.length) return [];
4057
4372
  const status = documents[0].publishedAt !== null ? "published" : "draft";
4058
4373
  const locale = documents[0]?.locale;
4059
4374
  const otherStatus = status === "published" ? "draft" : "published";
@@ -4080,10 +4395,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4080
4395
  } else if (otherVersion) {
4081
4396
  draftVersion = otherVersion;
4082
4397
  }
4083
- if (!draftVersion)
4084
- return CONTENT_MANAGER_STATUS.PUBLISHED;
4085
- if (!publishedVersion)
4086
- return CONTENT_MANAGER_STATUS.DRAFT;
4398
+ if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
4399
+ if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
4087
4400
  const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
4088
4401
  return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
4089
4402
  },
@@ -4120,7 +4433,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4120
4433
  */
4121
4434
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
4122
4435
  if (!document) {
4123
- return document;
4436
+ return {
4437
+ data: document,
4438
+ meta: {
4439
+ availableLocales: [],
4440
+ availableStatus: []
4441
+ }
4442
+ };
4124
4443
  }
4125
4444
  const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
4126
4445
  if (!hasDraftAndPublish) {
@@ -4228,10 +4547,7 @@ const documentManager = ({ strapi: strapi2 }) => {
4228
4547
  async clone(id, body, uid2) {
4229
4548
  const populate = await buildDeepPopulate(uid2);
4230
4549
  const params = {
4231
- data: {
4232
- ...omitIdField(body),
4233
- [PUBLISHED_AT_ATTRIBUTE]: null
4234
- },
4550
+ data: omitIdField(body),
4235
4551
  populate
4236
4552
  };
4237
4553
  return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
@@ -4347,7 +4663,8 @@ const services = {
4347
4663
  permission,
4348
4664
  "populate-builder": populateBuilder$1,
4349
4665
  uid,
4350
- ...history.services ? history.services : {}
4666
+ ...history.services ? history.services : {},
4667
+ ...preview.services ? preview.services : {}
4351
4668
  };
4352
4669
  const index = () => {
4353
4670
  return {