@strapi/content-manager 0.0.0-experimental.edc24aaa3bb5a90fa5fd4fee208167dd4e2e38d4 → 0.0.0-experimental.f0a0bc26f5ef0693aaea2a616bc6b816cfee54b6

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 (198) hide show
  1. package/dist/_chunks/{ComponentConfigurationPage-BAgyHiMm.mjs → ComponentConfigurationPage-DhWA-JzT.mjs} +4 -4
  2. package/dist/_chunks/{ComponentConfigurationPage-BAgyHiMm.mjs.map → ComponentConfigurationPage-DhWA-JzT.mjs.map} +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-5ukroXAh.js → ComponentConfigurationPage-UduDBv3m.js} +4 -4
  4. package/dist/_chunks/{ComponentConfigurationPage-5ukroXAh.js.map → ComponentConfigurationPage-UduDBv3m.js.map} +1 -1
  5. package/dist/_chunks/{EditConfigurationPage-DmoXawIh.mjs → EditConfigurationPage-5tmx_7Hp.mjs} +4 -4
  6. package/dist/_chunks/{EditConfigurationPage-DmoXawIh.mjs.map → EditConfigurationPage-5tmx_7Hp.mjs.map} +1 -1
  7. package/dist/_chunks/{EditConfigurationPage-Xp7lun0f.js → EditConfigurationPage-Cp9UzUfs.js} +4 -4
  8. package/dist/_chunks/{EditConfigurationPage-Xp7lun0f.js.map → EditConfigurationPage-Cp9UzUfs.js.map} +1 -1
  9. package/dist/_chunks/{EditViewPage-BLsjc5F-.mjs → EditViewPage-BKoISUOu.mjs} +63 -12
  10. package/dist/_chunks/EditViewPage-BKoISUOu.mjs.map +1 -0
  11. package/dist/_chunks/{EditViewPage-C-ukDOB7.js → EditViewPage-C7l2Emuj.js} +62 -11
  12. package/dist/_chunks/EditViewPage-C7l2Emuj.js.map +1 -0
  13. package/dist/_chunks/{Field-Bfph5SOd.js → Field-BPSJpDfE.js} +211 -120
  14. package/dist/_chunks/Field-BPSJpDfE.js.map +1 -0
  15. package/dist/_chunks/{Field-Cs7duwWd.mjs → Field-BZxzYf1x.mjs} +210 -119
  16. package/dist/_chunks/Field-BZxzYf1x.mjs.map +1 -0
  17. package/dist/_chunks/{Form-Dg_GS5TQ.mjs → Form-8qyOU6YG.mjs} +36 -17
  18. package/dist/_chunks/Form-8qyOU6YG.mjs.map +1 -0
  19. package/dist/_chunks/{Form-CPYqIWDG.js → Form-DLkqDd2G.js} +36 -17
  20. package/dist/_chunks/Form-DLkqDd2G.js.map +1 -0
  21. package/dist/_chunks/{History-DNQkXANT.js → History-DYMicybF.js} +41 -98
  22. package/dist/_chunks/History-DYMicybF.js.map +1 -0
  23. package/dist/_chunks/{History-wrnHqf09.mjs → History-N_kRb1Yr.mjs} +43 -100
  24. package/dist/_chunks/History-N_kRb1Yr.mjs.map +1 -0
  25. package/dist/_chunks/{ListConfigurationPage-DScmJVkW.mjs → ListConfigurationPage-BM3qVxug.mjs} +18 -7
  26. package/dist/_chunks/ListConfigurationPage-BM3qVxug.mjs.map +1 -0
  27. package/dist/_chunks/{ListConfigurationPage-CUQxfpjT.js → ListConfigurationPage-rUF9iGWq.js} +17 -6
  28. package/dist/_chunks/ListConfigurationPage-rUF9iGWq.js.map +1 -0
  29. package/dist/_chunks/{ListViewPage-BsLiH2-2.js → ListViewPage-BSLzd7cZ.js} +108 -76
  30. package/dist/_chunks/ListViewPage-BSLzd7cZ.js.map +1 -0
  31. package/dist/_chunks/{ListViewPage-C4IvrMgY.mjs → ListViewPage-CWilGbZb.mjs} +106 -74
  32. package/dist/_chunks/ListViewPage-CWilGbZb.mjs.map +1 -0
  33. package/dist/_chunks/{NoContentTypePage-BZ-PnGAf.js → NoContentTypePage-CQccVhIX.js} +2 -2
  34. package/dist/_chunks/{NoContentTypePage-BZ-PnGAf.js.map → NoContentTypePage-CQccVhIX.js.map} +1 -1
  35. package/dist/_chunks/{NoContentTypePage-Djg8nPlj.mjs → NoContentTypePage-VWYlePwI.mjs} +2 -2
  36. package/dist/_chunks/{NoContentTypePage-Djg8nPlj.mjs.map → NoContentTypePage-VWYlePwI.mjs.map} +1 -1
  37. package/dist/_chunks/{NoPermissionsPage-_lUqjGW3.js → NoPermissionsPage-Af32Gg2m.js} +2 -2
  38. package/dist/_chunks/{NoPermissionsPage-_lUqjGW3.js.map → NoPermissionsPage-Af32Gg2m.js.map} +1 -1
  39. package/dist/_chunks/{NoPermissionsPage-DSP7R-hv.mjs → NoPermissionsPage-CS2tCmfr.mjs} +2 -2
  40. package/dist/_chunks/{NoPermissionsPage-DSP7R-hv.mjs.map → NoPermissionsPage-CS2tCmfr.mjs.map} +1 -1
  41. package/dist/_chunks/Preview-D4KzuJFL.js +291 -0
  42. package/dist/_chunks/Preview-D4KzuJFL.js.map +1 -0
  43. package/dist/_chunks/Preview-kPkuZbBJ.mjs +272 -0
  44. package/dist/_chunks/Preview-kPkuZbBJ.mjs.map +1 -0
  45. package/dist/_chunks/{Relations-BZr8tL0R.mjs → Relations-5k27Rh54.mjs} +73 -37
  46. package/dist/_chunks/Relations-5k27Rh54.mjs.map +1 -0
  47. package/dist/_chunks/{Relations-CtELXYIK.js → Relations-D_Ki5aVM.js} +72 -36
  48. package/dist/_chunks/Relations-D_Ki5aVM.js.map +1 -0
  49. package/dist/_chunks/{en-uOUIxfcQ.js → en-BK8Xyl5I.js} +28 -15
  50. package/dist/_chunks/{en-uOUIxfcQ.js.map → en-BK8Xyl5I.js.map} +1 -1
  51. package/dist/_chunks/{en-BrCTWlZv.mjs → en-Dtk_ot79.mjs} +28 -15
  52. package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-Dtk_ot79.mjs.map} +1 -1
  53. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  54. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  55. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  56. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  57. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
  58. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
  59. package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
  60. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
  61. package/dist/_chunks/{index-c_5DdJi-.mjs → index-BLPa8Dq-.mjs} +1201 -924
  62. package/dist/_chunks/index-BLPa8Dq-.mjs.map +1 -0
  63. package/dist/_chunks/{index-OerGjbAN.js → index-DwOsF7wF.js} +1182 -904
  64. package/dist/_chunks/index-DwOsF7wF.js.map +1 -0
  65. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  66. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  67. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  68. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  69. package/dist/_chunks/{layout-oPBiO7RY.mjs → layout-2Si0j0jO.mjs} +22 -9
  70. package/dist/_chunks/layout-2Si0j0jO.mjs.map +1 -0
  71. package/dist/_chunks/{layout-Ci7qHlFb.js → layout-CN2bFL9V.js} +21 -8
  72. package/dist/_chunks/layout-CN2bFL9V.js.map +1 -0
  73. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  74. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  75. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  76. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  77. package/dist/_chunks/{relations-COBpStiF.js → relations-B0E0XUY7.js} +6 -7
  78. package/dist/_chunks/relations-B0E0XUY7.js.map +1 -0
  79. package/dist/_chunks/{relations-BIdWFjdq.mjs → relations-CAxDjUJF.mjs} +6 -7
  80. package/dist/_chunks/relations-CAxDjUJF.mjs.map +1 -0
  81. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  82. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  83. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  84. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  85. package/dist/admin/index.js +2 -1
  86. package/dist/admin/index.js.map +1 -1
  87. package/dist/admin/index.mjs +5 -4
  88. package/dist/admin/src/exports.d.ts +1 -1
  89. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  90. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  91. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  92. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
  93. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  95. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  96. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  97. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  98. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  99. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  100. package/dist/admin/src/preview/constants.d.ts +1 -0
  101. package/dist/admin/src/preview/index.d.ts +4 -0
  102. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  103. package/dist/admin/src/preview/routes.d.ts +3 -0
  104. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  105. package/dist/admin/src/router.d.ts +1 -1
  106. package/dist/admin/src/services/api.d.ts +1 -1
  107. package/dist/admin/src/services/components.d.ts +2 -2
  108. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  109. package/dist/admin/src/services/documents.d.ts +19 -20
  110. package/dist/admin/src/services/init.d.ts +1 -1
  111. package/dist/admin/src/services/relations.d.ts +2 -2
  112. package/dist/admin/src/services/uid.d.ts +3 -3
  113. package/dist/admin/src/utils/validation.d.ts +4 -1
  114. package/dist/server/index.js +560 -235
  115. package/dist/server/index.js.map +1 -1
  116. package/dist/server/index.mjs +561 -236
  117. package/dist/server/index.mjs.map +1 -1
  118. package/dist/server/src/bootstrap.d.ts.map +1 -1
  119. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  120. package/dist/server/src/controllers/index.d.ts.map +1 -1
  121. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  122. package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
  123. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  124. package/dist/server/src/history/services/history.d.ts.map +1 -1
  125. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  126. package/dist/server/src/history/services/utils.d.ts +4 -4
  127. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  128. package/dist/server/src/index.d.ts +4 -4
  129. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  130. package/dist/server/src/preview/constants.d.ts +2 -0
  131. package/dist/server/src/preview/constants.d.ts.map +1 -0
  132. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  133. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  134. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  135. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  136. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  137. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  138. package/dist/server/src/preview/index.d.ts +4 -0
  139. package/dist/server/src/preview/index.d.ts.map +1 -0
  140. package/dist/server/src/preview/routes/index.d.ts +8 -0
  141. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  142. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  143. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  144. package/dist/server/src/preview/services/index.d.ts +16 -0
  145. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  146. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  147. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  148. package/dist/server/src/preview/services/preview.d.ts +12 -0
  149. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  150. package/dist/server/src/preview/utils.d.ts +19 -0
  151. package/dist/server/src/preview/utils.d.ts.map +1 -0
  152. package/dist/server/src/register.d.ts.map +1 -1
  153. package/dist/server/src/routes/index.d.ts.map +1 -1
  154. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  155. package/dist/server/src/services/document-metadata.d.ts +8 -8
  156. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  157. package/dist/server/src/services/index.d.ts +4 -4
  158. package/dist/server/src/services/index.d.ts.map +1 -1
  159. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  160. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  161. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  162. package/dist/server/src/utils/index.d.ts +2 -0
  163. package/dist/server/src/utils/index.d.ts.map +1 -1
  164. package/dist/shared/contracts/collection-types.d.ts +3 -1
  165. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  166. package/dist/shared/contracts/index.d.ts +1 -0
  167. package/dist/shared/contracts/index.d.ts.map +1 -1
  168. package/dist/shared/contracts/preview.d.ts +27 -0
  169. package/dist/shared/contracts/preview.d.ts.map +1 -0
  170. package/dist/shared/index.js +4 -0
  171. package/dist/shared/index.js.map +1 -1
  172. package/dist/shared/index.mjs +4 -0
  173. package/dist/shared/index.mjs.map +1 -1
  174. package/package.json +14 -14
  175. package/dist/_chunks/EditViewPage-BLsjc5F-.mjs.map +0 -1
  176. package/dist/_chunks/EditViewPage-C-ukDOB7.js.map +0 -1
  177. package/dist/_chunks/Field-Bfph5SOd.js.map +0 -1
  178. package/dist/_chunks/Field-Cs7duwWd.mjs.map +0 -1
  179. package/dist/_chunks/Form-CPYqIWDG.js.map +0 -1
  180. package/dist/_chunks/Form-Dg_GS5TQ.mjs.map +0 -1
  181. package/dist/_chunks/History-DNQkXANT.js.map +0 -1
  182. package/dist/_chunks/History-wrnHqf09.mjs.map +0 -1
  183. package/dist/_chunks/ListConfigurationPage-CUQxfpjT.js.map +0 -1
  184. package/dist/_chunks/ListConfigurationPage-DScmJVkW.mjs.map +0 -1
  185. package/dist/_chunks/ListViewPage-BsLiH2-2.js.map +0 -1
  186. package/dist/_chunks/ListViewPage-C4IvrMgY.mjs.map +0 -1
  187. package/dist/_chunks/Relations-BZr8tL0R.mjs.map +0 -1
  188. package/dist/_chunks/Relations-CtELXYIK.js.map +0 -1
  189. package/dist/_chunks/index-OerGjbAN.js.map +0 -1
  190. package/dist/_chunks/index-c_5DdJi-.mjs.map +0 -1
  191. package/dist/_chunks/layout-Ci7qHlFb.js.map +0 -1
  192. package/dist/_chunks/layout-oPBiO7RY.mjs.map +0 -1
  193. package/dist/_chunks/relations-BIdWFjdq.mjs.map +0 -1
  194. package/dist/_chunks/relations-COBpStiF.js.map +0 -1
  195. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  196. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  197. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  198. package/strapi-server.js +0 -3
@@ -33,10 +33,10 @@ const isNil__default = /* @__PURE__ */ _interopDefault(isNil);
33
33
  const ___default = /* @__PURE__ */ _interopDefault(_);
34
34
  const qs__default = /* @__PURE__ */ _interopDefault(qs);
35
35
  const slugify__default = /* @__PURE__ */ _interopDefault(slugify);
36
- const getService$1 = (name) => {
36
+ const getService$2 = (name) => {
37
37
  return strapi.plugin("content-manager").service(name);
38
38
  };
39
- function getService(strapi2, name) {
39
+ function getService$1(strapi2, name) {
40
40
  return strapi2.service(`plugin::content-manager.${name}`);
41
41
  }
42
42
  const historyRestoreVersionSchema = yup__namespace.object().shape({
@@ -72,7 +72,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
72
72
  if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
73
73
  throw new strapiUtils.errors.ForbiddenError("contentType and documentId are required");
74
74
  }
75
- const permissionChecker2 = getService$1("permission-checker").create({
75
+ const permissionChecker2 = getService$2("permission-checker").create({
76
76
  userAbility: ctx.state.userAbility,
77
77
  model: ctx.query.contentType
78
78
  });
@@ -80,7 +80,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
80
80
  return ctx.forbidden();
81
81
  }
82
82
  const query = await permissionChecker2.sanitizeQuery(ctx.query);
83
- const { results, pagination } = await getService(strapi2, "history").findVersionsPage({
83
+ const { results, pagination } = await getService$1(strapi2, "history").findVersionsPage({
84
84
  query: {
85
85
  ...query,
86
86
  ...getValidPagination({ page: query.page, pageSize: query.pageSize })
@@ -105,14 +105,14 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
105
105
  async restoreVersion(ctx) {
106
106
  const request = ctx.request;
107
107
  await validateRestoreVersion(request.body, "contentType is required");
108
- const permissionChecker2 = getService$1("permission-checker").create({
108
+ const permissionChecker2 = getService$2("permission-checker").create({
109
109
  userAbility: ctx.state.userAbility,
110
110
  model: request.body.contentType
111
111
  });
112
112
  if (permissionChecker2.cannot.update()) {
113
113
  throw new strapiUtils.errors.ForbiddenError();
114
114
  }
115
- const restoredDocument = await getService(strapi2, "history").restoreVersion(
115
+ const restoredDocument = await getService$1(strapi2, "history").restoreVersion(
116
116
  request.params.versionId
117
117
  );
118
118
  return {
@@ -121,7 +121,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
121
121
  }
122
122
  };
123
123
  };
124
- const controllers$1 = {
124
+ const controllers$2 = {
125
125
  "history-version": createHistoryVersionController
126
126
  /**
127
127
  * Casting is needed because the types aren't aware that Strapi supports
@@ -199,7 +199,9 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
199
199
  return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
200
200
  };
201
201
  const localesService = strapi2.plugin("i18n")?.service("locales");
202
+ const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
202
203
  const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
204
+ const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
203
205
  const getLocaleDictionary = async () => {
204
206
  if (!localesService)
205
207
  return {};
@@ -226,9 +228,21 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
226
228
  const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
227
229
  return documentMetadataService.getStatus(document, meta.availableStatus);
228
230
  };
229
- const getDeepPopulate2 = (uid2) => {
231
+ const getComponentFields = (componentUID) => {
232
+ return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
233
+ (fieldsAcc, [key, attribute]) => {
234
+ if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
235
+ fieldsAcc.push(key);
236
+ }
237
+ return fieldsAcc;
238
+ },
239
+ []
240
+ );
241
+ };
242
+ const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
230
243
  const model = strapi2.getModel(uid2);
231
244
  const attributes = Object.entries(model.attributes);
245
+ const fieldSelector = useDatabaseSyntax ? "select" : "fields";
232
246
  return attributes.reduce((acc, [attributeName, attribute]) => {
233
247
  switch (attribute.type) {
234
248
  case "relation": {
@@ -238,23 +252,29 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
238
252
  }
239
253
  const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
240
254
  if (isVisible2) {
241
- acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
255
+ acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
242
256
  }
243
257
  break;
244
258
  }
245
259
  case "media": {
246
- acc[attributeName] = { fields: ["id"] };
260
+ acc[attributeName] = { [fieldSelector]: ["id"] };
247
261
  break;
248
262
  }
249
263
  case "component": {
250
264
  const populate = getDeepPopulate2(attribute.component);
251
- acc[attributeName] = { populate };
265
+ acc[attributeName] = {
266
+ populate,
267
+ [fieldSelector]: getComponentFields(attribute.component)
268
+ };
252
269
  break;
253
270
  }
254
271
  case "dynamiczone": {
255
272
  const populatedComponents = (attribute.components || []).reduce(
256
273
  (acc2, componentUID) => {
257
- acc2[componentUID] = { populate: getDeepPopulate2(componentUID) };
274
+ acc2[componentUID] = {
275
+ populate: getDeepPopulate2(componentUID),
276
+ [fieldSelector]: getComponentFields(componentUID)
277
+ };
258
278
  return acc2;
259
279
  },
260
280
  {}
@@ -316,6 +336,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
316
336
  getRelationRestoreValue,
317
337
  getMediaRestoreValue,
318
338
  getDefaultLocale,
339
+ isLocalizedContentType,
319
340
  getLocaleDictionary,
320
341
  getRetentionDays,
321
342
  getVersionStatus,
@@ -338,7 +359,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
338
359
  });
339
360
  },
340
361
  async findVersionsPage(params) {
341
- const locale = params.query.locale || await serviceUtils.getDefaultLocale();
362
+ const model = strapi2.getModel(params.query.contentType);
363
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
364
+ const defaultLocale = await serviceUtils.getDefaultLocale();
365
+ let locale = null;
366
+ if (isLocalizedContentType) {
367
+ locale = params.query.locale || defaultLocale;
368
+ }
342
369
  const [{ results, pagination }, localeDictionary] = await Promise.all([
343
370
  query.findPage({
344
371
  ...params.query,
@@ -360,7 +387,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
360
387
  const attributeValue = entry.data[attributeKey];
361
388
  const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
362
389
  if (attributeSchema.type === "media") {
363
- const permissionChecker2 = getService$1("permission-checker").create({
390
+ const permissionChecker2 = getService$2("permission-checker").create({
364
391
  userAbility: params.state.userAbility,
365
392
  model: "plugin::upload.file"
366
393
  });
@@ -383,7 +410,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
383
410
  if (userToPopulate == null) {
384
411
  return null;
385
412
  }
386
- return strapi2.query("admin::user").findOne({ where: { id: userToPopulate.id } });
413
+ return strapi2.query("admin::user").findOne({
414
+ where: {
415
+ ...userToPopulate.id ? { id: userToPopulate.id } : {},
416
+ ...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
417
+ }
418
+ });
387
419
  })
388
420
  );
389
421
  return {
@@ -396,7 +428,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
396
428
  [attributeKey]: adminUsers
397
429
  };
398
430
  }
399
- const permissionChecker2 = getService$1("permission-checker").create({
431
+ const permissionChecker2 = getService$2("permission-checker").create({
400
432
  userAbility: params.state.userAbility,
401
433
  model: attributeSchema.target
402
434
  });
@@ -494,6 +526,42 @@ const createHistoryService = ({ strapi: strapi2 }) => {
494
526
  }
495
527
  };
496
528
  };
529
+ const shouldCreateHistoryVersion = (context) => {
530
+ if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
531
+ return false;
532
+ }
533
+ if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
534
+ return false;
535
+ }
536
+ if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
537
+ return false;
538
+ }
539
+ if (!context.contentType.uid.startsWith("api::")) {
540
+ return false;
541
+ }
542
+ return true;
543
+ };
544
+ const getSchemas = (uid2) => {
545
+ const attributesSchema = strapi.getModel(uid2).attributes;
546
+ const componentsSchemas = Object.keys(attributesSchema).reduce(
547
+ (currentComponentSchemas, key) => {
548
+ const fieldSchema = attributesSchema[key];
549
+ if (fieldSchema.type === "component") {
550
+ const componentSchema = strapi.getModel(fieldSchema.component).attributes;
551
+ return {
552
+ ...currentComponentSchemas,
553
+ [fieldSchema.component]: componentSchema
554
+ };
555
+ }
556
+ return currentComponentSchemas;
557
+ },
558
+ {}
559
+ );
560
+ return {
561
+ schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
562
+ componentsSchemas
563
+ };
564
+ };
497
565
  const createLifecyclesService = ({ strapi: strapi2 }) => {
498
566
  const state = {
499
567
  deleteExpiredJob: null,
@@ -506,76 +574,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
506
574
  return;
507
575
  }
508
576
  strapi2.documents.use(async (context, next) => {
509
- if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
510
- return next();
511
- }
512
- if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
513
- return next();
514
- }
515
- if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
516
- return next();
517
- }
518
- const contentTypeUid = context.contentType.uid;
519
- if (!contentTypeUid.startsWith("api::")) {
520
- return next();
521
- }
522
577
  const result = await next();
523
- const documentContext = {
524
- documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
525
- locale: context.params?.locale
526
- };
578
+ if (!shouldCreateHistoryVersion(context)) {
579
+ return result;
580
+ }
581
+ const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
527
582
  const defaultLocale = await serviceUtils.getDefaultLocale();
528
- const locale = documentContext.locale || defaultLocale;
529
- if (Array.isArray(locale)) {
530
- strapi2.log.warn(
531
- "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
532
- );
533
- return next();
583
+ const locales = fp.castArray(context.params?.locale || defaultLocale);
584
+ if (!locales.length) {
585
+ return result;
534
586
  }
535
- const document = await strapi2.documents(contentTypeUid).findOne({
536
- documentId: documentContext.documentId,
537
- locale,
538
- populate: serviceUtils.getDeepPopulate(contentTypeUid)
587
+ const uid2 = context.contentType.uid;
588
+ const schemas = getSchemas(uid2);
589
+ const model = strapi2.getModel(uid2);
590
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
591
+ const localeEntries = await strapi2.db.query(uid2).findMany({
592
+ where: {
593
+ documentId,
594
+ ...isLocalizedContentType ? { locale: { $in: locales } } : {},
595
+ ...strapiUtils.contentTypes.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
596
+ },
597
+ populate: serviceUtils.getDeepPopulate(
598
+ uid2,
599
+ true
600
+ /* use database syntax */
601
+ )
539
602
  });
540
- const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
541
- const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
542
- const componentsSchemas = Object.keys(
543
- attributesSchema
544
- ).reduce((currentComponentSchemas, key) => {
545
- const fieldSchema = attributesSchema[key];
546
- if (fieldSchema.type === "component") {
547
- const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
548
- return {
549
- ...currentComponentSchemas,
550
- [fieldSchema.component]: componentSchema
551
- };
552
- }
553
- return currentComponentSchemas;
554
- }, {});
555
603
  await strapi2.db.transaction(async ({ onCommit }) => {
556
- onCommit(() => {
557
- getService(strapi2, "history").createVersion({
558
- contentType: contentTypeUid,
559
- data: fp.omit(FIELDS_TO_IGNORE, document),
560
- schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
561
- componentsSchemas,
562
- relatedDocumentId: documentContext.documentId,
563
- locale,
564
- status
565
- });
604
+ onCommit(async () => {
605
+ for (const entry of localeEntries) {
606
+ const status = await serviceUtils.getVersionStatus(uid2, entry);
607
+ await getService$1(strapi2, "history").createVersion({
608
+ contentType: uid2,
609
+ data: fp.omit(FIELDS_TO_IGNORE, entry),
610
+ relatedDocumentId: documentId,
611
+ locale: entry.locale,
612
+ status,
613
+ ...schemas
614
+ });
615
+ }
566
616
  });
567
617
  });
568
618
  return result;
569
619
  });
570
- state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
620
+ state.deleteExpiredJob = nodeSchedule.scheduleJob("historyDaily", "0 0 * * *", () => {
571
621
  const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
572
622
  const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
573
623
  strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
574
624
  where: {
575
625
  created_at: {
576
- $lt: expirationDate.toISOString()
626
+ $lt: expirationDate
577
627
  }
578
628
  }
629
+ }).catch((error) => {
630
+ if (error instanceof Error) {
631
+ strapi2.log.error("Error deleting expired history versions", error.message);
632
+ }
579
633
  });
580
634
  });
581
635
  state.isInitialized = true;
@@ -587,17 +641,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
587
641
  }
588
642
  };
589
643
  };
590
- const services$1 = {
644
+ const services$2 = {
591
645
  history: createHistoryService,
592
646
  lifecycles: createLifecyclesService
593
647
  };
594
- const info = { pluginName: "content-manager", type: "admin" };
648
+ const info$1 = { pluginName: "content-manager", type: "admin" };
595
649
  const historyVersionRouter = {
596
650
  type: "admin",
597
651
  routes: [
598
652
  {
599
653
  method: "GET",
600
- info,
654
+ info: info$1,
601
655
  path: "/history-versions",
602
656
  handler: "history-version.findMany",
603
657
  config: {
@@ -606,7 +660,7 @@ const historyVersionRouter = {
606
660
  },
607
661
  {
608
662
  method: "PUT",
609
- info,
663
+ info: info$1,
610
664
  path: "/history-versions/:versionId/restore",
611
665
  handler: "history-version.restoreVersion",
612
666
  config: {
@@ -615,7 +669,7 @@ const historyVersionRouter = {
615
669
  }
616
670
  ]
617
671
  };
618
- const routes$1 = {
672
+ const routes$2 = {
619
673
  "history-version": historyVersionRouter
620
674
  };
621
675
  const historyVersion = {
@@ -662,21 +716,21 @@ const historyVersion = {
662
716
  }
663
717
  }
664
718
  };
665
- const getFeature = () => {
719
+ const getFeature$1 = () => {
666
720
  if (strapi.ee.features.isEnabled("cms-content-history")) {
667
721
  return {
668
722
  register({ strapi: strapi2 }) {
669
723
  strapi2.get("models").add(historyVersion);
670
724
  },
671
725
  bootstrap({ strapi: strapi2 }) {
672
- getService(strapi2, "lifecycles").bootstrap();
726
+ getService$1(strapi2, "lifecycles").bootstrap();
673
727
  },
674
728
  destroy({ strapi: strapi2 }) {
675
- getService(strapi2, "lifecycles").destroy();
729
+ getService$1(strapi2, "lifecycles").destroy();
676
730
  },
677
- controllers: controllers$1,
678
- services: services$1,
679
- routes: routes$1
731
+ controllers: controllers$2,
732
+ services: services$2,
733
+ routes: routes$2
680
734
  };
681
735
  }
682
736
  return {
@@ -685,9 +739,205 @@ const getFeature = () => {
685
739
  }
686
740
  };
687
741
  };
688
- const history = getFeature();
742
+ const history = getFeature$1();
743
+ const FEATURE_ID = "preview";
744
+ const info = { pluginName: "content-manager", type: "admin" };
745
+ const previewRouter = {
746
+ type: "admin",
747
+ routes: [
748
+ {
749
+ method: "GET",
750
+ info,
751
+ path: "/preview/url/:contentType",
752
+ handler: "preview.getPreviewUrl",
753
+ config: {
754
+ policies: ["admin::isAuthenticatedAdmin"]
755
+ }
756
+ }
757
+ ]
758
+ };
759
+ const routes$1 = {
760
+ preview: previewRouter
761
+ };
762
+ function getService(strapi2, name) {
763
+ return strapi2.service(`plugin::content-manager.${name}`);
764
+ }
765
+ const getPreviewUrlSchema = yup__namespace.object().shape({
766
+ // Will be undefined for single types
767
+ documentId: yup__namespace.string(),
768
+ locale: yup__namespace.string().nullable(),
769
+ status: yup__namespace.string()
770
+ }).required();
771
+ const validatePreviewUrl = async (strapi2, uid2, params) => {
772
+ await strapiUtils.validateYupSchema(getPreviewUrlSchema)(params);
773
+ const newParams = fp.pick(["documentId", "locale", "status"], params);
774
+ const model = strapi2.getModel(uid2);
775
+ if (!model || model.modelType !== "contentType") {
776
+ throw new strapiUtils.errors.ValidationError("Invalid content type");
777
+ }
778
+ const isSingleType = model?.kind === "singleType";
779
+ if (!isSingleType && !params.documentId) {
780
+ throw new strapiUtils.errors.ValidationError("documentId is required for Collection Types");
781
+ }
782
+ if (isSingleType) {
783
+ const doc = await strapi2.documents(uid2).findFirst();
784
+ if (!doc) {
785
+ throw new strapiUtils.errors.NotFoundError("Document not found");
786
+ }
787
+ newParams.documentId = doc?.documentId;
788
+ }
789
+ if (!newParams.status) {
790
+ const isDPEnabled = model?.options?.draftAndPublish;
791
+ newParams.status = isDPEnabled ? "draft" : "published";
792
+ }
793
+ return newParams;
794
+ };
795
+ const createPreviewController = () => {
796
+ return {
797
+ /**
798
+ * Transforms an entry into a preview URL, so that it can be previewed
799
+ * in the Content Manager.
800
+ */
801
+ async getPreviewUrl(ctx) {
802
+ const uid2 = ctx.params.contentType;
803
+ const query = ctx.request.query;
804
+ const params = await validatePreviewUrl(strapi, uid2, query);
805
+ const previewService = getService(strapi, "preview");
806
+ const url = await previewService.getPreviewUrl(uid2, params);
807
+ if (!url) {
808
+ ctx.status = 204;
809
+ }
810
+ return {
811
+ data: { url }
812
+ };
813
+ }
814
+ };
815
+ };
816
+ const controllers$1 = {
817
+ preview: createPreviewController
818
+ /**
819
+ * Casting is needed because the types aren't aware that Strapi supports
820
+ * passing a controller factory as the value, instead of a controller object directly
821
+ */
822
+ };
823
+ const createPreviewService = ({ strapi: strapi2 }) => {
824
+ const config = getService(strapi2, "preview-config");
825
+ return {
826
+ async getPreviewUrl(uid2, params) {
827
+ const handler = config.getPreviewHandler();
828
+ try {
829
+ return handler(uid2, params);
830
+ } catch (error) {
831
+ strapi2.log.error(`Failed to get preview URL: ${error}`);
832
+ throw new strapiUtils.errors.ApplicationError("Failed to get preview URL");
833
+ }
834
+ return;
835
+ }
836
+ };
837
+ };
838
+ const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
839
+ const middlewares = strapi.config.get("middlewares");
840
+ const configuredMiddlewares = middlewares.map((currentMiddleware) => {
841
+ if (currentMiddleware === middleware.name) {
842
+ return middleware;
843
+ }
844
+ if (currentMiddleware.name === middleware.name) {
845
+ return fp.mergeWith(
846
+ (objValue, srcValue) => {
847
+ if (Array.isArray(objValue)) {
848
+ return objValue.concat(srcValue);
849
+ }
850
+ return void 0;
851
+ },
852
+ currentMiddleware,
853
+ middleware
854
+ );
855
+ }
856
+ return currentMiddleware;
857
+ });
858
+ strapi.config.set("middlewares", configuredMiddlewares);
859
+ };
860
+ const createPreviewConfigService = ({ strapi: strapi2 }) => {
861
+ return {
862
+ register() {
863
+ if (!this.isEnabled()) {
864
+ return;
865
+ }
866
+ const config = strapi2.config.get("admin.preview");
867
+ if (config.config?.allowedOrigins) {
868
+ extendMiddlewareConfiguration({
869
+ name: "strapi::security",
870
+ config: {
871
+ contentSecurityPolicy: {
872
+ directives: {
873
+ "frame-src": config.config.allowedOrigins
874
+ }
875
+ }
876
+ }
877
+ });
878
+ }
879
+ },
880
+ isEnabled() {
881
+ const config = strapi2.config.get("admin.preview");
882
+ if (!config) {
883
+ return false;
884
+ }
885
+ return config?.enabled ?? true;
886
+ },
887
+ /**
888
+ * Validate if the configuration is valid
889
+ */
890
+ validate() {
891
+ if (!this.isEnabled()) {
892
+ return;
893
+ }
894
+ const handler = this.getPreviewHandler();
895
+ if (typeof handler !== "function") {
896
+ throw new strapiUtils.errors.ValidationError(
897
+ "Preview configuration is invalid. Handler must be a function"
898
+ );
899
+ }
900
+ },
901
+ /**
902
+ * Utility to get the preview handler from the configuration
903
+ */
904
+ getPreviewHandler() {
905
+ const config = strapi2.config.get("admin.preview");
906
+ const emptyHandler = () => {
907
+ return void 0;
908
+ };
909
+ if (!this.isEnabled()) {
910
+ return emptyHandler;
911
+ }
912
+ return config?.config?.handler || emptyHandler;
913
+ }
914
+ };
915
+ };
916
+ const services$1 = {
917
+ preview: createPreviewService,
918
+ "preview-config": createPreviewConfigService
919
+ };
920
+ const getFeature = () => {
921
+ if (!strapi.features.future.isEnabled(FEATURE_ID)) {
922
+ return {};
923
+ }
924
+ return {
925
+ register() {
926
+ const config = getService(strapi, "preview-config");
927
+ config.validate();
928
+ config.register();
929
+ },
930
+ bootstrap() {
931
+ },
932
+ routes: routes$1,
933
+ controllers: controllers$1,
934
+ services: services$1
935
+ };
936
+ };
937
+ const preview = getFeature();
689
938
  const register = async ({ strapi: strapi2 }) => {
690
939
  await history.register?.({ strapi: strapi2 });
940
+ await preview.register?.({ strapi: strapi2 });
691
941
  };
692
942
  const ALLOWED_WEBHOOK_EVENTS = {
693
943
  ENTRY_PUBLISH: "entry.publish",
@@ -697,11 +947,12 @@ const bootstrap = async () => {
697
947
  Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
698
948
  strapi.get("webhookStore").addAllowedEvent(key, value);
699
949
  });
700
- getService$1("field-sizes").setCustomFieldInputSizes();
701
- await getService$1("components").syncConfigurations();
702
- await getService$1("content-types").syncConfigurations();
703
- await getService$1("permission").registerPermissions();
950
+ getService$2("field-sizes").setCustomFieldInputSizes();
951
+ await getService$2("components").syncConfigurations();
952
+ await getService$2("content-types").syncConfigurations();
953
+ await getService$2("permission").registerPermissions();
704
954
  await history.bootstrap?.({ strapi });
955
+ await preview.bootstrap?.({ strapi });
705
956
  };
706
957
  const destroy = async ({ strapi: strapi2 }) => {
707
958
  await history.destroy?.({ strapi: strapi2 });
@@ -1191,7 +1442,8 @@ const admin = {
1191
1442
  };
1192
1443
  const routes = {
1193
1444
  admin,
1194
- ...history.routes ? history.routes : {}
1445
+ ...history.routes ? history.routes : {},
1446
+ ...preview.routes ? preview.routes : {}
1195
1447
  };
1196
1448
  const hasPermissionsSchema = strapiUtils.yup.object({
1197
1449
  actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
@@ -1202,6 +1454,11 @@ const { createPolicy } = strapiUtils.policy;
1202
1454
  const hasPermissions = createPolicy({
1203
1455
  name: "plugin::content-manager.hasPermissions",
1204
1456
  validator: validateHasPermissionsInput,
1457
+ /**
1458
+ * NOTE: Action aliases are currently not checked at this level (policy).
1459
+ * This is currently the intended behavior to avoid changing the behavior of API related permissions.
1460
+ * If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
1461
+ */
1205
1462
  handler(ctx, config = {}) {
1206
1463
  const { actions = [], hasAtLeastOne = false } = config;
1207
1464
  const { userAbility } = ctx.state;
@@ -1443,7 +1700,7 @@ const createMetadasSchema = (schema) => {
1443
1700
  if (!value) {
1444
1701
  return strapiUtils.yup.string();
1445
1702
  }
1446
- const targetSchema = getService$1("content-types").findContentType(
1703
+ const targetSchema = getService$2("content-types").findContentType(
1447
1704
  schema.attributes[key].targetModel
1448
1705
  );
1449
1706
  if (!targetSchema) {
@@ -1612,7 +1869,7 @@ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultiple
1612
1869
  }
1613
1870
  };
1614
1871
  const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
1615
- const documentMetadata2 = getService$1("document-metadata");
1872
+ const documentMetadata2 = getService$2("document-metadata");
1616
1873
  const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
1617
1874
  let {
1618
1875
  meta: { availableLocales, availableStatus }
@@ -1638,8 +1895,8 @@ const createDocument = async (ctx, opts) => {
1638
1895
  const { userAbility, user } = ctx.state;
1639
1896
  const { model } = ctx.params;
1640
1897
  const { body } = ctx.request;
1641
- const documentManager2 = getService$1("document-manager");
1642
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1898
+ const documentManager2 = getService$2("document-manager");
1899
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1643
1900
  if (permissionChecker2.cannot.create()) {
1644
1901
  throw new strapiUtils.errors.ForbiddenError();
1645
1902
  }
@@ -1659,13 +1916,13 @@ const updateDocument = async (ctx, opts) => {
1659
1916
  const { userAbility, user } = ctx.state;
1660
1917
  const { id, model } = ctx.params;
1661
1918
  const { body } = ctx.request;
1662
- const documentManager2 = getService$1("document-manager");
1663
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1919
+ const documentManager2 = getService$2("document-manager");
1920
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1664
1921
  if (permissionChecker2.cannot.update()) {
1665
1922
  throw new strapiUtils.errors.ForbiddenError();
1666
1923
  }
1667
1924
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1668
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1925
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
1669
1926
  const { locale } = await getDocumentLocaleAndStatus(body, model);
1670
1927
  const [documentVersion, documentExists] = await Promise.all([
1671
1928
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
@@ -1682,7 +1939,7 @@ const updateDocument = async (ctx, opts) => {
1682
1939
  throw new strapiUtils.errors.ForbiddenError();
1683
1940
  }
1684
1941
  const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
1685
- const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
1942
+ const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
1686
1943
  const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1687
1944
  const sanitizedBody = await sanitizeFn(body);
1688
1945
  return documentManager2.update(documentVersion?.documentId || id, model, {
@@ -1696,14 +1953,14 @@ const collectionTypes = {
1696
1953
  const { userAbility } = ctx.state;
1697
1954
  const { model } = ctx.params;
1698
1955
  const { query } = ctx.request;
1699
- const documentMetadata2 = getService$1("document-metadata");
1700
- const documentManager2 = getService$1("document-manager");
1701
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1956
+ const documentMetadata2 = getService$2("document-metadata");
1957
+ const documentManager2 = getService$2("document-manager");
1958
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1702
1959
  if (permissionChecker2.cannot.read()) {
1703
1960
  return ctx.forbidden();
1704
1961
  }
1705
1962
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1706
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1963
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1707
1964
  const { locale, status } = await getDocumentLocaleAndStatus(query, model);
1708
1965
  const { results: documents, pagination } = await documentManager2.findPage(
1709
1966
  { ...permissionQuery, populate, locale, status },
@@ -1732,13 +1989,13 @@ const collectionTypes = {
1732
1989
  async findOne(ctx) {
1733
1990
  const { userAbility } = ctx.state;
1734
1991
  const { model, id } = ctx.params;
1735
- const documentManager2 = getService$1("document-manager");
1736
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1992
+ const documentManager2 = getService$2("document-manager");
1993
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1737
1994
  if (permissionChecker2.cannot.read()) {
1738
1995
  return ctx.forbidden();
1739
1996
  }
1740
1997
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1741
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1998
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1742
1999
  const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
1743
2000
  const version = await documentManager2.findOne(id, model, {
1744
2001
  populate,
@@ -1754,7 +2011,7 @@ const collectionTypes = {
1754
2011
  permissionChecker2,
1755
2012
  model,
1756
2013
  // @ts-expect-error TODO: fix
1757
- { id, locale, publishedAt: null },
2014
+ { documentId: id, locale, publishedAt: null },
1758
2015
  { availableLocales: true, availableStatus: false }
1759
2016
  );
1760
2017
  ctx.body = { data: {}, meta };
@@ -1769,7 +2026,7 @@ const collectionTypes = {
1769
2026
  async create(ctx) {
1770
2027
  const { userAbility } = ctx.state;
1771
2028
  const { model } = ctx.params;
1772
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2029
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1773
2030
  const [totalEntries, document] = await Promise.all([
1774
2031
  strapi.db.query(model).count(),
1775
2032
  createDocument(ctx)
@@ -1790,7 +2047,7 @@ const collectionTypes = {
1790
2047
  async update(ctx) {
1791
2048
  const { userAbility } = ctx.state;
1792
2049
  const { model } = ctx.params;
1793
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2050
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1794
2051
  const updatedVersion = await updateDocument(ctx);
1795
2052
  const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
1796
2053
  ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
@@ -1799,13 +2056,13 @@ const collectionTypes = {
1799
2056
  const { userAbility, user } = ctx.state;
1800
2057
  const { model, sourceId: id } = ctx.params;
1801
2058
  const { body } = ctx.request;
1802
- const documentManager2 = getService$1("document-manager");
1803
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2059
+ const documentManager2 = getService$2("document-manager");
2060
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1804
2061
  if (permissionChecker2.cannot.create()) {
1805
2062
  return ctx.forbidden();
1806
2063
  }
1807
2064
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1808
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2065
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
1809
2066
  const { locale } = await getDocumentLocaleAndStatus(body, model);
1810
2067
  const document = await documentManager2.findOne(id, model, {
1811
2068
  populate,
@@ -1844,13 +2101,13 @@ const collectionTypes = {
1844
2101
  async delete(ctx) {
1845
2102
  const { userAbility } = ctx.state;
1846
2103
  const { id, model } = ctx.params;
1847
- const documentManager2 = getService$1("document-manager");
1848
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2104
+ const documentManager2 = getService$2("document-manager");
2105
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1849
2106
  if (permissionChecker2.cannot.delete()) {
1850
2107
  return ctx.forbidden();
1851
2108
  }
1852
2109
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1853
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2110
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
1854
2111
  const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
1855
2112
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1856
2113
  if (documentLocales.length === 0) {
@@ -1872,19 +2129,42 @@ const collectionTypes = {
1872
2129
  const { userAbility } = ctx.state;
1873
2130
  const { id, model } = ctx.params;
1874
2131
  const { body } = ctx.request;
1875
- const documentManager2 = getService$1("document-manager");
1876
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2132
+ const documentManager2 = getService$2("document-manager");
2133
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1877
2134
  if (permissionChecker2.cannot.publish()) {
1878
2135
  return ctx.forbidden();
1879
2136
  }
1880
2137
  const publishedDocument = await strapi.db.transaction(async () => {
1881
2138
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1882
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1883
- const document = id ? await updateDocument(ctx, { populate }) : await createDocument(ctx, { populate });
2139
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
2140
+ let document;
2141
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2142
+ const isCreate = fp.isNil(id);
2143
+ if (isCreate) {
2144
+ if (permissionChecker2.cannot.create()) {
2145
+ throw new strapiUtils.errors.ForbiddenError();
2146
+ }
2147
+ document = await createDocument(ctx, { populate });
2148
+ }
2149
+ const isUpdate = !isCreate;
2150
+ if (isUpdate) {
2151
+ const documentExists = documentManager2.exists(model, id);
2152
+ if (!documentExists) {
2153
+ throw new strapiUtils.errors.NotFoundError("Document not found");
2154
+ }
2155
+ document = await documentManager2.findOne(id, model, { populate, locale });
2156
+ if (!document) {
2157
+ if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
2158
+ throw new strapiUtils.errors.ForbiddenError();
2159
+ }
2160
+ document = await updateDocument(ctx);
2161
+ } else if (permissionChecker2.can.update(document)) {
2162
+ await updateDocument(ctx);
2163
+ }
2164
+ }
1884
2165
  if (permissionChecker2.cannot.publish(document)) {
1885
2166
  throw new strapiUtils.errors.ForbiddenError();
1886
2167
  }
1887
- const { locale } = await getDocumentLocaleAndStatus(body, model);
1888
2168
  const publishResult = await documentManager2.publish(document.documentId, model, {
1889
2169
  locale
1890
2170
  // TODO: Allow setting creator fields on publish
@@ -1904,13 +2184,13 @@ const collectionTypes = {
1904
2184
  const { body } = ctx.request;
1905
2185
  const { documentIds } = body;
1906
2186
  await validateBulkActionInput(body);
1907
- const documentManager2 = getService$1("document-manager");
1908
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2187
+ const documentManager2 = getService$2("document-manager");
2188
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1909
2189
  if (permissionChecker2.cannot.publish()) {
1910
2190
  return ctx.forbidden();
1911
2191
  }
1912
2192
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1913
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
2193
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1914
2194
  const { locale } = await getDocumentLocaleAndStatus(body, model, {
1915
2195
  allowMultipleLocales: true
1916
2196
  });
@@ -1935,12 +2215,14 @@ const collectionTypes = {
1935
2215
  const { body } = ctx.request;
1936
2216
  const { documentIds } = body;
1937
2217
  await validateBulkActionInput(body);
1938
- const documentManager2 = getService$1("document-manager");
1939
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2218
+ const documentManager2 = getService$2("document-manager");
2219
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1940
2220
  if (permissionChecker2.cannot.unpublish()) {
1941
2221
  return ctx.forbidden();
1942
2222
  }
1943
- const { locale } = await getDocumentLocaleAndStatus(body, model);
2223
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
2224
+ allowMultipleLocales: true
2225
+ });
1944
2226
  const entityPromises = documentIds.map(
1945
2227
  (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1946
2228
  );
@@ -1963,8 +2245,8 @@ const collectionTypes = {
1963
2245
  const {
1964
2246
  body: { discardDraft, ...body }
1965
2247
  } = ctx.request;
1966
- const documentManager2 = getService$1("document-manager");
1967
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2248
+ const documentManager2 = getService$2("document-manager");
2249
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
1968
2250
  if (permissionChecker2.cannot.unpublish()) {
1969
2251
  return ctx.forbidden();
1970
2252
  }
@@ -1972,7 +2254,7 @@ const collectionTypes = {
1972
2254
  return ctx.forbidden();
1973
2255
  }
1974
2256
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1975
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2257
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
1976
2258
  const { locale } = await getDocumentLocaleAndStatus(body, model);
1977
2259
  const document = await documentManager2.findOne(id, model, {
1978
2260
  populate,
@@ -2003,13 +2285,13 @@ const collectionTypes = {
2003
2285
  const { userAbility } = ctx.state;
2004
2286
  const { id, model } = ctx.params;
2005
2287
  const { body } = ctx.request;
2006
- const documentManager2 = getService$1("document-manager");
2007
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2288
+ const documentManager2 = getService$2("document-manager");
2289
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2008
2290
  if (permissionChecker2.cannot.discard()) {
2009
2291
  return ctx.forbidden();
2010
2292
  }
2011
2293
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
2012
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2294
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2013
2295
  const { locale } = await getDocumentLocaleAndStatus(body, model);
2014
2296
  const document = await documentManager2.findOne(id, model, {
2015
2297
  populate,
@@ -2034,13 +2316,13 @@ const collectionTypes = {
2034
2316
  const { query, body } = ctx.request;
2035
2317
  const { documentIds } = body;
2036
2318
  await validateBulkActionInput(body);
2037
- const documentManager2 = getService$1("document-manager");
2038
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2319
+ const documentManager2 = getService$2("document-manager");
2320
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2039
2321
  if (permissionChecker2.cannot.delete()) {
2040
2322
  return ctx.forbidden();
2041
2323
  }
2042
2324
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
2043
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2325
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2044
2326
  const { locale } = await getDocumentLocaleAndStatus(body, model);
2045
2327
  const documentLocales = await documentManager2.findLocales(documentIds, model, {
2046
2328
  populate,
@@ -2061,13 +2343,13 @@ const collectionTypes = {
2061
2343
  async countDraftRelations(ctx) {
2062
2344
  const { userAbility } = ctx.state;
2063
2345
  const { model, id } = ctx.params;
2064
- const documentManager2 = getService$1("document-manager");
2065
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2346
+ const documentManager2 = getService$2("document-manager");
2347
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2066
2348
  if (permissionChecker2.cannot.read()) {
2067
2349
  return ctx.forbidden();
2068
2350
  }
2069
2351
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2070
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2352
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2071
2353
  const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
2072
2354
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
2073
2355
  if (!entity) {
@@ -2086,8 +2368,8 @@ const collectionTypes = {
2086
2368
  const ids = ctx.request.query.documentIds;
2087
2369
  const locale = ctx.request.query.locale;
2088
2370
  const { model } = ctx.params;
2089
- const documentManager2 = getService$1("document-manager");
2090
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2371
+ const documentManager2 = getService$2("document-manager");
2372
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2091
2373
  if (permissionChecker2.cannot.read()) {
2092
2374
  return ctx.forbidden();
2093
2375
  }
@@ -2111,13 +2393,13 @@ const collectionTypes = {
2111
2393
  };
2112
2394
  const components$1 = {
2113
2395
  findComponents(ctx) {
2114
- const components2 = getService$1("components").findAllComponents();
2115
- const { toDto } = getService$1("data-mapper");
2396
+ const components2 = getService$2("components").findAllComponents();
2397
+ const { toDto } = getService$2("data-mapper");
2116
2398
  ctx.body = { data: components2.map(toDto) };
2117
2399
  },
2118
2400
  async findComponentConfiguration(ctx) {
2119
2401
  const { uid: uid2 } = ctx.params;
2120
- const componentService = getService$1("components");
2402
+ const componentService = getService$2("components");
2121
2403
  const component = componentService.findComponent(uid2);
2122
2404
  if (!component) {
2123
2405
  return ctx.notFound("component.notFound");
@@ -2134,7 +2416,7 @@ const components$1 = {
2134
2416
  async updateComponentConfiguration(ctx) {
2135
2417
  const { uid: uid2 } = ctx.params;
2136
2418
  const { body } = ctx.request;
2137
- const componentService = getService$1("components");
2419
+ const componentService = getService$2("components");
2138
2420
  const component = componentService.findComponent(uid2);
2139
2421
  if (!component) {
2140
2422
  return ctx.notFound("component.notFound");
@@ -2168,12 +2450,12 @@ const contentTypes = {
2168
2450
  } catch (error) {
2169
2451
  return ctx.send({ error }, 400);
2170
2452
  }
2171
- const contentTypes2 = getService$1("content-types").findContentTypesByKind(kind);
2172
- const { toDto } = getService$1("data-mapper");
2453
+ const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
2454
+ const { toDto } = getService$2("data-mapper");
2173
2455
  ctx.body = { data: contentTypes2.map(toDto) };
2174
2456
  },
2175
2457
  async findContentTypesSettings(ctx) {
2176
- const { findAllContentTypes, findConfiguration } = getService$1("content-types");
2458
+ const { findAllContentTypes, findConfiguration } = getService$2("content-types");
2177
2459
  const contentTypes2 = await findAllContentTypes();
2178
2460
  const configurations = await Promise.all(
2179
2461
  contentTypes2.map(async (contentType) => {
@@ -2187,7 +2469,7 @@ const contentTypes = {
2187
2469
  },
2188
2470
  async findContentTypeConfiguration(ctx) {
2189
2471
  const { uid: uid2 } = ctx.params;
2190
- const contentTypeService = getService$1("content-types");
2472
+ const contentTypeService = getService$2("content-types");
2191
2473
  const contentType = await contentTypeService.findContentType(uid2);
2192
2474
  if (!contentType) {
2193
2475
  return ctx.notFound("contentType.notFound");
@@ -2209,13 +2491,13 @@ const contentTypes = {
2209
2491
  const { userAbility } = ctx.state;
2210
2492
  const { uid: uid2 } = ctx.params;
2211
2493
  const { body } = ctx.request;
2212
- const contentTypeService = getService$1("content-types");
2213
- const metricsService = getService$1("metrics");
2494
+ const contentTypeService = getService$2("content-types");
2495
+ const metricsService = getService$2("metrics");
2214
2496
  const contentType = await contentTypeService.findContentType(uid2);
2215
2497
  if (!contentType) {
2216
2498
  return ctx.notFound("contentType.notFound");
2217
2499
  }
2218
- if (!getService$1("permission").canConfigureContentType({ userAbility, contentType })) {
2500
+ if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
2219
2501
  return ctx.forbidden();
2220
2502
  }
2221
2503
  let input;
@@ -2248,10 +2530,10 @@ const contentTypes = {
2248
2530
  };
2249
2531
  const init = {
2250
2532
  getInitData(ctx) {
2251
- const { toDto } = getService$1("data-mapper");
2252
- const { findAllComponents } = getService$1("components");
2253
- const { getAllFieldSizes } = getService$1("field-sizes");
2254
- const { findAllContentTypes } = getService$1("content-types");
2533
+ const { toDto } = getService$2("data-mapper");
2534
+ const { findAllComponents } = getService$2("components");
2535
+ const { getAllFieldSizes } = getService$2("field-sizes");
2536
+ const { findAllContentTypes } = getService$2("content-types");
2255
2537
  ctx.body = {
2256
2538
  data: {
2257
2539
  fieldSizes: getAllFieldSizes(),
@@ -2287,36 +2569,41 @@ const addFiltersClause = (params, filtersClause) => {
2287
2569
  params.filters.$and.push(filtersClause);
2288
2570
  };
2289
2571
  const sanitizeMainField = (model, mainField, userAbility) => {
2290
- const permissionChecker2 = getService$1("permission-checker").create({
2572
+ const permissionChecker2 = getService$2("permission-checker").create({
2291
2573
  userAbility,
2292
2574
  model: model.uid
2293
2575
  });
2294
- if (!isListable(model, mainField)) {
2576
+ const isMainFieldListable = isListable(model, mainField);
2577
+ const canReadMainField = permissionChecker2.can.read(null, mainField);
2578
+ if (!isMainFieldListable || !canReadMainField) {
2295
2579
  return "id";
2296
2580
  }
2297
- if (permissionChecker2.cannot.read(null, mainField)) {
2298
- if (model.uid === "plugin::users-permissions.role") {
2299
- const userPermissionChecker = getService$1("permission-checker").create({
2300
- userAbility,
2301
- model: "plugin::users-permissions.user"
2302
- });
2303
- if (userPermissionChecker.can.read()) {
2304
- return "name";
2305
- }
2306
- }
2307
- return "id";
2581
+ if (model.uid === "plugin::users-permissions.role") {
2582
+ return "name";
2308
2583
  }
2309
2584
  return mainField;
2310
2585
  };
2311
- const addStatusToRelations = async (uid2, relations2) => {
2312
- if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.contentTypes[uid2])) {
2586
+ const addStatusToRelations = async (targetUid, relations2) => {
2587
+ if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {
2313
2588
  return relations2;
2314
2589
  }
2315
- const documentMetadata2 = getService$1("document-metadata");
2316
- const documentsAvailableStatus = await documentMetadata2.getManyAvailableStatus(uid2, relations2);
2590
+ const documentMetadata2 = getService$2("document-metadata");
2591
+ if (!relations2.length) {
2592
+ return relations2;
2593
+ }
2594
+ const firstRelation = relations2[0];
2595
+ const filters = {
2596
+ documentId: { $in: relations2.map((r) => r.documentId) },
2597
+ // NOTE: find the "opposite" status
2598
+ publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
2599
+ };
2600
+ const availableStatus = await strapi.query(targetUid).findMany({
2601
+ select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
2602
+ filters
2603
+ });
2317
2604
  return relations2.map((relation) => {
2318
- const availableStatuses = documentsAvailableStatus.filter(
2319
- (availableDocument) => availableDocument.documentId === relation.documentId
2605
+ const availableStatuses = availableStatus.filter(
2606
+ (availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
2320
2607
  );
2321
2608
  return {
2322
2609
  ...relation,
@@ -2337,11 +2624,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
2337
2624
  const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
2338
2625
  const isSourceLocalized = isLocalized(sourceModel);
2339
2626
  const isTargetLocalized = isLocalized(targetModel);
2340
- let validatedLocale = locale;
2341
- if (!targetModel || !isTargetLocalized)
2342
- validatedLocale = void 0;
2343
2627
  return {
2344
- locale: validatedLocale,
2628
+ locale,
2345
2629
  isSourceLocalized,
2346
2630
  isTargetLocalized
2347
2631
  };
@@ -2381,7 +2665,7 @@ const relations = {
2381
2665
  ctx.request?.query?.locale
2382
2666
  );
2383
2667
  const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
2384
- const permissionChecker2 = getService$1("permission-checker").create({
2668
+ const permissionChecker2 = getService$2("permission-checker").create({
2385
2669
  userAbility,
2386
2670
  model
2387
2671
  });
@@ -2406,7 +2690,7 @@ const relations = {
2406
2690
  where.id = id;
2407
2691
  }
2408
2692
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2409
- const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2693
+ const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
2410
2694
  const currentEntity = await strapi.db.query(model).findOne({
2411
2695
  where,
2412
2696
  populate
@@ -2421,7 +2705,7 @@ const relations = {
2421
2705
  }
2422
2706
  entryId = currentEntity.id;
2423
2707
  }
2424
- const modelConfig = isComponent2 ? await getService$1("components").findConfiguration(sourceSchema) : await getService$1("content-types").findConfiguration(sourceSchema);
2708
+ const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
2425
2709
  const targetSchema = strapi.getModel(targetUid);
2426
2710
  const mainField = fp.flow(
2427
2711
  fp.prop(`metadatas.${targetField}.edit.mainField`),
@@ -2444,7 +2728,7 @@ const relations = {
2444
2728
  attribute,
2445
2729
  fieldsToSelect,
2446
2730
  mainField,
2447
- source: { schema: sourceSchema },
2731
+ source: { schema: sourceSchema, isLocalized: isSourceLocalized },
2448
2732
  target: { schema: targetSchema, isLocalized: isTargetLocalized },
2449
2733
  sourceSchema,
2450
2734
  targetSchema,
@@ -2466,7 +2750,8 @@ const relations = {
2466
2750
  fieldsToSelect,
2467
2751
  mainField,
2468
2752
  source: {
2469
- schema: { uid: sourceUid, modelType: sourceModelType }
2753
+ schema: { uid: sourceUid, modelType: sourceModelType },
2754
+ isLocalized: isSourceLocalized
2470
2755
  },
2471
2756
  target: {
2472
2757
  schema: { uid: targetUid },
@@ -2474,7 +2759,7 @@ const relations = {
2474
2759
  }
2475
2760
  } = await this.extractAndValidateRequestInfo(ctx, id);
2476
2761
  const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
2477
- const permissionChecker2 = getService$1("permission-checker").create({
2762
+ const permissionChecker2 = getService$2("permission-checker").create({
2478
2763
  userAbility: ctx.state.userAbility,
2479
2764
  model: targetUid
2480
2765
  });
@@ -2504,12 +2789,16 @@ const relations = {
2504
2789
  } else {
2505
2790
  where.id = id;
2506
2791
  }
2507
- if (status) {
2508
- where[`${alias}.published_at`] = getPublishedAtClause(status, targetUid);
2792
+ const publishedAt = getPublishedAtClause(status, targetUid);
2793
+ if (!fp.isEmpty(publishedAt)) {
2794
+ where[`${alias}.published_at`] = publishedAt;
2509
2795
  }
2510
- if (filterByLocale) {
2796
+ if (isTargetLocalized && locale) {
2511
2797
  where[`${alias}.locale`] = locale;
2512
2798
  }
2799
+ if (isSourceLocalized && locale) {
2800
+ where.locale = locale;
2801
+ }
2513
2802
  if ((idsToInclude?.length ?? 0) !== 0) {
2514
2803
  where[`${alias}.id`].$notIn = idsToInclude;
2515
2804
  }
@@ -2527,7 +2816,8 @@ const relations = {
2527
2816
  id: { $notIn: fp.uniq(idsToOmit) }
2528
2817
  });
2529
2818
  }
2530
- const res = await strapi.db.query(targetUid).findPage(strapi.get("query-params").transform(targetUid, queryParams));
2819
+ const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
2820
+ const res = await strapi.db.query(targetUid).findPage(dbQuery);
2531
2821
  ctx.body = {
2532
2822
  ...res,
2533
2823
  results: await addStatusToRelations(targetUid, res.results)
@@ -2542,29 +2832,39 @@ const relations = {
2542
2832
  attribute,
2543
2833
  targetField,
2544
2834
  fieldsToSelect,
2545
- source: {
2546
- schema: { uid: sourceUid }
2547
- },
2548
- target: {
2549
- schema: { uid: targetUid }
2550
- }
2835
+ status,
2836
+ source: { schema: sourceSchema },
2837
+ target: { schema: targetSchema }
2551
2838
  } = await this.extractAndValidateRequestInfo(ctx, id);
2552
- const permissionQuery = await getService$1("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
2839
+ const { uid: sourceUid } = sourceSchema;
2840
+ const { uid: targetUid } = targetSchema;
2841
+ const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
2553
2842
  const dbQuery = strapi.db.query(sourceUid);
2554
2843
  const loadRelations = strapiUtils.relations.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
2844
+ const filters = {};
2845
+ if (sourceSchema?.options?.draftAndPublish) {
2846
+ if (targetSchema?.options?.draftAndPublish) {
2847
+ if (status === "published") {
2848
+ filters.publishedAt = { $notNull: true };
2849
+ } else {
2850
+ filters.publishedAt = { $null: true };
2851
+ }
2852
+ }
2853
+ } else if (targetSchema?.options?.draftAndPublish) {
2854
+ filters.publishedAt = { $null: true };
2855
+ }
2555
2856
  const res = await loadRelations({ id: entryId }, targetField, {
2556
- select: ["id", "documentId", "locale", "publishedAt"],
2857
+ select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
2557
2858
  ordering: "desc",
2558
2859
  page: ctx.request.query.page,
2559
- pageSize: ctx.request.query.pageSize
2860
+ pageSize: ctx.request.query.pageSize,
2861
+ filters
2560
2862
  });
2561
2863
  const loadedIds = res.results.map((item) => item.id);
2562
2864
  addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
2563
2865
  const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
2564
2866
  ...strapi.get("query-params").transform(targetUid, permissionQuery),
2565
- ordering: "desc",
2566
- page: ctx.request.query.page,
2567
- pageSize: ctx.request.query.pageSize
2867
+ ordering: "desc"
2568
2868
  });
2569
2869
  const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
2570
2870
  ctx.body = {
@@ -2579,10 +2879,10 @@ const relations = {
2579
2879
  }
2580
2880
  };
2581
2881
  const buildPopulateFromQuery = async (query, model) => {
2582
- return getService$1("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
2882
+ return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
2583
2883
  };
2584
2884
  const findDocument = async (query, uid2, opts = {}) => {
2585
- const documentManager2 = getService$1("document-manager");
2885
+ const documentManager2 = getService$2("document-manager");
2586
2886
  const populate = await buildPopulateFromQuery(query, uid2);
2587
2887
  return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
2588
2888
  };
@@ -2590,8 +2890,8 @@ const createOrUpdateDocument = async (ctx, opts) => {
2590
2890
  const { user, userAbility } = ctx.state;
2591
2891
  const { model } = ctx.params;
2592
2892
  const { body, query } = ctx.request;
2593
- const documentManager2 = getService$1("document-manager");
2594
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2893
+ const documentManager2 = getService$2("document-manager");
2894
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2595
2895
  if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
2596
2896
  throw new strapiUtils.errors.ForbiddenError();
2597
2897
  }
@@ -2632,7 +2932,7 @@ const singleTypes = {
2632
2932
  const { userAbility } = ctx.state;
2633
2933
  const { model } = ctx.params;
2634
2934
  const { query = {} } = ctx.request;
2635
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2935
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2636
2936
  if (permissionChecker2.cannot.read()) {
2637
2937
  return ctx.forbidden();
2638
2938
  }
@@ -2651,7 +2951,7 @@ const singleTypes = {
2651
2951
  permissionChecker2,
2652
2952
  model,
2653
2953
  // @ts-expect-error - fix types
2654
- { id: document.documentId, locale, publishedAt: null },
2954
+ { documentId: document.documentId, locale, publishedAt: null },
2655
2955
  { availableLocales: true, availableStatus: false }
2656
2956
  );
2657
2957
  ctx.body = { data: {}, meta };
@@ -2666,7 +2966,7 @@ const singleTypes = {
2666
2966
  async createOrUpdate(ctx) {
2667
2967
  const { userAbility } = ctx.state;
2668
2968
  const { model } = ctx.params;
2669
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2969
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2670
2970
  const document = await createOrUpdateDocument(ctx);
2671
2971
  const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
2672
2972
  ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
@@ -2675,8 +2975,8 @@ const singleTypes = {
2675
2975
  const { userAbility } = ctx.state;
2676
2976
  const { model } = ctx.params;
2677
2977
  const { query = {} } = ctx.request;
2678
- const documentManager2 = getService$1("document-manager");
2679
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2978
+ const documentManager2 = getService$2("document-manager");
2979
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2680
2980
  if (permissionChecker2.cannot.delete()) {
2681
2981
  return ctx.forbidden();
2682
2982
  }
@@ -2704,8 +3004,8 @@ const singleTypes = {
2704
3004
  const { userAbility } = ctx.state;
2705
3005
  const { model } = ctx.params;
2706
3006
  const { query = {} } = ctx.request;
2707
- const documentManager2 = getService$1("document-manager");
2708
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
3007
+ const documentManager2 = getService$2("document-manager");
3008
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2709
3009
  if (permissionChecker2.cannot.publish()) {
2710
3010
  return ctx.forbidden();
2711
3011
  }
@@ -2733,8 +3033,8 @@ const singleTypes = {
2733
3033
  body: { discardDraft, ...body },
2734
3034
  query = {}
2735
3035
  } = ctx.request;
2736
- const documentManager2 = getService$1("document-manager");
2737
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
3036
+ const documentManager2 = getService$2("document-manager");
3037
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2738
3038
  if (permissionChecker2.cannot.unpublish()) {
2739
3039
  return ctx.forbidden();
2740
3040
  }
@@ -2768,8 +3068,8 @@ const singleTypes = {
2768
3068
  const { userAbility } = ctx.state;
2769
3069
  const { model } = ctx.params;
2770
3070
  const { body, query = {} } = ctx.request;
2771
- const documentManager2 = getService$1("document-manager");
2772
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
3071
+ const documentManager2 = getService$2("document-manager");
3072
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2773
3073
  if (permissionChecker2.cannot.discard()) {
2774
3074
  return ctx.forbidden();
2775
3075
  }
@@ -2792,8 +3092,8 @@ const singleTypes = {
2792
3092
  const { userAbility } = ctx.state;
2793
3093
  const { model } = ctx.params;
2794
3094
  const { query } = ctx.request;
2795
- const documentManager2 = getService$1("document-manager");
2796
- const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
3095
+ const documentManager2 = getService$2("document-manager");
3096
+ const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
2797
3097
  const { locale } = await getDocumentLocaleAndStatus(query, model);
2798
3098
  if (permissionChecker2.cannot.read()) {
2799
3099
  return ctx.forbidden();
@@ -2817,7 +3117,7 @@ const uid$1 = {
2817
3117
  const { query = {} } = ctx.request;
2818
3118
  const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2819
3119
  await validateUIDField(contentTypeUID, field);
2820
- const uidService = getService$1("uid");
3120
+ const uidService = getService$2("uid");
2821
3121
  ctx.body = {
2822
3122
  data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
2823
3123
  };
@@ -2829,7 +3129,7 @@ const uid$1 = {
2829
3129
  const { query = {} } = ctx.request;
2830
3130
  const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2831
3131
  await validateUIDField(contentTypeUID, field);
2832
- const uidService = getService$1("uid");
3132
+ const uidService = getService$2("uid");
2833
3133
  const isAvailable = await uidService.checkUIDAvailability({
2834
3134
  contentTypeUID,
2835
3135
  field,
@@ -2850,7 +3150,8 @@ const controllers = {
2850
3150
  relations,
2851
3151
  "single-types": singleTypes,
2852
3152
  uid: uid$1,
2853
- ...history.controllers ? history.controllers : {}
3153
+ ...history.controllers ? history.controllers : {},
3154
+ ...preview.controllers ? preview.controllers : {}
2854
3155
  };
2855
3156
  const keys = {
2856
3157
  CONFIGURATION: "configuration"
@@ -3001,12 +3302,12 @@ async function syncMetadatas(configuration, schema) {
3001
3302
  return ___default.default.assign(metasWithDefaults, updatedMetas);
3002
3303
  }
3003
3304
  const getTargetSchema = (targetModel) => {
3004
- return getService$1("content-types").findContentType(targetModel);
3305
+ return getService$2("content-types").findContentType(targetModel);
3005
3306
  };
3006
3307
  const DEFAULT_LIST_LENGTH = 4;
3007
3308
  const MAX_ROW_SIZE = 12;
3008
3309
  const isAllowedFieldSize = (type, size) => {
3009
- const { getFieldSize } = getService$1("field-sizes");
3310
+ const { getFieldSize } = getService$2("field-sizes");
3010
3311
  const fieldSize = getFieldSize(type);
3011
3312
  if (!fieldSize.isResizable && size !== fieldSize.default) {
3012
3313
  return false;
@@ -3014,7 +3315,7 @@ const isAllowedFieldSize = (type, size) => {
3014
3315
  return size <= MAX_ROW_SIZE;
3015
3316
  };
3016
3317
  const getDefaultFieldSize = (attribute) => {
3017
- const { hasFieldSize, getFieldSize } = getService$1("field-sizes");
3318
+ const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
3018
3319
  return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
3019
3320
  };
3020
3321
  async function createDefaultLayouts(schema) {
@@ -3049,7 +3350,7 @@ function syncLayouts(configuration, schema) {
3049
3350
  for (const el of row) {
3050
3351
  if (!hasEditableAttribute(schema, el.name))
3051
3352
  continue;
3052
- const { hasFieldSize } = getService$1("field-sizes");
3353
+ const { hasFieldSize } = getService$2("field-sizes");
3053
3354
  const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
3054
3355
  if (!isAllowedFieldSize(fieldType, el.size)) {
3055
3356
  elementsToReAppend.push(el.name);
@@ -3189,17 +3490,17 @@ const configurationService$1 = createConfigurationService({
3189
3490
  isComponent: true,
3190
3491
  prefix: STORE_KEY_PREFIX,
3191
3492
  getModels() {
3192
- const { toContentManagerModel } = getService$1("data-mapper");
3493
+ const { toContentManagerModel } = getService$2("data-mapper");
3193
3494
  return fp.mapValues(toContentManagerModel, strapi.components);
3194
3495
  }
3195
3496
  });
3196
3497
  const components = ({ strapi: strapi2 }) => ({
3197
3498
  findAllComponents() {
3198
- const { toContentManagerModel } = getService$1("data-mapper");
3499
+ const { toContentManagerModel } = getService$2("data-mapper");
3199
3500
  return Object.values(strapi2.components).map(toContentManagerModel);
3200
3501
  },
3201
3502
  findComponent(uid2) {
3202
- const { toContentManagerModel } = getService$1("data-mapper");
3503
+ const { toContentManagerModel } = getService$2("data-mapper");
3203
3504
  const component = strapi2.components[uid2];
3204
3505
  return fp.isNil(component) ? component : toContentManagerModel(component);
3205
3506
  },
@@ -3250,17 +3551,17 @@ const configurationService = createConfigurationService({
3250
3551
  storeUtils,
3251
3552
  prefix: "content_types",
3252
3553
  getModels() {
3253
- const { toContentManagerModel } = getService$1("data-mapper");
3554
+ const { toContentManagerModel } = getService$2("data-mapper");
3254
3555
  return fp.mapValues(toContentManagerModel, strapi.contentTypes);
3255
3556
  }
3256
3557
  });
3257
3558
  const service = ({ strapi: strapi2 }) => ({
3258
3559
  findAllContentTypes() {
3259
- const { toContentManagerModel } = getService$1("data-mapper");
3560
+ const { toContentManagerModel } = getService$2("data-mapper");
3260
3561
  return Object.values(strapi2.contentTypes).map(toContentManagerModel);
3261
3562
  },
3262
3563
  findContentType(uid2) {
3263
- const { toContentManagerModel } = getService$1("data-mapper");
3564
+ const { toContentManagerModel } = getService$2("data-mapper");
3264
3565
  const contentType = strapi2.contentTypes[uid2];
3265
3566
  return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
3266
3567
  },
@@ -3289,7 +3590,7 @@ const service = ({ strapi: strapi2 }) => ({
3289
3590
  return this.findConfiguration(contentType);
3290
3591
  },
3291
3592
  findComponentsConfigurations(contentType) {
3292
- return getService$1("components").findComponentsConfigurations(contentType);
3593
+ return getService$2("components").findComponentsConfigurations(contentType);
3293
3594
  },
3294
3595
  syncConfigurations() {
3295
3596
  return configurationService.syncConfigurations();
@@ -3470,12 +3771,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
3470
3771
  ability: userAbility,
3471
3772
  model
3472
3773
  });
3473
- const toSubject = (entity) => entity ? permissionsManager.toSubject(entity, model) : model;
3774
+ const { actionProvider } = strapi2.service("admin::permission");
3775
+ const toSubject = (entity) => {
3776
+ return entity ? permissionsManager.toSubject(entity, model) : model;
3777
+ };
3474
3778
  const can = (action, entity, field) => {
3475
- return userAbility.can(action, toSubject(entity), field);
3779
+ const subject = toSubject(entity);
3780
+ const aliases = actionProvider.unstable_aliases(action, model);
3781
+ return (
3782
+ // Test the original action to see if it passes
3783
+ userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
3784
+ aliases.some((alias) => userAbility.can(alias, subject, field))
3785
+ );
3476
3786
  };
3477
3787
  const cannot = (action, entity, field) => {
3478
- return userAbility.cannot(action, toSubject(entity), field);
3788
+ const subject = toSubject(entity);
3789
+ const aliases = actionProvider.unstable_aliases(action, model);
3790
+ return (
3791
+ // Test both the original action
3792
+ userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
3793
+ aliases.every((alias) => userAbility.cannot(alias, subject, field))
3794
+ );
3479
3795
  };
3480
3796
  const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
3481
3797
  return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
@@ -3546,7 +3862,7 @@ const permission = ({ strapi: strapi2 }) => ({
3546
3862
  return userAbility.can(action);
3547
3863
  },
3548
3864
  async registerPermissions() {
3549
- const displayedContentTypes = getService$1("content-types").findDisplayedContentTypes();
3865
+ const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
3550
3866
  const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
3551
3867
  const actions = [
3552
3868
  {
@@ -3822,7 +4138,7 @@ const getQueryPopulate = async (uid2, query) => {
3822
4138
  return populateQuery;
3823
4139
  };
3824
4140
  const buildDeepPopulate = (uid2) => {
3825
- return getService$1("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
4141
+ return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
3826
4142
  };
3827
4143
  const populateBuilder = (uid2) => {
3828
4144
  let getInitialPopulate = async () => {
@@ -4007,7 +4323,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4007
4323
  */
4008
4324
  async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
4009
4325
  const versionsByLocale = fp.groupBy("locale", allVersions);
4010
- delete versionsByLocale[version.locale];
4326
+ if (version.locale) {
4327
+ delete versionsByLocale[version.locale];
4328
+ }
4011
4329
  const model = strapi2.getModel(uid2);
4012
4330
  const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
4013
4331
  const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
@@ -4133,7 +4451,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4133
4451
  */
4134
4452
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
4135
4453
  if (!document) {
4136
- return document;
4454
+ return {
4455
+ data: document,
4456
+ meta: {
4457
+ availableLocales: [],
4458
+ availableStatus: []
4459
+ }
4460
+ };
4137
4461
  }
4138
4462
  const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
4139
4463
  if (!hasDraftAndPublish) {
@@ -4357,7 +4681,8 @@ const services = {
4357
4681
  permission,
4358
4682
  "populate-builder": populateBuilder$1,
4359
4683
  uid,
4360
- ...history.services ? history.services : {}
4684
+ ...history.services ? history.services : {},
4685
+ ...preview.services ? preview.services : {}
4361
4686
  };
4362
4687
  const index = () => {
4363
4688
  return {