@strapi/content-manager 0.0.0 → 5.0.0-beta.6

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 (505) hide show
  1. package/README.md +9 -1
  2. package/dist/_chunks/CardDragPreview-DSVYodBX.js +73 -0
  3. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +1 -0
  4. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs +72 -0
  5. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +1 -0
  6. package/dist/_chunks/ComponentConfigurationPage--2aLCv-G.mjs +236 -0
  7. package/dist/_chunks/ComponentConfigurationPage--2aLCv-G.mjs.map +1 -0
  8. package/dist/_chunks/ComponentConfigurationPage-43KmCNQE.js +255 -0
  9. package/dist/_chunks/ComponentConfigurationPage-43KmCNQE.js.map +1 -0
  10. package/dist/_chunks/ComponentIcon-BBQsYCVn.js +170 -0
  11. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +1 -0
  12. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs +151 -0
  13. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +1 -0
  14. package/dist/_chunks/EditConfigurationPage-BfFzJ4Br.js +151 -0
  15. package/dist/_chunks/EditConfigurationPage-BfFzJ4Br.js.map +1 -0
  16. package/dist/_chunks/EditConfigurationPage-CUcGHHvQ.mjs +132 -0
  17. package/dist/_chunks/EditConfigurationPage-CUcGHHvQ.mjs.map +1 -0
  18. package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs +203 -0
  19. package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs.map +1 -0
  20. package/dist/_chunks/EditViewPage-CzOT5Kpj.js +224 -0
  21. package/dist/_chunks/EditViewPage-CzOT5Kpj.js.map +1 -0
  22. package/dist/_chunks/Field-Caef4JjM.js +5352 -0
  23. package/dist/_chunks/Field-Caef4JjM.js.map +1 -0
  24. package/dist/_chunks/Field-Dlh0uGnL.mjs +5319 -0
  25. package/dist/_chunks/Field-Dlh0uGnL.mjs.map +1 -0
  26. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs +50 -0
  27. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -0
  28. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js +49 -0
  29. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -0
  30. package/dist/_chunks/Form-BzuAjtRq.js +759 -0
  31. package/dist/_chunks/Form-BzuAjtRq.js.map +1 -0
  32. package/dist/_chunks/Form-EnaQL_6L.mjs +737 -0
  33. package/dist/_chunks/Form-EnaQL_6L.mjs.map +1 -0
  34. package/dist/_chunks/History-C17LiyRg.js +960 -0
  35. package/dist/_chunks/History-C17LiyRg.js.map +1 -0
  36. package/dist/_chunks/History-D6sbCJvo.mjs +938 -0
  37. package/dist/_chunks/History-D6sbCJvo.mjs.map +1 -0
  38. package/dist/_chunks/ListConfigurationPage-Ce4qs7qE.mjs +622 -0
  39. package/dist/_chunks/ListConfigurationPage-Ce4qs7qE.mjs.map +1 -0
  40. package/dist/_chunks/ListConfigurationPage-Dks5SX6f.js +643 -0
  41. package/dist/_chunks/ListConfigurationPage-Dks5SX6f.js.map +1 -0
  42. package/dist/_chunks/ListViewPage-Be7S5aKL.mjs +835 -0
  43. package/dist/_chunks/ListViewPage-Be7S5aKL.mjs.map +1 -0
  44. package/dist/_chunks/ListViewPage-BwrZrPsh.js +859 -0
  45. package/dist/_chunks/ListViewPage-BwrZrPsh.js.map +1 -0
  46. package/dist/_chunks/NoContentTypePage-CIPmYQMm.mjs +51 -0
  47. package/dist/_chunks/NoContentTypePage-CIPmYQMm.mjs.map +1 -0
  48. package/dist/_chunks/NoContentTypePage-Cu5r1-JT.js +51 -0
  49. package/dist/_chunks/NoContentTypePage-Cu5r1-JT.js.map +1 -0
  50. package/dist/_chunks/NoPermissionsPage-C-j6TEUF.js +24 -0
  51. package/dist/_chunks/NoPermissionsPage-C-j6TEUF.js.map +1 -0
  52. package/dist/_chunks/NoPermissionsPage-DhJ7LYrr.mjs +24 -0
  53. package/dist/_chunks/NoPermissionsPage-DhJ7LYrr.mjs.map +1 -0
  54. package/dist/_chunks/Relations-CY7AtkDA.mjs +684 -0
  55. package/dist/_chunks/Relations-CY7AtkDA.mjs.map +1 -0
  56. package/dist/_chunks/Relations-Czs-uZ-s.js +705 -0
  57. package/dist/_chunks/Relations-Czs-uZ-s.js.map +1 -0
  58. package/dist/_chunks/ar-BUUWXIYu.js +226 -0
  59. package/dist/_chunks/ar-BUUWXIYu.js.map +1 -0
  60. package/dist/_chunks/ar-CCEVvqGG.mjs +226 -0
  61. package/dist/_chunks/ar-CCEVvqGG.mjs.map +1 -0
  62. package/dist/_chunks/ca-5U32ON2v.mjs +201 -0
  63. package/dist/_chunks/ca-5U32ON2v.mjs.map +1 -0
  64. package/dist/_chunks/ca-Cmk45QO6.js +201 -0
  65. package/dist/_chunks/ca-Cmk45QO6.js.map +1 -0
  66. package/dist/_chunks/cs-CM2aBUar.mjs +125 -0
  67. package/dist/_chunks/cs-CM2aBUar.mjs.map +1 -0
  68. package/dist/_chunks/cs-CkJy6B2v.js +125 -0
  69. package/dist/_chunks/cs-CkJy6B2v.js.map +1 -0
  70. package/dist/_chunks/de-C72KDNOl.mjs +199 -0
  71. package/dist/_chunks/de-C72KDNOl.mjs.map +1 -0
  72. package/dist/_chunks/de-CCEmbAah.js +199 -0
  73. package/dist/_chunks/de-CCEmbAah.js.map +1 -0
  74. package/dist/_chunks/en-C-V1_90f.js +285 -0
  75. package/dist/_chunks/en-C-V1_90f.js.map +1 -0
  76. package/dist/_chunks/en-MBPul9Su.mjs +285 -0
  77. package/dist/_chunks/en-MBPul9Su.mjs.map +1 -0
  78. package/dist/_chunks/es-CeXiYflN.mjs +196 -0
  79. package/dist/_chunks/es-CeXiYflN.mjs.map +1 -0
  80. package/dist/_chunks/es-EUonQTon.js +196 -0
  81. package/dist/_chunks/es-EUonQTon.js.map +1 -0
  82. package/dist/_chunks/eu-CdALomew.mjs +202 -0
  83. package/dist/_chunks/eu-CdALomew.mjs.map +1 -0
  84. package/dist/_chunks/eu-VDH-3ovk.js +202 -0
  85. package/dist/_chunks/eu-VDH-3ovk.js.map +1 -0
  86. package/dist/_chunks/fr-B7kGGg3E.js +206 -0
  87. package/dist/_chunks/fr-B7kGGg3E.js.map +1 -0
  88. package/dist/_chunks/fr-CD9VFbPM.mjs +206 -0
  89. package/dist/_chunks/fr-CD9VFbPM.mjs.map +1 -0
  90. package/dist/_chunks/gu-BRmF601H.js +200 -0
  91. package/dist/_chunks/gu-BRmF601H.js.map +1 -0
  92. package/dist/_chunks/gu-CNpaMDpH.mjs +200 -0
  93. package/dist/_chunks/gu-CNpaMDpH.mjs.map +1 -0
  94. package/dist/_chunks/hi-CCJBptSq.js +200 -0
  95. package/dist/_chunks/hi-CCJBptSq.js.map +1 -0
  96. package/dist/_chunks/hi-Dwvd04m3.mjs +200 -0
  97. package/dist/_chunks/hi-Dwvd04m3.mjs.map +1 -0
  98. package/dist/_chunks/hooks-BAaaKPS_.js +7 -0
  99. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -0
  100. package/dist/_chunks/hooks-E5u1mcgM.mjs +8 -0
  101. package/dist/_chunks/hooks-E5u1mcgM.mjs.map +1 -0
  102. package/dist/_chunks/hu-CeYvaaO0.mjs +202 -0
  103. package/dist/_chunks/hu-CeYvaaO0.mjs.map +1 -0
  104. package/dist/_chunks/hu-sNV_yLYy.js +202 -0
  105. package/dist/_chunks/hu-sNV_yLYy.js.map +1 -0
  106. package/dist/_chunks/id-B5Ser98A.js +160 -0
  107. package/dist/_chunks/id-B5Ser98A.js.map +1 -0
  108. package/dist/_chunks/id-BtwA9WJT.mjs +160 -0
  109. package/dist/_chunks/id-BtwA9WJT.mjs.map +1 -0
  110. package/dist/_chunks/index-DNVx8ssZ.mjs +3175 -0
  111. package/dist/_chunks/index-DNVx8ssZ.mjs.map +1 -0
  112. package/dist/_chunks/index-X_2tafck.js +3195 -0
  113. package/dist/_chunks/index-X_2tafck.js.map +1 -0
  114. package/dist/_chunks/it-BrVPqaf1.mjs +162 -0
  115. package/dist/_chunks/it-BrVPqaf1.mjs.map +1 -0
  116. package/dist/_chunks/it-DkBIs7vD.js +162 -0
  117. package/dist/_chunks/it-DkBIs7vD.js.map +1 -0
  118. package/dist/_chunks/ja-CcFe8diO.js +196 -0
  119. package/dist/_chunks/ja-CcFe8diO.js.map +1 -0
  120. package/dist/_chunks/ja-CtsUxOvk.mjs +196 -0
  121. package/dist/_chunks/ja-CtsUxOvk.mjs.map +1 -0
  122. package/dist/_chunks/ko-HVQRlfUI.mjs +195 -0
  123. package/dist/_chunks/ko-HVQRlfUI.mjs.map +1 -0
  124. package/dist/_chunks/ko-woFZPmLk.js +195 -0
  125. package/dist/_chunks/ko-woFZPmLk.js.map +1 -0
  126. package/dist/_chunks/layout-Dnh0PNp9.mjs +453 -0
  127. package/dist/_chunks/layout-Dnh0PNp9.mjs.map +1 -0
  128. package/dist/_chunks/layout-dBc7wN7L.js +473 -0
  129. package/dist/_chunks/layout-dBc7wN7L.js.map +1 -0
  130. package/dist/_chunks/ml-BihZwQit.mjs +200 -0
  131. package/dist/_chunks/ml-BihZwQit.mjs.map +1 -0
  132. package/dist/_chunks/ml-C2W8N8k1.js +200 -0
  133. package/dist/_chunks/ml-C2W8N8k1.js.map +1 -0
  134. package/dist/_chunks/ms-BuFotyP_.js +144 -0
  135. package/dist/_chunks/ms-BuFotyP_.js.map +1 -0
  136. package/dist/_chunks/ms-m_WjyWx7.mjs +144 -0
  137. package/dist/_chunks/ms-m_WjyWx7.mjs.map +1 -0
  138. package/dist/_chunks/nl-D4R9gHx5.mjs +202 -0
  139. package/dist/_chunks/nl-D4R9gHx5.mjs.map +1 -0
  140. package/dist/_chunks/nl-bbEOHChV.js +202 -0
  141. package/dist/_chunks/nl-bbEOHChV.js.map +1 -0
  142. package/dist/_chunks/objects-gigeqt7s.js +49 -0
  143. package/dist/_chunks/objects-gigeqt7s.js.map +1 -0
  144. package/dist/_chunks/objects-mKMAmfec.mjs +47 -0
  145. package/dist/_chunks/objects-mKMAmfec.mjs.map +1 -0
  146. package/dist/_chunks/pl-sbx9mSt_.mjs +199 -0
  147. package/dist/_chunks/pl-sbx9mSt_.mjs.map +1 -0
  148. package/dist/_chunks/pl-uzwG-hk7.js +199 -0
  149. package/dist/_chunks/pl-uzwG-hk7.js.map +1 -0
  150. package/dist/_chunks/pt-BR-BiOz37D9.js +201 -0
  151. package/dist/_chunks/pt-BR-BiOz37D9.js.map +1 -0
  152. package/dist/_chunks/pt-BR-C71iDxnh.mjs +201 -0
  153. package/dist/_chunks/pt-BR-C71iDxnh.mjs.map +1 -0
  154. package/dist/_chunks/pt-BsaFvS8-.mjs +95 -0
  155. package/dist/_chunks/pt-BsaFvS8-.mjs.map +1 -0
  156. package/dist/_chunks/pt-CeXQuq50.js +95 -0
  157. package/dist/_chunks/pt-CeXQuq50.js.map +1 -0
  158. package/dist/_chunks/relations-4pHtBrHJ.js +134 -0
  159. package/dist/_chunks/relations-4pHtBrHJ.js.map +1 -0
  160. package/dist/_chunks/relations-Dx7tMKJN.mjs +135 -0
  161. package/dist/_chunks/relations-Dx7tMKJN.mjs.map +1 -0
  162. package/dist/_chunks/ru-BE6A4Exp.mjs +231 -0
  163. package/dist/_chunks/ru-BE6A4Exp.mjs.map +1 -0
  164. package/dist/_chunks/ru-BT3ybNny.js +231 -0
  165. package/dist/_chunks/ru-BT3ybNny.js.map +1 -0
  166. package/dist/_chunks/sa-CcvkYInH.js +200 -0
  167. package/dist/_chunks/sa-CcvkYInH.js.map +1 -0
  168. package/dist/_chunks/sa-Dag0k-Z8.mjs +200 -0
  169. package/dist/_chunks/sa-Dag0k-Z8.mjs.map +1 -0
  170. package/dist/_chunks/sk-BFg-R8qJ.mjs +202 -0
  171. package/dist/_chunks/sk-BFg-R8qJ.mjs.map +1 -0
  172. package/dist/_chunks/sk-CvY09Xjv.js +202 -0
  173. package/dist/_chunks/sk-CvY09Xjv.js.map +1 -0
  174. package/dist/_chunks/sv-CUnfWGsh.mjs +202 -0
  175. package/dist/_chunks/sv-CUnfWGsh.mjs.map +1 -0
  176. package/dist/_chunks/sv-MYDuzgvT.js +202 -0
  177. package/dist/_chunks/sv-MYDuzgvT.js.map +1 -0
  178. package/dist/_chunks/th-BqbI8lIT.mjs +148 -0
  179. package/dist/_chunks/th-BqbI8lIT.mjs.map +1 -0
  180. package/dist/_chunks/th-D9_GfAjc.js +148 -0
  181. package/dist/_chunks/th-D9_GfAjc.js.map +1 -0
  182. package/dist/_chunks/tr-CgeK3wJM.mjs +199 -0
  183. package/dist/_chunks/tr-CgeK3wJM.mjs.map +1 -0
  184. package/dist/_chunks/tr-D9UH-O_R.js +199 -0
  185. package/dist/_chunks/tr-D9UH-O_R.js.map +1 -0
  186. package/dist/_chunks/uk-C8EiqJY7.js +144 -0
  187. package/dist/_chunks/uk-C8EiqJY7.js.map +1 -0
  188. package/dist/_chunks/uk-CR-zDhAY.mjs +144 -0
  189. package/dist/_chunks/uk-CR-zDhAY.mjs.map +1 -0
  190. package/dist/_chunks/urls-CbOsUOoW.mjs +7 -0
  191. package/dist/_chunks/urls-CbOsUOoW.mjs.map +1 -0
  192. package/dist/_chunks/urls-DzZya_gm.js +6 -0
  193. package/dist/_chunks/urls-DzZya_gm.js.map +1 -0
  194. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs +231 -0
  195. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -0
  196. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js +249 -0
  197. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -0
  198. package/dist/_chunks/vi-CJlYDheJ.js +111 -0
  199. package/dist/_chunks/vi-CJlYDheJ.js.map +1 -0
  200. package/dist/_chunks/vi-DUXIk_fw.mjs +111 -0
  201. package/dist/_chunks/vi-DUXIk_fw.mjs.map +1 -0
  202. package/dist/_chunks/zh-BWZspA60.mjs +209 -0
  203. package/dist/_chunks/zh-BWZspA60.mjs.map +1 -0
  204. package/dist/_chunks/zh-CQQfszqR.js +209 -0
  205. package/dist/_chunks/zh-CQQfszqR.js.map +1 -0
  206. package/dist/_chunks/zh-Hans-9kOncHGw.js +952 -0
  207. package/dist/_chunks/zh-Hans-9kOncHGw.js.map +1 -0
  208. package/dist/_chunks/zh-Hans-BPQcRIyH.mjs +952 -0
  209. package/dist/_chunks/zh-Hans-BPQcRIyH.mjs.map +1 -0
  210. package/dist/admin/index.js +11 -0
  211. package/dist/admin/index.js.map +1 -0
  212. package/dist/admin/index.mjs +11 -0
  213. package/dist/admin/index.mjs.map +1 -0
  214. package/dist/admin/src/components/ComponentIcon.d.ts +8 -0
  215. package/dist/admin/src/components/ConfigurationForm/EditFieldForm.d.ts +9 -0
  216. package/dist/admin/src/components/ConfigurationForm/Fields.d.ts +21 -0
  217. package/dist/admin/src/components/ConfigurationForm/Form.d.ts +32 -0
  218. package/dist/admin/src/components/DragLayer.d.ts +13 -0
  219. package/dist/admin/src/components/DragPreviews/CardDragPreview.d.ts +7 -0
  220. package/dist/admin/src/components/DragPreviews/ComponentDragPreview.d.ts +6 -0
  221. package/dist/admin/src/components/DragPreviews/RelationDragPreview.d.ts +11 -0
  222. package/dist/admin/src/components/FieldTypeIcon.d.ts +9 -0
  223. package/dist/admin/src/components/InjectionZone.d.ts +45 -0
  224. package/dist/admin/src/components/LeftMenu.d.ts +2 -0
  225. package/dist/admin/src/components/RelativeTime.d.ts +28 -0
  226. package/dist/admin/src/constants/attributes.d.ts +14 -0
  227. package/dist/admin/src/constants/collections.d.ts +3 -0
  228. package/dist/admin/src/constants/dragAndDrop.d.ts +8 -0
  229. package/dist/admin/src/constants/hooks.d.ts +26 -0
  230. package/dist/admin/src/constants/plugin.d.ts +3 -0
  231. package/dist/admin/src/content-manager.d.ts +133 -0
  232. package/dist/admin/src/exports.d.ts +11 -0
  233. package/dist/admin/src/features/DocumentRBAC.d.ts +36 -0
  234. package/dist/admin/src/history/components/HistoryAction.d.ts +3 -0
  235. package/dist/admin/src/history/components/VersionContent.d.ts +17 -0
  236. package/dist/admin/src/history/components/VersionHeader.d.ts +5 -0
  237. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +19 -0
  238. package/dist/admin/src/history/components/VersionsList.d.ts +2 -0
  239. package/dist/admin/src/history/pages/History.d.ts +27 -0
  240. package/dist/admin/src/history/routes.d.ts +6 -0
  241. package/dist/admin/src/history/services/historyVersion.d.ts +12 -0
  242. package/dist/admin/src/hooks/useContentManagerInitData.d.ts +15 -0
  243. package/dist/admin/src/hooks/useContentTypeSchema.d.ts +25 -0
  244. package/dist/admin/src/hooks/useDebounce.d.ts +1 -0
  245. package/dist/admin/src/hooks/useDocument.d.ts +90 -0
  246. package/dist/admin/src/hooks/useDocumentActions.d.ts +102 -0
  247. package/dist/admin/src/hooks/useDocumentLayout.d.ts +137 -0
  248. package/dist/admin/src/hooks/useDragAndDrop.d.ts +51 -0
  249. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +14 -0
  250. package/dist/admin/src/hooks/useLazyComponents.d.ts +13 -0
  251. package/dist/admin/src/hooks/useOnce.d.ts +2 -0
  252. package/dist/admin/src/hooks/usePrev.d.ts +1 -0
  253. package/dist/admin/src/index.d.ts +16 -0
  254. package/dist/admin/src/layout.d.ts +2 -0
  255. package/dist/admin/src/modules/app.d.ts +20 -0
  256. package/dist/admin/src/modules/hooks.d.ts +10 -0
  257. package/dist/admin/src/modules/reducers.d.ts +6 -0
  258. package/dist/admin/src/pages/ComponentConfigurationPage.d.ts +3 -0
  259. package/dist/admin/src/pages/EditConfigurationPage.d.ts +3 -0
  260. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +3 -0
  261. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +69 -0
  262. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +16 -0
  263. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +3 -0
  264. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Heading.d.ts +3 -0
  265. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.d.ts +3 -0
  266. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Link.d.ts +3 -0
  267. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.d.ts +3 -0
  268. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Paragraph.d.ts +3 -0
  269. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Quote.d.ts +3 -0
  270. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.d.ts +6 -0
  271. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.d.ts +61 -0
  272. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +11 -0
  273. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.d.ts +10 -0
  274. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.d.ts +10 -0
  275. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Modifiers.d.ts +16 -0
  276. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/plugins/withImages.d.ts +11 -0
  277. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/plugins/withLinks.d.ts +9 -0
  278. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.d.ts +8 -0
  279. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/conversions.d.ts +13 -0
  280. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/enterKey.d.ts +6 -0
  281. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/links.d.ts +10 -0
  282. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/types.d.ts +10 -0
  283. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Initializer.d.ts +9 -0
  284. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +18 -0
  285. package/dist/admin/src/pages/EditView/components/FormInputs/Component/NonRepeatable.d.ts +5 -0
  286. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Repeatable.d.ts +5 -0
  287. package/dist/admin/src/pages/EditView/components/FormInputs/ComponentContext.d.ts +42 -0
  288. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/AddComponentButton.d.ts +11 -0
  289. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCard.d.ts +9 -0
  290. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +17 -0
  291. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.d.ts +9 -0
  292. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +14 -0
  293. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicZoneLabel.d.ts +12 -0
  294. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +14 -0
  295. package/dist/admin/src/pages/EditView/components/FormInputs/NotAllowed.d.ts +7 -0
  296. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +26 -0
  297. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +9 -0
  298. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Editor.d.ts +17 -0
  299. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +60 -0
  300. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +11 -0
  301. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.d.ts +5 -0
  302. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +7 -0
  303. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygNav.d.ts +17 -0
  304. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +55 -0
  305. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/utils/continueList.d.ts +5 -0
  306. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/utils/mdRenderer.d.ts +4 -0
  307. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/utils/utils.d.ts +16 -0
  308. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +5 -0
  309. package/dist/admin/src/pages/EditView/components/Header.d.ts +35 -0
  310. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +17 -0
  311. package/dist/admin/src/pages/EditView/components/Panels.d.ts +10 -0
  312. package/dist/admin/src/pages/EditView/utils/data.d.ts +33 -0
  313. package/dist/admin/src/pages/EditView/utils/forms.d.ts +9 -0
  314. package/dist/admin/src/pages/ListConfiguration/ListConfigurationPage.d.ts +10 -0
  315. package/dist/admin/src/pages/ListConfiguration/components/DraggableCard.d.ts +12 -0
  316. package/dist/admin/src/pages/ListConfiguration/components/EditFieldForm.d.ts +8 -0
  317. package/dist/admin/src/pages/ListConfiguration/components/Header.d.ts +8 -0
  318. package/dist/admin/src/pages/ListConfiguration/components/Settings.d.ts +19 -0
  319. package/dist/admin/src/pages/ListConfiguration/components/SortDisplayedFields.d.ts +6 -0
  320. package/dist/admin/src/pages/ListView/ListViewPage.d.ts +3 -0
  321. package/dist/admin/src/pages/ListView/components/AutoCloneFailureModal.d.ts +7 -0
  322. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +51 -0
  323. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +15 -0
  324. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +31 -0
  325. package/dist/admin/src/pages/ListView/components/Filters.d.ts +8 -0
  326. package/dist/admin/src/pages/ListView/components/TableActions.d.ts +8 -0
  327. package/dist/admin/src/pages/ListView/components/TableCells/CellContent.d.ts +9 -0
  328. package/dist/admin/src/pages/ListView/components/TableCells/CellValue.d.ts +8 -0
  329. package/dist/admin/src/pages/ListView/components/TableCells/Components.d.ts +12 -0
  330. package/dist/admin/src/pages/ListView/components/TableCells/Media.d.ts +23 -0
  331. package/dist/admin/src/pages/ListView/components/TableCells/Relations.d.ts +12 -0
  332. package/dist/admin/src/pages/ListView/components/ViewSettingsMenu.d.ts +10 -0
  333. package/dist/admin/src/pages/NoContentTypePage.d.ts +2 -0
  334. package/dist/admin/src/pages/NoPermissionsPage.d.ts +2 -0
  335. package/dist/admin/src/router.d.ts +5 -0
  336. package/dist/admin/src/services/api.d.ts +3 -0
  337. package/dist/admin/src/services/components.d.ts +5 -0
  338. package/dist/admin/src/services/contentTypes.d.ts +17 -0
  339. package/dist/admin/src/services/documents.d.ts +89 -0
  340. package/dist/admin/src/services/init.d.ts +9 -0
  341. package/dist/admin/src/services/relations.d.ts +49 -0
  342. package/dist/admin/src/services/uid.d.ts +32 -0
  343. package/dist/admin/src/utils/api.d.ts +38 -0
  344. package/dist/admin/src/utils/attributes.d.ts +19 -0
  345. package/dist/admin/src/utils/objects.d.ts +33 -0
  346. package/dist/admin/src/utils/relations.d.ts +12 -0
  347. package/dist/admin/src/utils/strings.d.ts +2 -0
  348. package/dist/admin/src/utils/translations.d.ts +4 -0
  349. package/dist/admin/src/utils/urls.d.ts +2 -0
  350. package/dist/admin/src/utils/users.d.ts +6 -0
  351. package/dist/admin/src/utils/validation.d.ts +12 -0
  352. package/dist/server/index.js +4238 -0
  353. package/dist/server/index.js.map +1 -0
  354. package/dist/server/index.mjs +4214 -0
  355. package/dist/server/index.mjs.map +1 -0
  356. package/dist/server/src/bootstrap.d.ts +3 -0
  357. package/dist/server/src/bootstrap.d.ts.map +1 -0
  358. package/dist/server/src/config.d.ts +6 -0
  359. package/dist/server/src/config.d.ts.map +1 -0
  360. package/dist/server/src/constants/index.d.ts +6 -0
  361. package/dist/server/src/constants/index.d.ts.map +1 -0
  362. package/dist/server/src/controllers/collection-types.d.ts +23 -0
  363. package/dist/server/src/controllers/collection-types.d.ts.map +1 -0
  364. package/dist/server/src/controllers/components.d.ts +7 -0
  365. package/dist/server/src/controllers/components.d.ts.map +1 -0
  366. package/dist/server/src/controllers/content-types.d.ts +8 -0
  367. package/dist/server/src/controllers/content-types.d.ts.map +1 -0
  368. package/dist/server/src/controllers/index.d.ts +53 -0
  369. package/dist/server/src/controllers/index.d.ts.map +1 -0
  370. package/dist/server/src/controllers/init.d.ts +5 -0
  371. package/dist/server/src/controllers/init.d.ts.map +1 -0
  372. package/dist/server/src/controllers/relations.d.ts +13 -0
  373. package/dist/server/src/controllers/relations.d.ts.map +1 -0
  374. package/dist/server/src/controllers/single-types.d.ts +11 -0
  375. package/dist/server/src/controllers/single-types.d.ts.map +1 -0
  376. package/dist/server/src/controllers/uid.d.ts +6 -0
  377. package/dist/server/src/controllers/uid.d.ts.map +1 -0
  378. package/dist/server/src/controllers/utils/clone.d.ts +12 -0
  379. package/dist/server/src/controllers/utils/clone.d.ts.map +1 -0
  380. package/dist/server/src/controllers/utils/dimensions.d.ts +5 -0
  381. package/dist/server/src/controllers/utils/dimensions.d.ts.map +1 -0
  382. package/dist/server/src/controllers/validation/index.d.ts +20 -0
  383. package/dist/server/src/controllers/validation/index.d.ts.map +1 -0
  384. package/dist/server/src/controllers/validation/model-configuration.d.ts +22 -0
  385. package/dist/server/src/controllers/validation/model-configuration.d.ts.map +1 -0
  386. package/dist/server/src/controllers/validation/relations.d.ts +4 -0
  387. package/dist/server/src/controllers/validation/relations.d.ts.map +1 -0
  388. package/dist/server/src/destroy.d.ts +4 -0
  389. package/dist/server/src/destroy.d.ts.map +1 -0
  390. package/dist/server/src/history/constants.d.ts +3 -0
  391. package/dist/server/src/history/constants.d.ts.map +1 -0
  392. package/dist/server/src/history/controllers/history-version.d.ts +19 -0
  393. package/dist/server/src/history/controllers/history-version.d.ts.map +1 -0
  394. package/dist/server/src/history/controllers/index.d.ts +2 -0
  395. package/dist/server/src/history/controllers/index.d.ts.map +1 -0
  396. package/dist/server/src/history/controllers/validation/history-version.d.ts +2 -0
  397. package/dist/server/src/history/controllers/validation/history-version.d.ts.map +1 -0
  398. package/dist/server/src/history/index.d.ts +4 -0
  399. package/dist/server/src/history/index.d.ts.map +1 -0
  400. package/dist/server/src/history/models/history-version.d.ts +4 -0
  401. package/dist/server/src/history/models/history-version.d.ts.map +1 -0
  402. package/dist/server/src/history/routes/history-version.d.ts +4 -0
  403. package/dist/server/src/history/routes/history-version.d.ts.map +1 -0
  404. package/dist/server/src/history/routes/index.d.ts +8 -0
  405. package/dist/server/src/history/routes/index.d.ts.map +1 -0
  406. package/dist/server/src/history/services/history.d.ts +18 -0
  407. package/dist/server/src/history/services/history.d.ts.map +1 -0
  408. package/dist/server/src/history/services/index.d.ts +15 -0
  409. package/dist/server/src/history/services/index.d.ts.map +1 -0
  410. package/dist/server/src/history/services/utils.d.ts +12 -0
  411. package/dist/server/src/history/services/utils.d.ts.map +1 -0
  412. package/dist/server/src/history/utils.d.ts +18 -0
  413. package/dist/server/src/history/utils.d.ts.map +1 -0
  414. package/dist/server/src/index.d.ts +374 -0
  415. package/dist/server/src/index.d.ts.map +1 -0
  416. package/dist/server/src/middlewares/index.d.ts +3 -0
  417. package/dist/server/src/middlewares/index.d.ts.map +1 -0
  418. package/dist/server/src/middlewares/routing.d.ts +4 -0
  419. package/dist/server/src/middlewares/routing.d.ts.map +1 -0
  420. package/dist/server/src/policies/hasPermissions.d.ts +7 -0
  421. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -0
  422. package/dist/server/src/policies/index.d.ts +9 -0
  423. package/dist/server/src/policies/index.d.ts.map +1 -0
  424. package/dist/server/src/register.d.ts +4 -0
  425. package/dist/server/src/register.d.ts.map +1 -0
  426. package/dist/server/src/routes/admin.d.ts +41 -0
  427. package/dist/server/src/routes/admin.d.ts.map +1 -0
  428. package/dist/server/src/routes/index.d.ts +43 -0
  429. package/dist/server/src/routes/index.d.ts.map +1 -0
  430. package/dist/server/src/services/components.d.ts +32 -0
  431. package/dist/server/src/services/components.d.ts.map +1 -0
  432. package/dist/server/src/services/configuration.d.ts +20 -0
  433. package/dist/server/src/services/configuration.d.ts.map +1 -0
  434. package/dist/server/src/services/content-types.d.ts +18 -0
  435. package/dist/server/src/services/content-types.d.ts.map +1 -0
  436. package/dist/server/src/services/data-mapper.d.ts +20 -0
  437. package/dist/server/src/services/data-mapper.d.ts.map +1 -0
  438. package/dist/server/src/services/document-manager.d.ts +47 -0
  439. package/dist/server/src/services/document-manager.d.ts.map +1 -0
  440. package/dist/server/src/services/document-metadata.d.ts +88 -0
  441. package/dist/server/src/services/document-metadata.d.ts.map +1 -0
  442. package/dist/server/src/services/field-sizes.d.ts +19 -0
  443. package/dist/server/src/services/field-sizes.d.ts.map +1 -0
  444. package/dist/server/src/services/index.d.ts +266 -0
  445. package/dist/server/src/services/index.d.ts.map +1 -0
  446. package/dist/server/src/services/metrics.d.ts +9 -0
  447. package/dist/server/src/services/metrics.d.ts.map +1 -0
  448. package/dist/server/src/services/permission-checker.d.ts +54 -0
  449. package/dist/server/src/services/permission-checker.d.ts.map +1 -0
  450. package/dist/server/src/services/permission.d.ts +12 -0
  451. package/dist/server/src/services/permission.d.ts.map +1 -0
  452. package/dist/server/src/services/populate-builder.d.ts +30 -0
  453. package/dist/server/src/services/populate-builder.d.ts.map +1 -0
  454. package/dist/server/src/services/uid.d.ts +25 -0
  455. package/dist/server/src/services/uid.d.ts.map +1 -0
  456. package/dist/server/src/services/utils/configuration/attributes.d.ts +17 -0
  457. package/dist/server/src/services/utils/configuration/attributes.d.ts.map +1 -0
  458. package/dist/server/src/services/utils/configuration/index.d.ts +21 -0
  459. package/dist/server/src/services/utils/configuration/index.d.ts.map +1 -0
  460. package/dist/server/src/services/utils/configuration/layouts.d.ts +14 -0
  461. package/dist/server/src/services/utils/configuration/layouts.d.ts.map +1 -0
  462. package/dist/server/src/services/utils/configuration/metadatas.d.ts +5 -0
  463. package/dist/server/src/services/utils/configuration/metadatas.d.ts.map +1 -0
  464. package/dist/server/src/services/utils/configuration/settings.d.ts +5 -0
  465. package/dist/server/src/services/utils/configuration/settings.d.ts.map +1 -0
  466. package/dist/server/src/services/utils/count.d.ts +5 -0
  467. package/dist/server/src/services/utils/count.d.ts.map +1 -0
  468. package/dist/server/src/services/utils/draft.d.ts +11 -0
  469. package/dist/server/src/services/utils/draft.d.ts.map +1 -0
  470. package/dist/server/src/services/utils/populate.d.ts +35 -0
  471. package/dist/server/src/services/utils/populate.d.ts.map +1 -0
  472. package/dist/server/src/services/utils/store.d.ts +16 -0
  473. package/dist/server/src/services/utils/store.d.ts.map +1 -0
  474. package/dist/server/src/utils/index.d.ts +9 -0
  475. package/dist/server/src/utils/index.d.ts.map +1 -0
  476. package/dist/server/src/validation/policies/hasPermissions.d.ts +2 -0
  477. package/dist/server/src/validation/policies/hasPermissions.d.ts.map +1 -0
  478. package/dist/shared/contracts/collection-types.d.ts +328 -0
  479. package/dist/shared/contracts/collection-types.d.ts.map +1 -0
  480. package/dist/shared/contracts/components.d.ts +65 -0
  481. package/dist/shared/contracts/components.d.ts.map +1 -0
  482. package/dist/shared/contracts/content-types.d.ts +113 -0
  483. package/dist/shared/contracts/content-types.d.ts.map +1 -0
  484. package/dist/shared/contracts/history-versions.d.ts +92 -0
  485. package/dist/shared/contracts/history-versions.d.ts.map +1 -0
  486. package/dist/shared/contracts/index.d.ts +10 -0
  487. package/dist/shared/contracts/index.d.ts.map +1 -0
  488. package/dist/shared/contracts/init.d.ts +24 -0
  489. package/dist/shared/contracts/init.d.ts.map +1 -0
  490. package/dist/shared/contracts/relations.d.ts +70 -0
  491. package/dist/shared/contracts/relations.d.ts.map +1 -0
  492. package/dist/shared/contracts/review-workflows.d.ts +78 -0
  493. package/dist/shared/contracts/review-workflows.d.ts.map +1 -0
  494. package/dist/shared/contracts/single-types.d.ts +113 -0
  495. package/dist/shared/contracts/single-types.d.ts.map +1 -0
  496. package/dist/shared/contracts/uid.d.ts +48 -0
  497. package/dist/shared/contracts/uid.d.ts.map +1 -0
  498. package/dist/shared/index.d.ts +2 -0
  499. package/dist/shared/index.d.ts.map +1 -0
  500. package/dist/shared/index.js +43 -0
  501. package/dist/shared/index.js.map +1 -0
  502. package/dist/shared/index.mjs +43 -0
  503. package/dist/shared/index.mjs.map +1 -0
  504. package/package.json +114 -2
  505. package/strapi-server.js +3 -0
@@ -0,0 +1,4238 @@
1
+ "use strict";
2
+ const strapiUtils = require("@strapi/utils");
3
+ const fp = require("lodash/fp");
4
+ require("@strapi/types");
5
+ const yup = require("yup");
6
+ const nodeSchedule = require("node-schedule");
7
+ const isNil = require("lodash/isNil");
8
+ const _ = require("lodash");
9
+ const qs = require("qs");
10
+ const slugify = require("@sindresorhus/slugify");
11
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
12
+ function _interopNamespace(e) {
13
+ if (e && e.__esModule)
14
+ return e;
15
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
16
+ if (e) {
17
+ for (const k in e) {
18
+ if (k !== "default") {
19
+ const d = Object.getOwnPropertyDescriptor(e, k);
20
+ Object.defineProperty(n, k, d.get ? d : {
21
+ enumerable: true,
22
+ get: () => e[k]
23
+ });
24
+ }
25
+ }
26
+ }
27
+ n.default = e;
28
+ return Object.freeze(n);
29
+ }
30
+ const strapiUtils__default = /* @__PURE__ */ _interopDefault(strapiUtils);
31
+ const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
32
+ const isNil__default = /* @__PURE__ */ _interopDefault(isNil);
33
+ const ___default = /* @__PURE__ */ _interopDefault(_);
34
+ const qs__default = /* @__PURE__ */ _interopDefault(qs);
35
+ const slugify__default = /* @__PURE__ */ _interopDefault(slugify);
36
+ const getService$1 = (name) => {
37
+ return strapi.plugin("content-manager").service(name);
38
+ };
39
+ function getService(strapi2, name) {
40
+ return strapi2.service(`plugin::content-manager.${name}`);
41
+ }
42
+ const historyRestoreVersionSchema = yup__namespace.object().shape({
43
+ contentType: yup__namespace.string().trim().required()
44
+ }).required();
45
+ const validateRestoreVersion = strapiUtils.validateYupSchema(historyRestoreVersionSchema);
46
+ const getValidPagination = ({ page, pageSize }) => {
47
+ let pageNumber = 1;
48
+ let pageSizeNumber = 20;
49
+ if (page) {
50
+ const parsedPage = parseInt(page, 10);
51
+ pageNumber = parseInt(page, 10);
52
+ if (!Number.isNaN(parsedPage) && parsedPage >= 1) {
53
+ pageNumber = parsedPage;
54
+ }
55
+ }
56
+ if (pageSize) {
57
+ const parsedPageSize = parseInt(pageSize, 10);
58
+ if (!Number.isNaN(parsedPageSize) && parsedPageSize >= 1 && parsedPageSize <= 100) {
59
+ pageSizeNumber = parsedPageSize;
60
+ }
61
+ }
62
+ return { page: pageNumber, pageSize: pageSizeNumber };
63
+ };
64
+ const createHistoryVersionController = ({ strapi: strapi2 }) => {
65
+ return {
66
+ async findMany(ctx) {
67
+ const contentTypeUid = ctx.query.contentType;
68
+ const isSingleType = strapi2.getModel(contentTypeUid)?.kind === "singleType";
69
+ if (isSingleType && !contentTypeUid) {
70
+ throw new strapiUtils.errors.ForbiddenError("contentType is required");
71
+ }
72
+ if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
73
+ throw new strapiUtils.errors.ForbiddenError("contentType and documentId are required");
74
+ }
75
+ const permissionChecker2 = getService$1("permission-checker").create({
76
+ userAbility: ctx.state.userAbility,
77
+ model: ctx.query.contentType
78
+ });
79
+ if (permissionChecker2.cannot.read()) {
80
+ return ctx.forbidden();
81
+ }
82
+ const query = await permissionChecker2.sanitizeQuery(ctx.query);
83
+ const { results, pagination } = await getService(strapi2, "history").findVersionsPage({
84
+ query: {
85
+ ...query,
86
+ ...getValidPagination({ page: query.page, pageSize: query.pageSize })
87
+ },
88
+ state: { userAbility: ctx.state.userAbility }
89
+ });
90
+ const sanitizedResults = await strapiUtils.async.map(
91
+ results,
92
+ async (version) => {
93
+ return {
94
+ ...version,
95
+ data: await permissionChecker2.sanitizeOutput(version.data),
96
+ createdBy: version.createdBy ? fp.pick(["id", "firstname", "lastname", "username", "email"], version.createdBy) : void 0
97
+ };
98
+ }
99
+ );
100
+ return {
101
+ data: sanitizedResults,
102
+ meta: { pagination }
103
+ };
104
+ },
105
+ async restoreVersion(ctx) {
106
+ const request = ctx.request;
107
+ await validateRestoreVersion(request.body, "contentType is required");
108
+ const permissionChecker2 = getService$1("permission-checker").create({
109
+ userAbility: ctx.state.userAbility,
110
+ model: request.body.contentType
111
+ });
112
+ if (permissionChecker2.cannot.update()) {
113
+ throw new strapiUtils.errors.ForbiddenError();
114
+ }
115
+ const restoredDocument = await getService(strapi2, "history").restoreVersion(
116
+ request.params.versionId
117
+ );
118
+ return {
119
+ data: { documentId: restoredDocument.documentId }
120
+ };
121
+ }
122
+ };
123
+ };
124
+ const controllers$1 = {
125
+ "history-version": createHistoryVersionController
126
+ /**
127
+ * Casting is needed because the types aren't aware that Strapi supports
128
+ * passing a controller factory as the value, instead of a controller object directly
129
+ */
130
+ };
131
+ const HISTORY_VERSION_UID = "plugin::content-manager.history-version";
132
+ const FIELDS_TO_IGNORE = [
133
+ "createdAt",
134
+ "updatedAt",
135
+ "publishedAt",
136
+ "createdBy",
137
+ "updatedBy",
138
+ "strapi_stage",
139
+ "strapi_assignee"
140
+ ];
141
+ const getSchemaAttributesDiff = (versionSchemaAttributes, contentTypeSchemaAttributes) => {
142
+ const sanitizedContentTypeSchemaAttributes = fp.omit(FIELDS_TO_IGNORE, contentTypeSchemaAttributes);
143
+ const reduceDifferenceToAttributesObject = (diffKeys, source) => {
144
+ return diffKeys.reduce((previousAttributesObject, diffKey) => {
145
+ previousAttributesObject[diffKey] = source[diffKey];
146
+ return previousAttributesObject;
147
+ }, {});
148
+ };
149
+ const versionSchemaKeys = Object.keys(versionSchemaAttributes);
150
+ const contentTypeSchemaAttributesKeys = Object.keys(sanitizedContentTypeSchemaAttributes);
151
+ const uniqueToContentType = fp.difference(contentTypeSchemaAttributesKeys, versionSchemaKeys);
152
+ const added = reduceDifferenceToAttributesObject(
153
+ uniqueToContentType,
154
+ sanitizedContentTypeSchemaAttributes
155
+ );
156
+ const uniqueToVersion = fp.difference(versionSchemaKeys, contentTypeSchemaAttributesKeys);
157
+ const removed = reduceDifferenceToAttributesObject(uniqueToVersion, versionSchemaAttributes);
158
+ return { added, removed };
159
+ };
160
+ const DEFAULT_RETENTION_DAYS = 90;
161
+ const createHistoryService = ({ strapi: strapi2 }) => {
162
+ const state = {
163
+ deleteExpiredJob: null,
164
+ isInitialized: false
165
+ };
166
+ const query = strapi2.db.query(HISTORY_VERSION_UID);
167
+ const getRetentionDays = (strapi22) => {
168
+ const featureConfig = strapi22.ee.features.get("cms-content-history");
169
+ const licenseRetentionDays = typeof featureConfig === "object" && featureConfig?.options.retentionDays;
170
+ const userRetentionDays = strapi22.config.get("admin.history.retentionDays");
171
+ if (userRetentionDays && userRetentionDays < licenseRetentionDays) {
172
+ return userRetentionDays;
173
+ }
174
+ return Math.min(licenseRetentionDays, DEFAULT_RETENTION_DAYS);
175
+ };
176
+ const localesService = strapi2.plugin("i18n")?.service("locales");
177
+ const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
178
+ const getLocaleDictionary = async () => {
179
+ if (!localesService)
180
+ return {};
181
+ const locales = await localesService.find() || [];
182
+ return locales.reduce(
183
+ (acc, locale) => {
184
+ acc[locale.code] = { name: locale.name, code: locale.code };
185
+ return acc;
186
+ },
187
+ {}
188
+ );
189
+ };
190
+ const getVersionStatus = async (contentTypeUid, document) => {
191
+ const documentMetadataService = strapi2.plugin("content-manager").service("document-metadata");
192
+ const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
193
+ return documentMetadataService.getStatus(document, meta.availableStatus);
194
+ };
195
+ const getDeepPopulate2 = (uid2) => {
196
+ const model = strapi2.getModel(uid2);
197
+ const attributes = Object.entries(model.attributes);
198
+ return attributes.reduce((acc, [attributeName, attribute]) => {
199
+ switch (attribute.type) {
200
+ case "relation": {
201
+ const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
202
+ if (isVisible2) {
203
+ acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
204
+ }
205
+ break;
206
+ }
207
+ case "media": {
208
+ acc[attributeName] = { fields: ["id"] };
209
+ break;
210
+ }
211
+ case "component": {
212
+ const populate = getDeepPopulate2(attribute.component);
213
+ acc[attributeName] = { populate };
214
+ break;
215
+ }
216
+ case "dynamiczone": {
217
+ const populatedComponents = (attribute.components || []).reduce(
218
+ (acc2, componentUID) => {
219
+ acc2[componentUID] = { populate: getDeepPopulate2(componentUID) };
220
+ return acc2;
221
+ },
222
+ {}
223
+ );
224
+ acc[attributeName] = { on: populatedComponents };
225
+ break;
226
+ }
227
+ }
228
+ return acc;
229
+ }, {});
230
+ };
231
+ return {
232
+ async bootstrap() {
233
+ if (state.isInitialized) {
234
+ return;
235
+ }
236
+ strapi2.documents.use(async (context, next) => {
237
+ if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
238
+ return next();
239
+ }
240
+ if (context.action !== "create" && context.action !== "update" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
241
+ return next();
242
+ }
243
+ const contentTypeUid = context.contentType.uid;
244
+ if (!contentTypeUid.startsWith("api::")) {
245
+ return next();
246
+ }
247
+ const result = await next();
248
+ const documentContext = context.action === "create" ? { documentId: result.documentId, locale: context.params?.locale } : { documentId: context.params.documentId, locale: context.params?.locale };
249
+ const defaultLocale = await getDefaultLocale();
250
+ const locale = documentContext.locale || defaultLocale;
251
+ const document = await strapi2.documents(contentTypeUid).findOne({
252
+ documentId: documentContext.documentId,
253
+ locale,
254
+ populate: getDeepPopulate2(contentTypeUid)
255
+ });
256
+ const status = await getVersionStatus(contentTypeUid, document);
257
+ const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
258
+ const componentsSchemas = Object.keys(
259
+ attributesSchema
260
+ ).reduce((currentComponentSchemas, key) => {
261
+ const fieldSchema = attributesSchema[key];
262
+ if (fieldSchema.type === "component") {
263
+ const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
264
+ return {
265
+ ...currentComponentSchemas,
266
+ [fieldSchema.component]: componentSchema
267
+ };
268
+ }
269
+ return currentComponentSchemas;
270
+ }, {});
271
+ await strapi2.db.transaction(async ({ onCommit }) => {
272
+ onCommit(() => {
273
+ this.createVersion({
274
+ contentType: contentTypeUid,
275
+ data: fp.omit(FIELDS_TO_IGNORE, document),
276
+ schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
277
+ componentsSchemas,
278
+ relatedDocumentId: documentContext.documentId,
279
+ locale,
280
+ status
281
+ });
282
+ });
283
+ });
284
+ return result;
285
+ });
286
+ const retentionDays = getRetentionDays(strapi2);
287
+ state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
288
+ const retentionDaysInMilliseconds = retentionDays * 24 * 60 * 60 * 1e3;
289
+ const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
290
+ query.deleteMany({
291
+ where: {
292
+ created_at: {
293
+ $lt: expirationDate.toISOString()
294
+ }
295
+ }
296
+ });
297
+ });
298
+ state.isInitialized = true;
299
+ },
300
+ async destroy() {
301
+ if (state.deleteExpiredJob) {
302
+ state.deleteExpiredJob.cancel();
303
+ }
304
+ },
305
+ async createVersion(historyVersionData) {
306
+ await query.create({
307
+ data: {
308
+ ...historyVersionData,
309
+ createdAt: /* @__PURE__ */ new Date(),
310
+ createdBy: strapi2.requestContext.get()?.state?.user.id
311
+ }
312
+ });
313
+ },
314
+ async findVersionsPage(params) {
315
+ const locale = params.query.locale || await getDefaultLocale();
316
+ const [{ results, pagination }, localeDictionary] = await Promise.all([
317
+ query.findPage({
318
+ ...params.query,
319
+ where: {
320
+ $and: [
321
+ { contentType: params.query.contentType },
322
+ ...params.query.documentId ? [{ relatedDocumentId: params.query.documentId }] : [],
323
+ ...locale ? [{ locale }] : []
324
+ ]
325
+ },
326
+ populate: ["createdBy"],
327
+ orderBy: [{ createdAt: "desc" }]
328
+ }),
329
+ getLocaleDictionary()
330
+ ]);
331
+ const buildRelationReponse = async (values, attributeSchema) => {
332
+ return values.slice(0, 25).reduce(
333
+ async (currentRelationDataPromise, entry) => {
334
+ const currentRelationData = await currentRelationDataPromise;
335
+ if (!entry) {
336
+ return currentRelationData;
337
+ }
338
+ const relatedEntry = await strapi2.documents(attributeSchema.target).findOne({ documentId: entry.documentId, locale: entry.locale || void 0 });
339
+ const permissionChecker2 = getService$1("permission-checker").create({
340
+ userAbility: params.state.userAbility,
341
+ model: attributeSchema.target
342
+ });
343
+ const sanitizedEntry = await permissionChecker2.sanitizeOutput(relatedEntry);
344
+ if (sanitizedEntry) {
345
+ currentRelationData.results.push({
346
+ ...sanitizedEntry,
347
+ status: await getVersionStatus(attributeSchema.target, sanitizedEntry)
348
+ });
349
+ } else {
350
+ currentRelationData.meta.missingCount += 1;
351
+ }
352
+ return currentRelationData;
353
+ },
354
+ Promise.resolve({
355
+ results: [],
356
+ meta: { missingCount: 0 }
357
+ })
358
+ );
359
+ };
360
+ const buildMediaResponse = async (values) => {
361
+ return values.slice(0, 25).reduce(
362
+ async (currentRelationDataPromise, entry) => {
363
+ const currentRelationData = await currentRelationDataPromise;
364
+ if (!entry) {
365
+ return currentRelationData;
366
+ }
367
+ const permissionChecker2 = getService$1("permission-checker").create({
368
+ userAbility: params.state.userAbility,
369
+ model: "plugin::upload.file"
370
+ });
371
+ const relatedEntry = await strapi2.db.query("plugin::upload.file").findOne({ where: { id: entry.id } });
372
+ const sanitizedEntry = await permissionChecker2.sanitizeOutput(relatedEntry);
373
+ if (sanitizedEntry) {
374
+ currentRelationData.results.push(sanitizedEntry);
375
+ } else {
376
+ currentRelationData.meta.missingCount += 1;
377
+ }
378
+ return currentRelationData;
379
+ },
380
+ Promise.resolve({
381
+ results: [],
382
+ meta: { missingCount: 0 }
383
+ })
384
+ );
385
+ };
386
+ const populateEntryRelations = async (entry) => {
387
+ const entryWithRelations = await Object.entries(entry.schema).reduce(
388
+ async (currentDataWithRelations, [attributeKey, attributeSchema]) => {
389
+ const attributeValue = entry.data[attributeKey];
390
+ const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
391
+ if (attributeSchema.type === "media") {
392
+ return {
393
+ ...await currentDataWithRelations,
394
+ [attributeKey]: await buildMediaResponse(attributeValues)
395
+ };
396
+ }
397
+ if (attributeSchema.type === "relation" && attributeSchema.relation !== "morphToOne" && attributeSchema.relation !== "morphToMany") {
398
+ if (attributeSchema.target === "admin::user") {
399
+ const adminUsers = await Promise.all(
400
+ attributeValues.map(async (userToPopulate) => {
401
+ if (userToPopulate == null) {
402
+ return null;
403
+ }
404
+ return strapi2.query("admin::user").findOne({ where: { id: userToPopulate.id } });
405
+ })
406
+ );
407
+ return {
408
+ ...await currentDataWithRelations,
409
+ /**
410
+ * Ideally we would return the same "{results: [], meta: {}}" shape, however,
411
+ * when sanitizing the data as a whole in the controller before sending to the client,
412
+ * the data for admin relation user is completely sanitized if we return an object here as opposed to an array.
413
+ */
414
+ [attributeKey]: adminUsers
415
+ };
416
+ }
417
+ return {
418
+ ...await currentDataWithRelations,
419
+ [attributeKey]: await buildRelationReponse(attributeValues, attributeSchema)
420
+ };
421
+ }
422
+ return currentDataWithRelations;
423
+ },
424
+ Promise.resolve(entry.data)
425
+ );
426
+ return entryWithRelations;
427
+ };
428
+ const formattedResults = await Promise.all(
429
+ results.map(async (result) => {
430
+ return {
431
+ ...result,
432
+ data: await populateEntryRelations(result),
433
+ meta: {
434
+ unknownAttributes: getSchemaAttributesDiff(
435
+ result.schema,
436
+ strapi2.getModel(params.query.contentType).attributes
437
+ )
438
+ },
439
+ locale: result.locale ? localeDictionary[result.locale] : null
440
+ };
441
+ })
442
+ );
443
+ return {
444
+ results: formattedResults,
445
+ pagination
446
+ };
447
+ },
448
+ async restoreVersion(versionId) {
449
+ const version = await query.findOne({ where: { id: versionId } });
450
+ const contentTypeSchemaAttributes = strapi2.getModel(version.contentType).attributes;
451
+ const schemaDiff = getSchemaAttributesDiff(version.schema, contentTypeSchemaAttributes);
452
+ const dataWithoutAddedAttributes = Object.keys(schemaDiff.added).reduce(
453
+ (currentData, addedKey) => {
454
+ currentData[addedKey] = null;
455
+ return currentData;
456
+ },
457
+ // Clone to avoid mutating the original version data
458
+ structuredClone(version.data)
459
+ );
460
+ const sanitizedSchemaAttributes = fp.omit(
461
+ FIELDS_TO_IGNORE,
462
+ contentTypeSchemaAttributes
463
+ );
464
+ const dataWithoutMissingRelations = await Object.entries(sanitizedSchemaAttributes).reduce(
465
+ async (previousRelationAttributesPromise, [name, attribute]) => {
466
+ const previousRelationAttributes = await previousRelationAttributesPromise;
467
+ const relationData = version.data[name];
468
+ if (relationData === null) {
469
+ return previousRelationAttributes;
470
+ }
471
+ if (attribute.type === "relation" && // TODO: handle polymorphic relations
472
+ attribute.relation !== "morphToOne" && attribute.relation !== "morphToMany") {
473
+ if (Array.isArray(relationData)) {
474
+ if (relationData.length === 0)
475
+ return previousRelationAttributes;
476
+ const existingAndMissingRelations = await Promise.all(
477
+ relationData.map((relation) => {
478
+ return strapi2.documents(attribute.target).findOne({
479
+ documentId: relation.documentId,
480
+ locale: relation.locale || void 0
481
+ });
482
+ })
483
+ );
484
+ const existingRelations = existingAndMissingRelations.filter(
485
+ (relation) => relation !== null
486
+ );
487
+ previousRelationAttributes[name] = existingRelations;
488
+ } else {
489
+ const existingRelation = await strapi2.documents(attribute.target).findOne({
490
+ documentId: relationData.documentId,
491
+ locale: relationData.locale || void 0
492
+ });
493
+ if (!existingRelation) {
494
+ previousRelationAttributes[name] = null;
495
+ }
496
+ }
497
+ }
498
+ if (attribute.type === "media") {
499
+ if (attribute.multiple) {
500
+ const existingAndMissingMedias = await Promise.all(
501
+ // @ts-expect-error Fix the type definitions so this isn't any
502
+ relationData.map((media) => {
503
+ return strapi2.db.query("plugin::upload.file").findOne({ where: { id: media.id } });
504
+ })
505
+ );
506
+ const existingMedias = existingAndMissingMedias.filter((media) => media != null);
507
+ previousRelationAttributes[name] = existingMedias;
508
+ } else {
509
+ const existingMedia = await strapi2.db.query("plugin::upload.file").findOne({ where: { id: version.data[name].id } });
510
+ if (!existingMedia) {
511
+ previousRelationAttributes[name] = null;
512
+ }
513
+ }
514
+ }
515
+ return previousRelationAttributes;
516
+ },
517
+ // Clone to avoid mutating the original version data
518
+ Promise.resolve(structuredClone(dataWithoutAddedAttributes))
519
+ );
520
+ const data = fp.omit(["id", ...Object.keys(schemaDiff.removed)], dataWithoutMissingRelations);
521
+ const restoredDocument = await strapi2.documents(version.contentType).update({
522
+ documentId: version.relatedDocumentId,
523
+ locale: version.locale,
524
+ data
525
+ });
526
+ if (!restoredDocument) {
527
+ throw new strapiUtils.errors.ApplicationError("Failed to restore version");
528
+ }
529
+ return restoredDocument;
530
+ }
531
+ };
532
+ };
533
+ const services$1 = {
534
+ history: createHistoryService
535
+ };
536
+ const info = { pluginName: "content-manager", type: "admin" };
537
+ const historyVersionRouter = {
538
+ type: "admin",
539
+ routes: [
540
+ {
541
+ method: "GET",
542
+ info,
543
+ path: "/history-versions",
544
+ handler: "history-version.findMany",
545
+ config: {
546
+ policies: ["admin::isAuthenticatedAdmin"]
547
+ }
548
+ },
549
+ {
550
+ method: "PUT",
551
+ info,
552
+ path: "/history-versions/:versionId/restore",
553
+ handler: "history-version.restoreVersion",
554
+ config: {
555
+ policies: ["admin::isAuthenticatedAdmin"]
556
+ }
557
+ }
558
+ ]
559
+ };
560
+ const routes$1 = {
561
+ "history-version": historyVersionRouter
562
+ };
563
+ const historyVersion = {
564
+ uid: HISTORY_VERSION_UID,
565
+ tableName: "strapi_history_versions",
566
+ singularName: "history-version",
567
+ attributes: {
568
+ id: {
569
+ type: "increments"
570
+ },
571
+ contentType: {
572
+ type: "string",
573
+ column: { notNullable: true }
574
+ },
575
+ relatedDocumentId: {
576
+ type: "string",
577
+ // TODO: notNullable should be true once history can record publish actions
578
+ column: { notNullable: false }
579
+ },
580
+ locale: {
581
+ type: "string"
582
+ },
583
+ status: {
584
+ type: "enumeration",
585
+ enum: ["draft", "published", "modified"]
586
+ },
587
+ data: {
588
+ type: "json"
589
+ },
590
+ schema: {
591
+ type: "json"
592
+ },
593
+ createdAt: {
594
+ type: "datetime",
595
+ default: () => /* @__PURE__ */ new Date()
596
+ },
597
+ // FIXME: joinTable should be optional
598
+ // @ts-expect-error database model is not yet updated to support useJoinTable
599
+ createdBy: {
600
+ type: "relation",
601
+ relation: "oneToOne",
602
+ target: "admin::user",
603
+ useJoinTable: false
604
+ }
605
+ }
606
+ };
607
+ const getFeature = () => {
608
+ if (strapi.ee.features.isEnabled("cms-content-history")) {
609
+ return {
610
+ register({ strapi: strapi2 }) {
611
+ strapi2.get("models").add(historyVersion);
612
+ },
613
+ bootstrap({ strapi: strapi2 }) {
614
+ getService(strapi2, "history").bootstrap();
615
+ },
616
+ destroy({ strapi: strapi2 }) {
617
+ getService(strapi2, "history").destroy();
618
+ },
619
+ controllers: controllers$1,
620
+ services: services$1,
621
+ routes: routes$1
622
+ };
623
+ }
624
+ return {
625
+ register({ strapi: strapi2 }) {
626
+ strapi2.get("models").add(historyVersion);
627
+ }
628
+ };
629
+ };
630
+ const history = getFeature();
631
+ const register = async ({ strapi: strapi2 }) => {
632
+ await history.register?.({ strapi: strapi2 });
633
+ };
634
+ const ALLOWED_WEBHOOK_EVENTS = {
635
+ ENTRY_PUBLISH: "entry.publish",
636
+ ENTRY_UNPUBLISH: "entry.unpublish"
637
+ };
638
+ const bootstrap = async () => {
639
+ Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
640
+ strapi.get("webhookStore").addAllowedEvent(key, value);
641
+ });
642
+ getService$1("field-sizes").setCustomFieldInputSizes();
643
+ await getService$1("components").syncConfigurations();
644
+ await getService$1("content-types").syncConfigurations();
645
+ await getService$1("permission").registerPermissions();
646
+ await history.bootstrap?.({ strapi });
647
+ };
648
+ const destroy = async ({ strapi: strapi2 }) => {
649
+ await history.destroy?.({ strapi: strapi2 });
650
+ };
651
+ const routing = async (ctx, next) => {
652
+ const { model } = ctx.params;
653
+ const ct = strapi.contentTypes[model];
654
+ if (!ct) {
655
+ return ctx.send({ error: "contentType.notFound" }, 404);
656
+ }
657
+ let controllers2;
658
+ if (!ct.plugin || ct.plugin === "admin") {
659
+ controllers2 = strapi.admin.controllers;
660
+ } else {
661
+ controllers2 = strapi.plugin(ct.plugin).controllers;
662
+ }
663
+ const { route } = ctx.state;
664
+ if (typeof route.handler !== "string") {
665
+ return next();
666
+ }
667
+ const [, action] = route.handler.split(".");
668
+ let actionConfig;
669
+ if (!ct.plugin || ct.plugin === "admin") {
670
+ actionConfig = strapi.config.get(`admin.layout.${ct.modelName}.actions.${action}`);
671
+ } else {
672
+ actionConfig = strapi.plugin(ct.plugin).config(`layout.${ct.modelName}.actions.${action}`);
673
+ }
674
+ if (!isNil__default.default(actionConfig)) {
675
+ const [controller, action2] = actionConfig.split(".");
676
+ if (controller && action2) {
677
+ return controllers2[controller.toLowerCase()][action2](ctx, next);
678
+ }
679
+ }
680
+ await next();
681
+ };
682
+ const admin = {
683
+ type: "admin",
684
+ routes: [
685
+ {
686
+ method: "GET",
687
+ path: "/init",
688
+ handler: "init.getInitData",
689
+ config: {
690
+ policies: []
691
+ }
692
+ },
693
+ {
694
+ method: "GET",
695
+ path: "/content-types",
696
+ handler: "content-types.findContentTypes",
697
+ config: {
698
+ policies: []
699
+ }
700
+ },
701
+ {
702
+ method: "GET",
703
+ path: "/content-types-settings",
704
+ handler: "content-types.findContentTypesSettings",
705
+ config: {
706
+ policies: []
707
+ }
708
+ },
709
+ {
710
+ method: "GET",
711
+ path: "/content-types/:uid/configuration",
712
+ handler: "content-types.findContentTypeConfiguration",
713
+ config: {
714
+ policies: []
715
+ }
716
+ },
717
+ {
718
+ method: "PUT",
719
+ path: "/content-types/:uid/configuration",
720
+ handler: "content-types.updateContentTypeConfiguration",
721
+ config: {
722
+ policies: ["admin::isAuthenticatedAdmin"]
723
+ }
724
+ },
725
+ {
726
+ method: "GET",
727
+ path: "/components",
728
+ handler: "components.findComponents",
729
+ config: {
730
+ policies: []
731
+ }
732
+ },
733
+ {
734
+ method: "GET",
735
+ path: "/components/:uid/configuration",
736
+ handler: "components.findComponentConfiguration",
737
+ config: {
738
+ policies: []
739
+ }
740
+ },
741
+ {
742
+ method: "PUT",
743
+ path: "/components/:uid/configuration",
744
+ handler: "components.updateComponentConfiguration",
745
+ config: {
746
+ policies: []
747
+ }
748
+ },
749
+ {
750
+ method: "POST",
751
+ path: "/uid/generate",
752
+ handler: "uid.generateUID",
753
+ config: {
754
+ policies: []
755
+ }
756
+ },
757
+ {
758
+ method: "POST",
759
+ path: "/uid/check-availability",
760
+ handler: "uid.checkUIDAvailability",
761
+ config: {
762
+ policies: []
763
+ }
764
+ },
765
+ {
766
+ method: "GET",
767
+ path: "/relations/:model/:targetField",
768
+ handler: "relations.findAvailable",
769
+ config: {
770
+ policies: ["admin::isAuthenticatedAdmin"]
771
+ }
772
+ },
773
+ {
774
+ method: "GET",
775
+ path: "/relations/:model/:id/:targetField",
776
+ handler: "relations.findExisting",
777
+ config: {
778
+ policies: ["admin::isAuthenticatedAdmin"]
779
+ }
780
+ },
781
+ {
782
+ method: "GET",
783
+ path: "/single-types/:model",
784
+ handler: "single-types.find",
785
+ config: {
786
+ middlewares: [routing],
787
+ policies: [
788
+ "admin::isAuthenticatedAdmin",
789
+ {
790
+ name: "plugin::content-manager.hasPermissions",
791
+ config: { actions: ["plugin::content-manager.explorer.read"] }
792
+ }
793
+ ]
794
+ }
795
+ },
796
+ {
797
+ method: "PUT",
798
+ path: "/single-types/:model",
799
+ handler: "single-types.createOrUpdate",
800
+ config: {
801
+ middlewares: [routing],
802
+ policies: [
803
+ "admin::isAuthenticatedAdmin",
804
+ {
805
+ name: "plugin::content-manager.hasPermissions",
806
+ config: {
807
+ actions: [
808
+ "plugin::content-manager.explorer.create",
809
+ "plugin::content-manager.explorer.update"
810
+ ],
811
+ hasAtLeastOne: true
812
+ }
813
+ }
814
+ ]
815
+ }
816
+ },
817
+ {
818
+ method: "DELETE",
819
+ path: "/single-types/:model",
820
+ handler: "single-types.delete",
821
+ config: {
822
+ middlewares: [routing],
823
+ policies: [
824
+ "admin::isAuthenticatedAdmin",
825
+ {
826
+ name: "plugin::content-manager.hasPermissions",
827
+ config: { actions: ["plugin::content-manager.explorer.delete"] }
828
+ }
829
+ ]
830
+ }
831
+ },
832
+ {
833
+ method: "POST",
834
+ path: "/single-types/:model/actions/publish",
835
+ handler: "single-types.publish",
836
+ config: {
837
+ middlewares: [routing],
838
+ policies: [
839
+ "admin::isAuthenticatedAdmin",
840
+ {
841
+ name: "plugin::content-manager.hasPermissions",
842
+ config: { actions: ["plugin::content-manager.explorer.publish"] }
843
+ }
844
+ ]
845
+ }
846
+ },
847
+ {
848
+ method: "POST",
849
+ path: "/single-types/:model/actions/unpublish",
850
+ handler: "single-types.unpublish",
851
+ config: {
852
+ middlewares: [routing],
853
+ policies: [
854
+ "admin::isAuthenticatedAdmin",
855
+ {
856
+ name: "plugin::content-manager.hasPermissions",
857
+ config: { actions: ["plugin::content-manager.explorer.publish"] }
858
+ }
859
+ ]
860
+ }
861
+ },
862
+ {
863
+ method: "POST",
864
+ path: "/single-types/:model/actions/discard",
865
+ handler: "single-types.discard",
866
+ config: {
867
+ middlewares: [routing],
868
+ policies: [
869
+ "admin::isAuthenticatedAdmin",
870
+ {
871
+ name: "plugin::content-manager.hasPermissions",
872
+ config: { actions: ["plugin::content-manager.explorer.update"] }
873
+ }
874
+ ]
875
+ }
876
+ },
877
+ {
878
+ method: "GET",
879
+ path: "/single-types/:model/actions/countDraftRelations",
880
+ handler: "single-types.countDraftRelations",
881
+ config: {
882
+ middlewares: [routing],
883
+ policies: [
884
+ "admin::isAuthenticatedAdmin",
885
+ {
886
+ name: "plugin::content-manager.hasPermissions",
887
+ config: { actions: ["plugin::content-manager.explorer.read"] }
888
+ }
889
+ ]
890
+ }
891
+ },
892
+ {
893
+ method: "GET",
894
+ path: "/collection-types/:model",
895
+ handler: "collection-types.find",
896
+ config: {
897
+ middlewares: [routing],
898
+ policies: [
899
+ "admin::isAuthenticatedAdmin",
900
+ {
901
+ name: "plugin::content-manager.hasPermissions",
902
+ config: { actions: ["plugin::content-manager.explorer.read"] }
903
+ }
904
+ ]
905
+ }
906
+ },
907
+ {
908
+ method: "POST",
909
+ path: "/collection-types/:model",
910
+ handler: "collection-types.create",
911
+ config: {
912
+ middlewares: [routing],
913
+ policies: [
914
+ "admin::isAuthenticatedAdmin",
915
+ {
916
+ name: "plugin::content-manager.hasPermissions",
917
+ config: { actions: ["plugin::content-manager.explorer.create"] }
918
+ }
919
+ ]
920
+ }
921
+ },
922
+ {
923
+ method: "POST",
924
+ path: "/collection-types/:model/clone/:sourceId",
925
+ handler: "collection-types.clone",
926
+ config: {
927
+ middlewares: [routing],
928
+ policies: [
929
+ "admin::isAuthenticatedAdmin",
930
+ {
931
+ name: "plugin::content-manager.hasPermissions",
932
+ config: { actions: ["plugin::content-manager.explorer.create"] }
933
+ }
934
+ ]
935
+ }
936
+ },
937
+ {
938
+ method: "POST",
939
+ path: "/collection-types/:model/auto-clone/:sourceId",
940
+ handler: "collection-types.autoClone",
941
+ config: {
942
+ middlewares: [routing],
943
+ policies: [
944
+ "admin::isAuthenticatedAdmin",
945
+ {
946
+ name: "plugin::content-manager.hasPermissions",
947
+ config: { actions: ["plugin::content-manager.explorer.create"] }
948
+ }
949
+ ]
950
+ }
951
+ },
952
+ {
953
+ method: "GET",
954
+ path: "/collection-types/:model/:id",
955
+ handler: "collection-types.findOne",
956
+ config: {
957
+ middlewares: [routing],
958
+ policies: [
959
+ "admin::isAuthenticatedAdmin",
960
+ {
961
+ name: "plugin::content-manager.hasPermissions",
962
+ config: { actions: ["plugin::content-manager.explorer.read"] }
963
+ }
964
+ ]
965
+ }
966
+ },
967
+ {
968
+ method: "PUT",
969
+ path: "/collection-types/:model/:id",
970
+ handler: "collection-types.update",
971
+ config: {
972
+ middlewares: [routing],
973
+ policies: [
974
+ "admin::isAuthenticatedAdmin",
975
+ {
976
+ name: "plugin::content-manager.hasPermissions",
977
+ config: { actions: ["plugin::content-manager.explorer.update"] }
978
+ }
979
+ ]
980
+ }
981
+ },
982
+ {
983
+ method: "DELETE",
984
+ path: "/collection-types/:model/:id",
985
+ handler: "collection-types.delete",
986
+ config: {
987
+ middlewares: [routing],
988
+ policies: [
989
+ "admin::isAuthenticatedAdmin",
990
+ {
991
+ name: "plugin::content-manager.hasPermissions",
992
+ config: { actions: ["plugin::content-manager.explorer.delete"] }
993
+ }
994
+ ]
995
+ }
996
+ },
997
+ {
998
+ method: "POST",
999
+ path: "/collection-types/:model/actions/publish",
1000
+ handler: "collection-types.publish",
1001
+ config: {
1002
+ middlewares: [routing],
1003
+ policies: [
1004
+ "admin::isAuthenticatedAdmin",
1005
+ {
1006
+ name: "plugin::content-manager.hasPermissions",
1007
+ config: { actions: ["plugin::content-manager.explorer.publish"] }
1008
+ }
1009
+ ]
1010
+ }
1011
+ },
1012
+ {
1013
+ method: "POST",
1014
+ path: "/collection-types/:model/:id/actions/publish",
1015
+ handler: "collection-types.publish",
1016
+ config: {
1017
+ middlewares: [routing],
1018
+ policies: [
1019
+ "admin::isAuthenticatedAdmin",
1020
+ {
1021
+ name: "plugin::content-manager.hasPermissions",
1022
+ config: { actions: ["plugin::content-manager.explorer.publish"] }
1023
+ }
1024
+ ]
1025
+ }
1026
+ },
1027
+ {
1028
+ method: "POST",
1029
+ path: "/collection-types/:model/:id/actions/unpublish",
1030
+ handler: "collection-types.unpublish",
1031
+ config: {
1032
+ middlewares: [routing],
1033
+ policies: [
1034
+ "admin::isAuthenticatedAdmin",
1035
+ {
1036
+ name: "plugin::content-manager.hasPermissions",
1037
+ config: { actions: ["plugin::content-manager.explorer.publish"] }
1038
+ }
1039
+ ]
1040
+ }
1041
+ },
1042
+ {
1043
+ method: "POST",
1044
+ path: "/collection-types/:model/:id/actions/discard",
1045
+ handler: "collection-types.discard",
1046
+ config: {
1047
+ middlewares: [routing],
1048
+ policies: [
1049
+ "admin::isAuthenticatedAdmin",
1050
+ {
1051
+ name: "plugin::content-manager.hasPermissions",
1052
+ config: { actions: ["plugin::content-manager.explorer.update"] }
1053
+ }
1054
+ ]
1055
+ }
1056
+ },
1057
+ {
1058
+ method: "POST",
1059
+ path: "/collection-types/:model/actions/bulkDelete",
1060
+ handler: "collection-types.bulkDelete",
1061
+ config: {
1062
+ middlewares: [routing],
1063
+ policies: [
1064
+ "admin::isAuthenticatedAdmin",
1065
+ {
1066
+ name: "plugin::content-manager.hasPermissions",
1067
+ config: { actions: ["plugin::content-manager.explorer.delete"] }
1068
+ }
1069
+ ]
1070
+ }
1071
+ },
1072
+ {
1073
+ method: "POST",
1074
+ path: "/collection-types/:model/actions/bulkPublish",
1075
+ handler: "collection-types.bulkPublish",
1076
+ config: {
1077
+ middlewares: [routing],
1078
+ policies: [
1079
+ "admin::isAuthenticatedAdmin",
1080
+ {
1081
+ name: "plugin::content-manager.hasPermissions",
1082
+ config: { actions: ["plugin::content-manager.explorer.publish"] }
1083
+ }
1084
+ ]
1085
+ }
1086
+ },
1087
+ {
1088
+ method: "POST",
1089
+ path: "/collection-types/:model/actions/bulkUnpublish",
1090
+ handler: "collection-types.bulkUnpublish",
1091
+ config: {
1092
+ middlewares: [routing],
1093
+ policies: [
1094
+ "admin::isAuthenticatedAdmin",
1095
+ {
1096
+ name: "plugin::content-manager.hasPermissions",
1097
+ config: { actions: ["plugin::content-manager.explorer.publish"] }
1098
+ }
1099
+ ]
1100
+ }
1101
+ },
1102
+ {
1103
+ method: "GET",
1104
+ path: "/collection-types/:model/:id/actions/countDraftRelations",
1105
+ handler: "collection-types.countDraftRelations",
1106
+ config: {
1107
+ middlewares: [routing],
1108
+ policies: [
1109
+ "admin::isAuthenticatedAdmin",
1110
+ {
1111
+ name: "plugin::content-manager.hasPermissions",
1112
+ config: { actions: ["plugin::content-manager.explorer.read"] }
1113
+ }
1114
+ ]
1115
+ }
1116
+ },
1117
+ {
1118
+ method: "GET",
1119
+ path: "/collection-types/:model/actions/countManyEntriesDraftRelations",
1120
+ handler: "collection-types.countManyEntriesDraftRelations",
1121
+ config: {
1122
+ middlewares: [routing],
1123
+ policies: [
1124
+ "admin::isAuthenticatedAdmin",
1125
+ {
1126
+ name: "plugin::content-manager.hasPermissions",
1127
+ config: { actions: ["plugin::content-manager.explorer.read"] }
1128
+ }
1129
+ ]
1130
+ }
1131
+ }
1132
+ ]
1133
+ };
1134
+ const routes = {
1135
+ admin,
1136
+ ...history.routes ? history.routes : {}
1137
+ };
1138
+ const hasPermissionsSchema = strapiUtils.yup.object({
1139
+ actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
1140
+ hasAtLeastOne: strapiUtils.yup.boolean()
1141
+ });
1142
+ const validateHasPermissionsInput = strapiUtils.validateYupSchemaSync(hasPermissionsSchema);
1143
+ const { createPolicy } = strapiUtils.policy;
1144
+ const hasPermissions = createPolicy({
1145
+ name: "plugin::content-manager.hasPermissions",
1146
+ validator: validateHasPermissionsInput,
1147
+ handler(ctx, config = {}) {
1148
+ const { actions = [], hasAtLeastOne = false } = config;
1149
+ const { userAbility } = ctx.state;
1150
+ const { model } = ctx.params;
1151
+ const isAuthorized = hasAtLeastOne ? actions.some((action) => userAbility.can(action, model)) : actions.every((action) => userAbility.can(action, model));
1152
+ return isAuthorized;
1153
+ }
1154
+ });
1155
+ const policies = {
1156
+ hasPermissions
1157
+ };
1158
+ const { getNonVisibleAttributes, getWritableAttributes } = strapiUtils.contentTypes;
1159
+ const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$3, CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = strapiUtils.contentTypes.constants;
1160
+ const NON_SORTABLES = ["component", "json", "media", "richtext", "dynamiczone", "blocks"];
1161
+ const SORTABLE_RELATIONS = ["oneToOne", "manyToOne"];
1162
+ const NON_LISTABLES = ["json", "password", "richtext", "dynamiczone", "blocks"];
1163
+ const LISTABLE_RELATIONS = ["oneToOne", "oneToMany", "manyToOne", "manyToMany"];
1164
+ const isHidden = (schema, name) => {
1165
+ if (!___default.default.has(schema.attributes, name)) {
1166
+ return false;
1167
+ }
1168
+ const isHidden2 = ___default.default.get(schema, ["config", "attributes", name, "hidden"], false);
1169
+ if (isHidden2 === true) {
1170
+ return true;
1171
+ }
1172
+ return false;
1173
+ };
1174
+ const isListable = (schema, name) => {
1175
+ if (!___default.default.has(schema.attributes, name)) {
1176
+ return false;
1177
+ }
1178
+ if (isHidden(schema, name)) {
1179
+ return false;
1180
+ }
1181
+ const attribute = schema.attributes[name];
1182
+ if (NON_LISTABLES.includes(attribute.type)) {
1183
+ return false;
1184
+ }
1185
+ if (isRelation$1(attribute) && !LISTABLE_RELATIONS.includes(attribute.relationType)) {
1186
+ return false;
1187
+ }
1188
+ return true;
1189
+ };
1190
+ const isSortable = (schema, name) => {
1191
+ if (!___default.default.has(schema.attributes, name)) {
1192
+ return false;
1193
+ }
1194
+ if (schema.modelType === "component" && name === "id")
1195
+ return false;
1196
+ const attribute = schema.attributes[name];
1197
+ if (NON_SORTABLES.includes(attribute.type)) {
1198
+ return false;
1199
+ }
1200
+ if (isRelation$1(attribute) && !SORTABLE_RELATIONS.includes(attribute.relationType)) {
1201
+ return false;
1202
+ }
1203
+ return true;
1204
+ };
1205
+ const isSearchable = (schema, name) => {
1206
+ return isSortable(schema, name);
1207
+ };
1208
+ const isVisible$1 = (schema, name) => {
1209
+ if (!___default.default.has(schema.attributes, name)) {
1210
+ return false;
1211
+ }
1212
+ if (isHidden(schema, name)) {
1213
+ return false;
1214
+ }
1215
+ if (isTimestamp(schema, name) || name === "id") {
1216
+ return false;
1217
+ }
1218
+ if (isPublicationField(name)) {
1219
+ return false;
1220
+ }
1221
+ if (isCreatorField(schema, name)) {
1222
+ return false;
1223
+ }
1224
+ return true;
1225
+ };
1226
+ const isPublicationField = (name) => PUBLISHED_AT_ATTRIBUTE$3 === name;
1227
+ const isTimestamp = (schema, name) => {
1228
+ if (!___default.default.has(schema.attributes, name)) {
1229
+ return false;
1230
+ }
1231
+ const timestamps = strapiUtils.contentTypes.getTimestamps(schema);
1232
+ if (!timestamps || !Array.isArray(timestamps)) {
1233
+ return false;
1234
+ }
1235
+ if (timestamps.includes(name)) {
1236
+ return true;
1237
+ }
1238
+ };
1239
+ const isCreatorField = (schema, name) => {
1240
+ if (!___default.default.has(schema.attributes, name)) {
1241
+ return false;
1242
+ }
1243
+ const creatorFields = strapiUtils.contentTypes.getCreatorFields(schema);
1244
+ if (!creatorFields || !Array.isArray(creatorFields)) {
1245
+ return false;
1246
+ }
1247
+ if (creatorFields.includes(name)) {
1248
+ return true;
1249
+ }
1250
+ };
1251
+ const isRelation$1 = (attribute) => attribute.type === "relation";
1252
+ const hasRelationAttribute = (schema, name) => {
1253
+ if (!___default.default.has(schema.attributes, name)) {
1254
+ return false;
1255
+ }
1256
+ if (isHidden(schema, name)) {
1257
+ return false;
1258
+ }
1259
+ if (!isVisible$1(schema, name)) {
1260
+ return false;
1261
+ }
1262
+ return isRelation$1(schema.attributes[name]);
1263
+ };
1264
+ const hasEditableAttribute = (schema, name) => {
1265
+ if (!___default.default.has(schema.attributes, name)) {
1266
+ return false;
1267
+ }
1268
+ if (isHidden(schema, name)) {
1269
+ return false;
1270
+ }
1271
+ if (!isVisible$1(schema, name)) {
1272
+ return false;
1273
+ }
1274
+ return true;
1275
+ };
1276
+ const findFirstStringAttribute = (schema) => {
1277
+ return Object.keys(schema.attributes || {}).find((key) => {
1278
+ const { type } = schema.attributes[key];
1279
+ return type === "string" && key !== "id";
1280
+ });
1281
+ };
1282
+ const getDefaultMainField = (schema) => findFirstStringAttribute(schema) || "id";
1283
+ const getSortableAttributes = (schema) => {
1284
+ const validAttributes = Object.keys(schema.attributes).filter((key) => isListable(schema, key));
1285
+ const model = strapi.getModel(schema.uid);
1286
+ const nonVisibleWritableAttributes = fp.intersection(
1287
+ getNonVisibleAttributes(model),
1288
+ getWritableAttributes(model)
1289
+ );
1290
+ return [
1291
+ "id",
1292
+ ...validAttributes,
1293
+ ...nonVisibleWritableAttributes,
1294
+ CREATED_BY_ATTRIBUTE,
1295
+ UPDATED_BY_ATTRIBUTE
1296
+ ];
1297
+ };
1298
+ const DEFAULT_SETTINGS = {
1299
+ bulkable: true,
1300
+ filterable: true,
1301
+ searchable: true,
1302
+ pageSize: 10
1303
+ };
1304
+ const settingsFields = [
1305
+ "searchable",
1306
+ "filterable",
1307
+ "bulkable",
1308
+ "pageSize",
1309
+ "mainField",
1310
+ "defaultSortBy",
1311
+ "defaultSortOrder"
1312
+ ];
1313
+ const getModelSettings = fp.pipe([fp.propOr({}, "config.settings"), fp.pick(settingsFields)]);
1314
+ async function isValidDefaultSort(schema, value) {
1315
+ const parsedValue = qs__default.default.parse(value);
1316
+ const omitNonSortableAttributes = ({ schema: schema2, key }, { remove }) => {
1317
+ const sortableAttributes = getSortableAttributes(schema2);
1318
+ if (!sortableAttributes.includes(key)) {
1319
+ remove(key);
1320
+ }
1321
+ };
1322
+ const sanitizedValue = await strapiUtils.traverse.traverseQuerySort(
1323
+ omitNonSortableAttributes,
1324
+ { schema, getModel: strapi.getModel.bind(strapi) },
1325
+ parsedValue
1326
+ );
1327
+ return fp.isEqual(parsedValue, sanitizedValue);
1328
+ }
1329
+ const createDefaultSettings = async (schema) => {
1330
+ const defaultField = getDefaultMainField(schema);
1331
+ return {
1332
+ ...DEFAULT_SETTINGS,
1333
+ mainField: defaultField,
1334
+ defaultSortBy: defaultField,
1335
+ defaultSortOrder: "ASC",
1336
+ ...getModelSettings(schema)
1337
+ };
1338
+ };
1339
+ const syncSettings = async (configuration, schema) => {
1340
+ if (fp.isEmpty(configuration.settings))
1341
+ return createDefaultSettings(schema);
1342
+ const defaultField = getDefaultMainField(schema);
1343
+ const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
1344
+ return {
1345
+ ...configuration.settings,
1346
+ mainField: isSortable(schema, mainField) ? mainField : defaultField,
1347
+ defaultSortBy: await isValidDefaultSort(schema, defaultSortBy) ? defaultSortBy : defaultField
1348
+ };
1349
+ };
1350
+ const createModelConfigurationSchema = (schema, opts = {}) => strapiUtils.yup.object().shape({
1351
+ settings: createSettingsSchema(schema).default(null).nullable(),
1352
+ metadatas: createMetadasSchema(schema).default(null).nullable(),
1353
+ layouts: createLayoutsSchema(schema, opts).default(null).nullable(),
1354
+ options: strapiUtils.yup.object().optional()
1355
+ }).noUnknown();
1356
+ const createSettingsSchema = (schema) => {
1357
+ const validAttributes = Object.keys(schema.attributes).filter((key) => isListable(schema, key));
1358
+ return strapiUtils.yup.object().shape({
1359
+ bulkable: strapiUtils.yup.boolean().required(),
1360
+ filterable: strapiUtils.yup.boolean().required(),
1361
+ pageSize: strapiUtils.yup.number().integer().min(10).max(100).required(),
1362
+ searchable: strapiUtils.yup.boolean().required(),
1363
+ // should be reset when the type changes
1364
+ mainField: strapiUtils.yup.string().oneOf(validAttributes.concat("id")).default("id"),
1365
+ // should be reset when the type changes
1366
+ defaultSortBy: strapiUtils.yup.string().test(
1367
+ "is-valid-sort-attribute",
1368
+ "${path} is not a valid sort attribute",
1369
+ async (value) => isValidDefaultSort(schema, value)
1370
+ ).default("id"),
1371
+ defaultSortOrder: strapiUtils.yup.string().oneOf(["ASC", "DESC"]).default("ASC")
1372
+ }).noUnknown();
1373
+ };
1374
+ const createMetadasSchema = (schema) => {
1375
+ return strapiUtils.yup.object().shape(
1376
+ Object.keys(schema.attributes).reduce((acc, key) => {
1377
+ acc[key] = strapiUtils.yup.object().shape({
1378
+ edit: strapiUtils.yup.object().shape({
1379
+ label: strapiUtils.yup.string(),
1380
+ description: strapiUtils.yup.string(),
1381
+ placeholder: strapiUtils.yup.string(),
1382
+ editable: strapiUtils.yup.boolean(),
1383
+ visible: strapiUtils.yup.boolean(),
1384
+ mainField: strapiUtils.yup.lazy((value) => {
1385
+ if (!value) {
1386
+ return strapiUtils.yup.string();
1387
+ }
1388
+ const targetSchema = getService$1("content-types").findContentType(
1389
+ schema.attributes[key].targetModel
1390
+ );
1391
+ if (!targetSchema) {
1392
+ return strapiUtils.yup.string();
1393
+ }
1394
+ const validAttributes = Object.keys(targetSchema.attributes).filter(
1395
+ (key2) => isListable(targetSchema, key2)
1396
+ );
1397
+ return strapiUtils.yup.string().oneOf(validAttributes.concat("id")).default("id");
1398
+ })
1399
+ }).noUnknown().required(),
1400
+ list: strapiUtils.yup.object().shape({
1401
+ label: strapiUtils.yup.string(),
1402
+ searchable: strapiUtils.yup.boolean(),
1403
+ sortable: strapiUtils.yup.boolean()
1404
+ }).noUnknown().required()
1405
+ }).noUnknown();
1406
+ return acc;
1407
+ }, {})
1408
+ );
1409
+ };
1410
+ const createArrayTest = ({ allowUndefined = false } = {}) => ({
1411
+ name: "isArray",
1412
+ message: "${path} is required and must be an array",
1413
+ test: (val) => allowUndefined === true && val === void 0 ? true : Array.isArray(val)
1414
+ });
1415
+ const createLayoutsSchema = (schema, opts = {}) => {
1416
+ const validAttributes = Object.keys(schema.attributes).filter((key) => isListable(schema, key));
1417
+ const editAttributes = Object.keys(schema.attributes).filter(
1418
+ (key) => hasEditableAttribute(schema, key)
1419
+ );
1420
+ return strapiUtils.yup.object().shape({
1421
+ edit: strapiUtils.yup.array().of(
1422
+ strapiUtils.yup.array().of(
1423
+ strapiUtils.yup.object().shape({
1424
+ name: strapiUtils.yup.string().oneOf(editAttributes).required(),
1425
+ size: strapiUtils.yup.number().integer().positive().required()
1426
+ }).noUnknown()
1427
+ )
1428
+ ).test(createArrayTest(opts)),
1429
+ list: strapiUtils.yup.array().of(strapiUtils.yup.string().oneOf(validAttributes)).test(createArrayTest(opts))
1430
+ });
1431
+ };
1432
+ const { PaginationError, ValidationError } = strapiUtils.errors;
1433
+ const TYPES = ["singleType", "collectionType"];
1434
+ const kindSchema = strapiUtils.yup.string().oneOf(TYPES).nullable();
1435
+ const bulkActionInputSchema = strapiUtils.yup.object({
1436
+ ids: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()).min(1).required()
1437
+ }).required();
1438
+ const generateUIDInputSchema = strapiUtils.yup.object({
1439
+ contentTypeUID: strapiUtils.yup.string().required(),
1440
+ field: strapiUtils.yup.string().required(),
1441
+ data: strapiUtils.yup.object().required()
1442
+ });
1443
+ const checkUIDAvailabilityInputSchema = strapiUtils.yup.object({
1444
+ contentTypeUID: strapiUtils.yup.string().required(),
1445
+ field: strapiUtils.yup.string().required(),
1446
+ value: strapiUtils.yup.string().matches(/^[A-Za-z0-9-_.~]*$/).required()
1447
+ });
1448
+ const validateUIDField = (contentTypeUID, field) => {
1449
+ const model = strapi.contentTypes[contentTypeUID];
1450
+ if (!model) {
1451
+ throw new ValidationError("ContentType not found");
1452
+ }
1453
+ if (!___default.default.has(model, ["attributes", field]) || ___default.default.get(model, ["attributes", field, "type"]) !== "uid") {
1454
+ throw new ValidationError(`${field} must be a valid \`uid\` attribute`);
1455
+ }
1456
+ };
1457
+ const validateKind = strapiUtils.validateYupSchema(kindSchema);
1458
+ const validateBulkActionInput = strapiUtils.validateYupSchema(bulkActionInputSchema);
1459
+ const validateGenerateUIDInput = strapiUtils.validateYupSchema(generateUIDInputSchema);
1460
+ const validateCheckUIDAvailabilityInput = strapiUtils.validateYupSchema(checkUIDAvailabilityInputSchema);
1461
+ const { isVisibleAttribute: isVisibleAttribute$2 } = strapiUtils__default.default.contentTypes;
1462
+ function checkRelation(model, attributeName, path) {
1463
+ if (!isVisibleAttribute$2(model, attributeName)) {
1464
+ return [];
1465
+ }
1466
+ const { relation, inversedBy, mappedBy } = model.attributes[attributeName];
1467
+ if (["oneToOne", "oneToMany"].includes(relation) && [mappedBy, inversedBy].some((key) => key != null)) {
1468
+ return [[[...path, attributeName], "relation"]];
1469
+ }
1470
+ return [];
1471
+ }
1472
+ const getProhibitedCloningFields = (uid2, pathPrefix = []) => {
1473
+ const model = strapi.getModel(uid2);
1474
+ const prohibitedFields = Object.keys(model.attributes).reduce(
1475
+ (acc, attributeName) => {
1476
+ const attribute = model.attributes[attributeName];
1477
+ const attributePath = [...pathPrefix, attributeName];
1478
+ switch (attribute.type) {
1479
+ case "relation":
1480
+ return [...acc, ...checkRelation(model, attributeName, pathPrefix)];
1481
+ case "component":
1482
+ return [...acc, ...getProhibitedCloningFields(attribute.component, attributePath)];
1483
+ case "dynamiczone":
1484
+ return [
1485
+ ...acc,
1486
+ ...(attribute.components || []).flatMap(
1487
+ (componentUID) => getProhibitedCloningFields(componentUID, [
1488
+ ...attributePath,
1489
+ strapi.getModel(componentUID).info.displayName
1490
+ ])
1491
+ )
1492
+ ];
1493
+ case "uid":
1494
+ return [...acc, [attributePath, "unique"]];
1495
+ default:
1496
+ if (attribute?.unique) {
1497
+ return [...acc, [attributePath, "unique"]];
1498
+ }
1499
+ return acc;
1500
+ }
1501
+ },
1502
+ []
1503
+ );
1504
+ return prohibitedFields;
1505
+ };
1506
+ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []) => {
1507
+ const model = strapi.getModel(uid2);
1508
+ const canCreate = (path2) => permissionChecker2.can.create(null, path2);
1509
+ return Object.keys(model.attributes).reduce((body2, attributeName) => {
1510
+ const attribute = model.attributes[attributeName];
1511
+ const attributePath = [...path, attributeName].join(".");
1512
+ if (!isVisibleAttribute$2(model, attributeName)) {
1513
+ return body2;
1514
+ }
1515
+ switch (attribute.type) {
1516
+ case "relation": {
1517
+ if (canCreate(attributePath))
1518
+ return body2;
1519
+ return fp.set(attributePath, { set: [] }, body2);
1520
+ }
1521
+ case "component": {
1522
+ return excludeNotCreatableFields(attribute.component, permissionChecker2)(body2, [
1523
+ ...path,
1524
+ attributeName
1525
+ ]);
1526
+ }
1527
+ default: {
1528
+ if (canCreate(attributePath))
1529
+ return body2;
1530
+ return fp.set(attributePath, null, body2);
1531
+ }
1532
+ }
1533
+ }, body);
1534
+ };
1535
+ const getDocumentLocaleAndStatus = (request) => {
1536
+ const { locale, status, ...rest } = request || {};
1537
+ if (!fp.isNil(locale) && typeof locale !== "string") {
1538
+ throw new strapiUtils.errors.ValidationError(`Invalid locale: ${locale}`);
1539
+ }
1540
+ if (!fp.isNil(status) && !["draft", "published"].includes(status)) {
1541
+ throw new strapiUtils.errors.ValidationError(`Invalid status: ${status}`);
1542
+ }
1543
+ return { locale, status, ...rest };
1544
+ };
1545
+ const createDocument = async (ctx, opts) => {
1546
+ const { userAbility, user } = ctx.state;
1547
+ const { model } = ctx.params;
1548
+ const { body } = ctx.request;
1549
+ const documentManager2 = getService$1("document-manager");
1550
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1551
+ if (permissionChecker2.cannot.create()) {
1552
+ throw new strapiUtils.errors.ForbiddenError();
1553
+ }
1554
+ const pickPermittedFields = permissionChecker2.sanitizeCreateInput;
1555
+ const setCreator = strapiUtils.setCreatorFields({ user });
1556
+ const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1557
+ const sanitizedBody = await sanitizeFn(body);
1558
+ const { locale, status = "draft" } = getDocumentLocaleAndStatus(body);
1559
+ return documentManager2.create(model, {
1560
+ data: sanitizedBody,
1561
+ locale,
1562
+ status,
1563
+ populate: opts?.populate
1564
+ });
1565
+ };
1566
+ const updateDocument = async (ctx, opts) => {
1567
+ const { userAbility, user } = ctx.state;
1568
+ const { id, model } = ctx.params;
1569
+ const { body } = ctx.request;
1570
+ const documentManager2 = getService$1("document-manager");
1571
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1572
+ if (permissionChecker2.cannot.update()) {
1573
+ throw new strapiUtils.errors.ForbiddenError();
1574
+ }
1575
+ const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1576
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1577
+ const { locale } = getDocumentLocaleAndStatus(body);
1578
+ const [documentVersion, documentExists] = await Promise.all([
1579
+ documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1580
+ documentManager2.exists(model, id)
1581
+ ]);
1582
+ if (!documentExists) {
1583
+ throw new strapiUtils.errors.NotFoundError();
1584
+ }
1585
+ if (documentVersion) {
1586
+ if (permissionChecker2.cannot.update(documentVersion)) {
1587
+ throw new strapiUtils.errors.ForbiddenError();
1588
+ }
1589
+ } else if (permissionChecker2.cannot.create()) {
1590
+ throw new strapiUtils.errors.ForbiddenError();
1591
+ }
1592
+ const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
1593
+ const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
1594
+ const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1595
+ const sanitizedBody = await sanitizeFn(body);
1596
+ return documentManager2.update(documentVersion?.documentId || id, model, {
1597
+ data: sanitizedBody,
1598
+ populate: opts?.populate,
1599
+ locale
1600
+ });
1601
+ };
1602
+ const collectionTypes = {
1603
+ async find(ctx) {
1604
+ const { userAbility } = ctx.state;
1605
+ const { model } = ctx.params;
1606
+ const { query } = ctx.request;
1607
+ const documentMetadata2 = getService$1("document-metadata");
1608
+ const documentManager2 = getService$1("document-manager");
1609
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1610
+ if (permissionChecker2.cannot.read()) {
1611
+ return ctx.forbidden();
1612
+ }
1613
+ const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1614
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1615
+ const { locale, status } = getDocumentLocaleAndStatus(query);
1616
+ const { results: documents, pagination } = await documentManager2.findPage(
1617
+ { ...permissionQuery, populate, locale, status },
1618
+ model
1619
+ );
1620
+ const documentsAvailableStatus = await documentMetadata2.getManyAvailableStatus(
1621
+ model,
1622
+ documents
1623
+ );
1624
+ const setStatus = (document) => {
1625
+ const availableStatuses = documentsAvailableStatus.filter(
1626
+ (d) => d.documentId === document.documentId
1627
+ );
1628
+ document.status = documentMetadata2.getStatus(document, availableStatuses);
1629
+ return document;
1630
+ };
1631
+ const results = await strapiUtils.async.map(
1632
+ documents,
1633
+ strapiUtils.async.pipe(permissionChecker2.sanitizeOutput, setStatus)
1634
+ );
1635
+ ctx.body = {
1636
+ results,
1637
+ pagination
1638
+ };
1639
+ },
1640
+ async findOne(ctx) {
1641
+ const { userAbility } = ctx.state;
1642
+ const { model, id } = ctx.params;
1643
+ const documentManager2 = getService$1("document-manager");
1644
+ const documentMetadata2 = getService$1("document-metadata");
1645
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1646
+ if (permissionChecker2.cannot.read()) {
1647
+ return ctx.forbidden();
1648
+ }
1649
+ const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1650
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1651
+ const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
1652
+ const version = await documentManager2.findOne(id, model, {
1653
+ populate,
1654
+ locale,
1655
+ status
1656
+ });
1657
+ if (!version) {
1658
+ const exists = await documentManager2.exists(model, id);
1659
+ if (!exists) {
1660
+ return ctx.notFound();
1661
+ }
1662
+ const { meta } = await documentMetadata2.formatDocumentWithMetadata(
1663
+ model,
1664
+ { id, locale, publishedAt: null },
1665
+ { availableLocales: true, availableStatus: false }
1666
+ );
1667
+ ctx.body = { data: {}, meta };
1668
+ return;
1669
+ }
1670
+ if (permissionChecker2.cannot.read(version)) {
1671
+ return ctx.forbidden();
1672
+ }
1673
+ const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
1674
+ ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
1675
+ },
1676
+ async create(ctx) {
1677
+ const { userAbility } = ctx.state;
1678
+ const { model } = ctx.params;
1679
+ const documentMetadata2 = getService$1("document-metadata");
1680
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1681
+ const [totalEntries, document] = await Promise.all([
1682
+ strapi.db.query(model).count(),
1683
+ createDocument(ctx)
1684
+ ]);
1685
+ const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
1686
+ ctx.status = 201;
1687
+ ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument, {
1688
+ // Empty metadata as it's not relevant for a new document
1689
+ availableLocales: false,
1690
+ availableStatus: false
1691
+ });
1692
+ if (totalEntries === 0) {
1693
+ strapi.telemetry.send("didCreateFirstContentTypeEntry", {
1694
+ eventProperties: { model }
1695
+ });
1696
+ }
1697
+ },
1698
+ async update(ctx) {
1699
+ const { userAbility } = ctx.state;
1700
+ const { model } = ctx.params;
1701
+ const documentMetadata2 = getService$1("document-metadata");
1702
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1703
+ const updatedVersion = await updateDocument(ctx);
1704
+ const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
1705
+ ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedVersion);
1706
+ },
1707
+ async clone(ctx) {
1708
+ const { userAbility, user } = ctx.state;
1709
+ const { model, sourceId: id } = ctx.params;
1710
+ const { body } = ctx.request;
1711
+ const documentManager2 = getService$1("document-manager");
1712
+ const documentMetadata2 = getService$1("document-metadata");
1713
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1714
+ if (permissionChecker2.cannot.create()) {
1715
+ return ctx.forbidden();
1716
+ }
1717
+ const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1718
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1719
+ const { locale } = getDocumentLocaleAndStatus(body);
1720
+ const document = await documentManager2.findOne(id, model, {
1721
+ populate,
1722
+ locale,
1723
+ status: "draft"
1724
+ });
1725
+ if (!document) {
1726
+ return ctx.notFound();
1727
+ }
1728
+ const pickPermittedFields = permissionChecker2.sanitizeCreateInput;
1729
+ const setCreator = strapiUtils.setCreatorFields({ user });
1730
+ const excludeNotCreatable = excludeNotCreatableFields(model, permissionChecker2);
1731
+ const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator, excludeNotCreatable);
1732
+ const sanitizedBody = await sanitizeFn(body);
1733
+ const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
1734
+ const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
1735
+ ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument, {
1736
+ // Empty metadata as it's not relevant for a new document
1737
+ availableLocales: false,
1738
+ availableStatus: false
1739
+ });
1740
+ },
1741
+ async autoClone(ctx) {
1742
+ const { model } = ctx.params;
1743
+ const prohibitedFields = getProhibitedCloningFields(model);
1744
+ if (prohibitedFields.length > 0) {
1745
+ return ctx.badRequest(
1746
+ "Entity could not be cloned as it has unique and/or relational fields. Please edit those fields manually and save to complete the cloning.",
1747
+ {
1748
+ prohibitedFields
1749
+ }
1750
+ );
1751
+ }
1752
+ await this.clone(ctx);
1753
+ },
1754
+ async delete(ctx) {
1755
+ const { userAbility } = ctx.state;
1756
+ const { id, model } = ctx.params;
1757
+ const documentManager2 = getService$1("document-manager");
1758
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1759
+ if (permissionChecker2.cannot.delete()) {
1760
+ return ctx.forbidden();
1761
+ }
1762
+ const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1763
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1764
+ const { locale } = getDocumentLocaleAndStatus(ctx.query);
1765
+ const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1766
+ if (documentLocales.length === 0) {
1767
+ return ctx.notFound();
1768
+ }
1769
+ for (const document of documentLocales) {
1770
+ if (permissionChecker2.cannot.delete(document)) {
1771
+ return ctx.forbidden();
1772
+ }
1773
+ }
1774
+ const result = await documentManager2.delete(id, model, { locale });
1775
+ ctx.body = await permissionChecker2.sanitizeOutput(result);
1776
+ },
1777
+ /**
1778
+ * Publish a document version.
1779
+ * Supports creating/saving a document and publishing it in one request.
1780
+ */
1781
+ async publish(ctx) {
1782
+ const { userAbility } = ctx.state;
1783
+ const { id, model } = ctx.params;
1784
+ const { body } = ctx.request;
1785
+ const documentManager2 = getService$1("document-manager");
1786
+ const documentMetadata2 = getService$1("document-metadata");
1787
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1788
+ if (permissionChecker2.cannot.publish()) {
1789
+ return ctx.forbidden();
1790
+ }
1791
+ const publishedDocument = await strapi.db.transaction(async () => {
1792
+ const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1793
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1794
+ const document = id ? await updateDocument(ctx, { populate }) : await createDocument(ctx, { populate });
1795
+ if (permissionChecker2.cannot.publish(document)) {
1796
+ throw new strapiUtils.errors.ForbiddenError();
1797
+ }
1798
+ const { locale } = getDocumentLocaleAndStatus(body);
1799
+ return documentManager2.publish(document.documentId, model, {
1800
+ locale
1801
+ // TODO: Allow setting creator fields on publish
1802
+ // data: setCreatorFields({ user, isEdition: true })({}),
1803
+ });
1804
+ });
1805
+ const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
1806
+ ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
1807
+ },
1808
+ async bulkPublish(ctx) {
1809
+ const { userAbility } = ctx.state;
1810
+ const { model } = ctx.params;
1811
+ const { body } = ctx.request;
1812
+ const { ids } = body;
1813
+ await validateBulkActionInput(body);
1814
+ const documentManager2 = getService$1("document-manager");
1815
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1816
+ if (permissionChecker2.cannot.publish()) {
1817
+ return ctx.forbidden();
1818
+ }
1819
+ const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1820
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1821
+ const entityPromises = ids.map((id) => documentManager2.findOne(id, model, { populate }));
1822
+ const entities = await Promise.all(entityPromises);
1823
+ for (const entity of entities) {
1824
+ if (!entity) {
1825
+ return ctx.notFound();
1826
+ }
1827
+ if (permissionChecker2.cannot.publish(entity)) {
1828
+ return ctx.forbidden();
1829
+ }
1830
+ }
1831
+ const { count } = await documentManager2.publishMany(entities, model);
1832
+ ctx.body = { count };
1833
+ },
1834
+ async bulkUnpublish(ctx) {
1835
+ const { userAbility } = ctx.state;
1836
+ const { model } = ctx.params;
1837
+ const { body } = ctx.request;
1838
+ const { ids } = body;
1839
+ await validateBulkActionInput(body);
1840
+ const documentManager2 = getService$1("document-manager");
1841
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1842
+ if (permissionChecker2.cannot.unpublish()) {
1843
+ return ctx.forbidden();
1844
+ }
1845
+ const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1846
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1847
+ const entityPromises = ids.map((id) => documentManager2.findOne(id, model, { populate }));
1848
+ const entities = await Promise.all(entityPromises);
1849
+ for (const entity of entities) {
1850
+ if (!entity) {
1851
+ return ctx.notFound();
1852
+ }
1853
+ if (permissionChecker2.cannot.publish(entity)) {
1854
+ return ctx.forbidden();
1855
+ }
1856
+ }
1857
+ const { count } = await documentManager2.unpublishMany(entities, model);
1858
+ ctx.body = { count };
1859
+ },
1860
+ async unpublish(ctx) {
1861
+ const { userAbility } = ctx.state;
1862
+ const { id, model } = ctx.params;
1863
+ const {
1864
+ body: { discardDraft, ...body }
1865
+ } = ctx.request;
1866
+ const documentManager2 = getService$1("document-manager");
1867
+ const documentMetadata2 = getService$1("document-metadata");
1868
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1869
+ if (permissionChecker2.cannot.unpublish()) {
1870
+ return ctx.forbidden();
1871
+ }
1872
+ if (discardDraft && permissionChecker2.cannot.discard()) {
1873
+ return ctx.forbidden();
1874
+ }
1875
+ const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1876
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1877
+ const { locale } = getDocumentLocaleAndStatus(body);
1878
+ const document = await documentManager2.findOne(id, model, {
1879
+ populate,
1880
+ locale,
1881
+ status: "published"
1882
+ });
1883
+ if (!document) {
1884
+ throw new strapiUtils.errors.NotFoundError();
1885
+ }
1886
+ if (permissionChecker2.cannot.unpublish(document)) {
1887
+ throw new strapiUtils.errors.ForbiddenError();
1888
+ }
1889
+ if (discardDraft && permissionChecker2.cannot.discard(document)) {
1890
+ throw new strapiUtils.errors.ForbiddenError();
1891
+ }
1892
+ await strapi.db.transaction(async () => {
1893
+ if (discardDraft) {
1894
+ await documentManager2.discardDraft(document.documentId, model, { locale });
1895
+ }
1896
+ ctx.body = await strapiUtils.async.pipe(
1897
+ (document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
1898
+ permissionChecker2.sanitizeOutput,
1899
+ (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
1900
+ )(document);
1901
+ });
1902
+ },
1903
+ async discard(ctx) {
1904
+ const { userAbility } = ctx.state;
1905
+ const { id, model } = ctx.params;
1906
+ const { body } = ctx.request;
1907
+ const documentManager2 = getService$1("document-manager");
1908
+ const documentMetadata2 = getService$1("document-metadata");
1909
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1910
+ if (permissionChecker2.cannot.discard()) {
1911
+ return ctx.forbidden();
1912
+ }
1913
+ const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
1914
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1915
+ const { locale } = getDocumentLocaleAndStatus(body);
1916
+ const document = await documentManager2.findOne(id, model, {
1917
+ populate,
1918
+ locale,
1919
+ status: "published"
1920
+ });
1921
+ if (!document) {
1922
+ return ctx.notFound();
1923
+ }
1924
+ if (permissionChecker2.cannot.discard(document)) {
1925
+ return ctx.forbidden();
1926
+ }
1927
+ ctx.body = await strapiUtils.async.pipe(
1928
+ (document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
1929
+ permissionChecker2.sanitizeOutput,
1930
+ (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
1931
+ )(document);
1932
+ },
1933
+ async bulkDelete(ctx) {
1934
+ const { userAbility } = ctx.state;
1935
+ const { model } = ctx.params;
1936
+ const { query, body } = ctx.request;
1937
+ const { ids } = body;
1938
+ await validateBulkActionInput(body);
1939
+ const documentManager2 = getService$1("document-manager");
1940
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1941
+ if (permissionChecker2.cannot.delete()) {
1942
+ return ctx.forbidden();
1943
+ }
1944
+ const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
1945
+ const idsWhereClause = { id: { $in: ids } };
1946
+ const params = {
1947
+ ...permissionQuery,
1948
+ filters: {
1949
+ $and: [idsWhereClause].concat(permissionQuery.filters || [])
1950
+ }
1951
+ };
1952
+ const { count } = await documentManager2.deleteMany(params, model);
1953
+ ctx.body = { count };
1954
+ },
1955
+ async countDraftRelations(ctx) {
1956
+ const { userAbility } = ctx.state;
1957
+ const { model, id } = ctx.params;
1958
+ const documentManager2 = getService$1("document-manager");
1959
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1960
+ if (permissionChecker2.cannot.read()) {
1961
+ return ctx.forbidden();
1962
+ }
1963
+ const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1964
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1965
+ const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
1966
+ const entity = await documentManager2.findOne(id, model, { populate, locale, status });
1967
+ if (!entity) {
1968
+ return ctx.notFound();
1969
+ }
1970
+ if (permissionChecker2.cannot.read(entity)) {
1971
+ return ctx.forbidden();
1972
+ }
1973
+ const number = await documentManager2.countDraftRelations(id, model, locale);
1974
+ return {
1975
+ data: number
1976
+ };
1977
+ },
1978
+ async countManyEntriesDraftRelations(ctx) {
1979
+ const { userAbility } = ctx.state;
1980
+ const ids = ctx.request.query.ids;
1981
+ const locale = ctx.request.query.locale;
1982
+ const { model } = ctx.params;
1983
+ const documentManager2 = getService$1("document-manager");
1984
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
1985
+ if (permissionChecker2.cannot.read()) {
1986
+ return ctx.forbidden();
1987
+ }
1988
+ const entities = await documentManager2.findMany(
1989
+ {
1990
+ filters: {
1991
+ id: ids
1992
+ },
1993
+ locale
1994
+ },
1995
+ model
1996
+ );
1997
+ if (!entities) {
1998
+ return ctx.notFound();
1999
+ }
2000
+ const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
2001
+ return {
2002
+ data: number
2003
+ };
2004
+ }
2005
+ };
2006
+ const components$1 = {
2007
+ findComponents(ctx) {
2008
+ const components2 = getService$1("components").findAllComponents();
2009
+ const { toDto } = getService$1("data-mapper");
2010
+ ctx.body = { data: components2.map(toDto) };
2011
+ },
2012
+ async findComponentConfiguration(ctx) {
2013
+ const { uid: uid2 } = ctx.params;
2014
+ const componentService = getService$1("components");
2015
+ const component = componentService.findComponent(uid2);
2016
+ if (!component) {
2017
+ return ctx.notFound("component.notFound");
2018
+ }
2019
+ const configuration = await componentService.findConfiguration(component);
2020
+ const componentsConfigurations = await componentService.findComponentsConfigurations(component);
2021
+ ctx.body = {
2022
+ data: {
2023
+ component: configuration,
2024
+ components: componentsConfigurations
2025
+ }
2026
+ };
2027
+ },
2028
+ async updateComponentConfiguration(ctx) {
2029
+ const { uid: uid2 } = ctx.params;
2030
+ const { body } = ctx.request;
2031
+ const componentService = getService$1("components");
2032
+ const component = componentService.findComponent(uid2);
2033
+ if (!component) {
2034
+ return ctx.notFound("component.notFound");
2035
+ }
2036
+ let input;
2037
+ try {
2038
+ input = await createModelConfigurationSchema(component).validate(body, {
2039
+ abortEarly: false,
2040
+ stripUnknown: true,
2041
+ strict: true
2042
+ });
2043
+ } catch (error) {
2044
+ return ctx.badRequest(null, {
2045
+ name: "validationError",
2046
+ errors: error.errors
2047
+ });
2048
+ }
2049
+ const newConfiguration = await componentService.updateConfiguration(component, input);
2050
+ ctx.body = { data: newConfiguration };
2051
+ }
2052
+ };
2053
+ const hasEditMainField = fp.has("edit.mainField");
2054
+ const getEditMainField = fp.prop("edit.mainField");
2055
+ const assocListMainField = fp.assoc("list.mainField");
2056
+ const assocMainField = (metadata) => hasEditMainField(metadata) ? assocListMainField(getEditMainField(metadata), metadata) : metadata;
2057
+ const contentTypes = {
2058
+ async findContentTypes(ctx) {
2059
+ const { kind } = ctx.query;
2060
+ try {
2061
+ await validateKind(kind);
2062
+ } catch (error) {
2063
+ return ctx.send({ error }, 400);
2064
+ }
2065
+ const contentTypes2 = getService$1("content-types").findContentTypesByKind(kind);
2066
+ const { toDto } = getService$1("data-mapper");
2067
+ ctx.body = { data: contentTypes2.map(toDto) };
2068
+ },
2069
+ async findContentTypesSettings(ctx) {
2070
+ const { findAllContentTypes, findConfiguration } = getService$1("content-types");
2071
+ const contentTypes2 = await findAllContentTypes();
2072
+ const configurations = await Promise.all(
2073
+ contentTypes2.map(async (contentType) => {
2074
+ const { uid: uid2, settings } = await findConfiguration(contentType);
2075
+ return { uid: uid2, settings };
2076
+ })
2077
+ );
2078
+ ctx.body = {
2079
+ data: configurations
2080
+ };
2081
+ },
2082
+ async findContentTypeConfiguration(ctx) {
2083
+ const { uid: uid2 } = ctx.params;
2084
+ const contentTypeService = getService$1("content-types");
2085
+ const contentType = await contentTypeService.findContentType(uid2);
2086
+ if (!contentType) {
2087
+ return ctx.notFound("contentType.notFound");
2088
+ }
2089
+ const configuration = await contentTypeService.findConfiguration(contentType);
2090
+ const confWithUpdatedMetadata = {
2091
+ ...configuration,
2092
+ metadatas: fp.mapValues(assocMainField, configuration.metadatas)
2093
+ };
2094
+ const components2 = await contentTypeService.findComponentsConfigurations(contentType);
2095
+ ctx.body = {
2096
+ data: {
2097
+ contentType: confWithUpdatedMetadata,
2098
+ components: components2
2099
+ }
2100
+ };
2101
+ },
2102
+ async updateContentTypeConfiguration(ctx) {
2103
+ const { userAbility } = ctx.state;
2104
+ const { uid: uid2 } = ctx.params;
2105
+ const { body } = ctx.request;
2106
+ const contentTypeService = getService$1("content-types");
2107
+ const metricsService = getService$1("metrics");
2108
+ const contentType = await contentTypeService.findContentType(uid2);
2109
+ if (!contentType) {
2110
+ return ctx.notFound("contentType.notFound");
2111
+ }
2112
+ if (!getService$1("permission").canConfigureContentType({ userAbility, contentType })) {
2113
+ return ctx.forbidden();
2114
+ }
2115
+ let input;
2116
+ try {
2117
+ input = await createModelConfigurationSchema(contentType).validate(body, {
2118
+ abortEarly: false,
2119
+ stripUnknown: true,
2120
+ strict: true
2121
+ });
2122
+ } catch (error) {
2123
+ return ctx.badRequest(null, {
2124
+ name: "validationError",
2125
+ errors: error.errors
2126
+ });
2127
+ }
2128
+ const newConfiguration = await contentTypeService.updateConfiguration(contentType, input);
2129
+ await metricsService.sendDidConfigureListView(contentType, newConfiguration);
2130
+ const confWithUpdatedMetadata = {
2131
+ ...newConfiguration,
2132
+ metadatas: fp.mapValues(assocMainField, newConfiguration.metadatas)
2133
+ };
2134
+ const components2 = await contentTypeService.findComponentsConfigurations(contentType);
2135
+ ctx.body = {
2136
+ data: {
2137
+ contentType: confWithUpdatedMetadata,
2138
+ components: components2
2139
+ }
2140
+ };
2141
+ }
2142
+ };
2143
+ const init = {
2144
+ getInitData(ctx) {
2145
+ const { toDto } = getService$1("data-mapper");
2146
+ const { findAllComponents } = getService$1("components");
2147
+ const { getAllFieldSizes } = getService$1("field-sizes");
2148
+ const { findAllContentTypes } = getService$1("content-types");
2149
+ ctx.body = {
2150
+ data: {
2151
+ fieldSizes: getAllFieldSizes(),
2152
+ components: findAllComponents().map(toDto),
2153
+ contentTypes: findAllContentTypes().map(toDto)
2154
+ }
2155
+ };
2156
+ }
2157
+ };
2158
+ const validateFindAvailableSchema = strapiUtils.yup.object().shape({
2159
+ component: strapiUtils.yup.string(),
2160
+ id: strapiUtils.yup.strapiID(),
2161
+ _q: strapiUtils.yup.string(),
2162
+ idsToOmit: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()),
2163
+ idsToInclude: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()),
2164
+ page: strapiUtils.yup.number().integer().min(1),
2165
+ pageSize: strapiUtils.yup.number().integer().min(1).max(100),
2166
+ locale: strapiUtils.yup.string().nullable(),
2167
+ status: strapiUtils.yup.string().oneOf(["published", "draft"]).nullable()
2168
+ }).required();
2169
+ const validateFindExistingSchema = strapiUtils.yup.object().shape({
2170
+ page: strapiUtils.yup.number().integer().min(1),
2171
+ pageSize: strapiUtils.yup.number().integer().min(1).max(100),
2172
+ locale: strapiUtils.yup.string().nullable(),
2173
+ status: strapiUtils.yup.string().oneOf(["published", "draft"]).nullable()
2174
+ }).required();
2175
+ const validateFindAvailable = strapiUtils.validateYupSchema(validateFindAvailableSchema, { strict: false });
2176
+ const validateFindExisting = strapiUtils.validateYupSchema(validateFindExistingSchema, { strict: false });
2177
+ const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$2, UPDATED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
2178
+ const addFiltersClause = (params, filtersClause) => {
2179
+ params.filters = params.filters || {};
2180
+ params.filters.$and = params.filters.$and || [];
2181
+ params.filters.$and.push(filtersClause);
2182
+ };
2183
+ const sanitizeMainField = (model, mainField, userAbility) => {
2184
+ const permissionChecker2 = getService$1("permission-checker").create({
2185
+ userAbility,
2186
+ model: model.uid
2187
+ });
2188
+ if (!isListable(model, mainField)) {
2189
+ return "id";
2190
+ }
2191
+ if (permissionChecker2.cannot.read(null, mainField)) {
2192
+ if (model.uid === "plugin::users-permissions.role") {
2193
+ const userPermissionChecker = getService$1("permission-checker").create({
2194
+ userAbility,
2195
+ model: "plugin::users-permissions.user"
2196
+ });
2197
+ if (userPermissionChecker.can.read()) {
2198
+ return "name";
2199
+ }
2200
+ }
2201
+ return "id";
2202
+ }
2203
+ return mainField;
2204
+ };
2205
+ const addStatusToRelations = async (uid2, relations2) => {
2206
+ if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.contentTypes[uid2])) {
2207
+ return relations2;
2208
+ }
2209
+ const documentMetadata2 = getService$1("document-metadata");
2210
+ const documentsAvailableStatus = await documentMetadata2.getManyAvailableStatus(uid2, relations2);
2211
+ return relations2.map((relation) => {
2212
+ const availableStatuses = documentsAvailableStatus.filter(
2213
+ (availableDocument) => availableDocument.documentId === relation.documentId
2214
+ );
2215
+ return {
2216
+ ...relation,
2217
+ status: documentMetadata2.getStatus(relation, availableStatuses)
2218
+ };
2219
+ });
2220
+ };
2221
+ const getPublishedAtClause = (status, uid2) => {
2222
+ const model = strapi.getModel(uid2);
2223
+ if (!model || !strapiUtils.contentTypes.hasDraftAndPublish(model)) {
2224
+ return {};
2225
+ }
2226
+ return status === "published" ? { $notNull: true } : { $null: true };
2227
+ };
2228
+ const validateLocale = (sourceUid, targetUid, locale) => {
2229
+ const sourceModel = strapi.getModel(sourceUid);
2230
+ const targetModel = strapi.getModel(targetUid);
2231
+ const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
2232
+ const isSourceLocalized = isLocalized(sourceModel);
2233
+ const isTargetLocalized = isLocalized(targetModel);
2234
+ let validatedLocale = locale;
2235
+ if (!targetModel || !isTargetLocalized)
2236
+ validatedLocale = void 0;
2237
+ return {
2238
+ locale: validatedLocale,
2239
+ isSourceLocalized,
2240
+ isTargetLocalized
2241
+ };
2242
+ };
2243
+ const validateStatus = (sourceUid, status) => {
2244
+ const sourceModel = strapi.getModel(sourceUid);
2245
+ const isDP = strapiUtils.contentTypes.hasDraftAndPublish;
2246
+ const isSourceDP = isDP(sourceModel);
2247
+ if (!isSourceDP)
2248
+ return { status: void 0 };
2249
+ switch (status) {
2250
+ case "published":
2251
+ return { status: "published" };
2252
+ default:
2253
+ return { status: "draft" };
2254
+ }
2255
+ };
2256
+ const relations = {
2257
+ async extractAndValidateRequestInfo(ctx, id) {
2258
+ const { userAbility } = ctx.state;
2259
+ const { model, targetField } = ctx.params;
2260
+ const sourceSchema = strapi.getModel(model);
2261
+ if (!sourceSchema) {
2262
+ throw new strapiUtils.errors.ValidationError(`The model ${model} doesn't exist`);
2263
+ }
2264
+ const attribute = sourceSchema.attributes[targetField];
2265
+ if (!attribute || attribute.type !== "relation") {
2266
+ throw new strapiUtils.errors.ValidationError(
2267
+ `The relational field ${targetField} doesn't exist on ${model}`
2268
+ );
2269
+ }
2270
+ const sourceUid = model;
2271
+ const targetUid = attribute.target;
2272
+ const { locale, isSourceLocalized, isTargetLocalized } = validateLocale(
2273
+ sourceUid,
2274
+ targetUid,
2275
+ ctx.request?.query?.locale
2276
+ );
2277
+ const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
2278
+ const permissionChecker2 = getService$1("permission-checker").create({
2279
+ userAbility,
2280
+ model
2281
+ });
2282
+ const isComponent2 = sourceSchema.modelType === "component";
2283
+ if (!isComponent2) {
2284
+ if (permissionChecker2.cannot.read(null, targetField)) {
2285
+ return ctx.forbidden();
2286
+ }
2287
+ }
2288
+ let entryId = null;
2289
+ if (id) {
2290
+ const where = {};
2291
+ if (!isComponent2) {
2292
+ where.documentId = id;
2293
+ if (status) {
2294
+ where.publishedAt = getPublishedAtClause(status, sourceUid);
2295
+ }
2296
+ if (locale && isSourceLocalized) {
2297
+ where.locale = locale;
2298
+ }
2299
+ } else {
2300
+ where.id = id;
2301
+ }
2302
+ const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2303
+ const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2304
+ const currentEntity = await strapi.db.query(model).findOne({
2305
+ where,
2306
+ populate
2307
+ });
2308
+ if (!currentEntity) {
2309
+ throw new strapiUtils.errors.NotFoundError();
2310
+ }
2311
+ if (!isComponent2) {
2312
+ if (permissionChecker2.cannot.read(currentEntity, targetField)) {
2313
+ throw new strapiUtils.errors.ForbiddenError();
2314
+ }
2315
+ }
2316
+ entryId = currentEntity.id;
2317
+ }
2318
+ const modelConfig = isComponent2 ? await getService$1("components").findConfiguration(sourceSchema) : await getService$1("content-types").findConfiguration(sourceSchema);
2319
+ const targetSchema = strapi.getModel(targetUid);
2320
+ const mainField = fp.flow(
2321
+ fp.prop(`metadatas.${targetField}.edit.mainField`),
2322
+ (mainField2) => mainField2 || "id",
2323
+ (mainField2) => sanitizeMainField(targetSchema, mainField2, userAbility)
2324
+ )(modelConfig);
2325
+ const fieldsToSelect = fp.uniq([
2326
+ mainField,
2327
+ PUBLISHED_AT_ATTRIBUTE$2,
2328
+ UPDATED_AT_ATTRIBUTE,
2329
+ "documentId"
2330
+ ]);
2331
+ if (isTargetLocalized) {
2332
+ fieldsToSelect.push("locale");
2333
+ }
2334
+ return {
2335
+ entryId,
2336
+ locale,
2337
+ status,
2338
+ attribute,
2339
+ fieldsToSelect,
2340
+ mainField,
2341
+ source: { schema: sourceSchema },
2342
+ target: { schema: targetSchema, isLocalized: isTargetLocalized },
2343
+ sourceSchema,
2344
+ targetSchema,
2345
+ targetField
2346
+ };
2347
+ },
2348
+ /**
2349
+ * Used to find new relations to add in a relational field.
2350
+ *
2351
+ * Component and document relations are dealt a bit differently (they don't have a document_id).
2352
+ */
2353
+ async findAvailable(ctx) {
2354
+ const { id } = ctx.request.query;
2355
+ await validateFindAvailable(ctx.request.query);
2356
+ const {
2357
+ locale,
2358
+ status,
2359
+ targetField,
2360
+ fieldsToSelect,
2361
+ mainField,
2362
+ source: {
2363
+ schema: { uid: sourceUid, modelType: sourceModelType }
2364
+ },
2365
+ target: {
2366
+ schema: { uid: targetUid },
2367
+ isLocalized: isTargetLocalized
2368
+ }
2369
+ } = await this.extractAndValidateRequestInfo(ctx, id);
2370
+ const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
2371
+ const permissionChecker2 = getService$1("permission-checker").create({
2372
+ userAbility: ctx.state.userAbility,
2373
+ model: targetUid
2374
+ });
2375
+ const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2376
+ const queryParams = {
2377
+ sort: mainField,
2378
+ // cannot select other fields as the user may not have the permissions
2379
+ fields: fieldsToSelect,
2380
+ ...permissionQuery
2381
+ };
2382
+ addFiltersClause(queryParams, {
2383
+ publishedAt: getPublishedAtClause(status, targetUid)
2384
+ });
2385
+ const filterByLocale = isTargetLocalized && locale;
2386
+ if (filterByLocale) {
2387
+ addFiltersClause(queryParams, { locale });
2388
+ }
2389
+ if (id) {
2390
+ const subQuery = strapi.db.queryBuilder(sourceUid);
2391
+ const alias = subQuery.getAlias();
2392
+ const where = {
2393
+ [`${alias}.id`]: { $notNull: true },
2394
+ [`${alias}.document_id`]: { $notNull: true }
2395
+ };
2396
+ if (sourceModelType === "contentType") {
2397
+ where.document_id = id;
2398
+ } else {
2399
+ where.id = id;
2400
+ }
2401
+ if (status) {
2402
+ where[`${alias}.published_at`] = getPublishedAtClause(status, targetUid);
2403
+ }
2404
+ if (filterByLocale) {
2405
+ where[`${alias}.locale`] = locale;
2406
+ }
2407
+ if ((idsToInclude?.length ?? 0) !== 0) {
2408
+ where[`${alias}.id`].$notIn = idsToInclude;
2409
+ }
2410
+ const knexSubQuery = subQuery.where(where).join({ alias, targetField }).select(`${alias}.id`).getKnexQuery();
2411
+ addFiltersClause(queryParams, {
2412
+ id: { $notIn: knexSubQuery }
2413
+ });
2414
+ }
2415
+ if (_q) {
2416
+ const _filter = strapiUtils.isOperatorOfType("where", query._filter) ? query._filter : "$containsi";
2417
+ addFiltersClause(queryParams, { [mainField]: { [_filter]: _q } });
2418
+ }
2419
+ if (idsToOmit?.length > 0) {
2420
+ addFiltersClause(queryParams, {
2421
+ id: { $notIn: fp.uniq(idsToOmit) }
2422
+ });
2423
+ }
2424
+ const res = await strapi.db.query(targetUid).findPage(strapi.get("query-params").transform(targetUid, queryParams));
2425
+ ctx.body = {
2426
+ ...res,
2427
+ results: await addStatusToRelations(targetUid, res.results)
2428
+ };
2429
+ },
2430
+ async findExisting(ctx) {
2431
+ const { userAbility } = ctx.state;
2432
+ const { id } = ctx.params;
2433
+ await validateFindExisting(ctx.request.query);
2434
+ const {
2435
+ entryId,
2436
+ attribute,
2437
+ targetField,
2438
+ fieldsToSelect,
2439
+ source: {
2440
+ schema: { uid: sourceUid }
2441
+ },
2442
+ target: {
2443
+ schema: { uid: targetUid }
2444
+ }
2445
+ } = await this.extractAndValidateRequestInfo(ctx, id);
2446
+ const permissionQuery = await getService$1("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
2447
+ const dbQuery = strapi.db.query(sourceUid);
2448
+ const loadRelations = strapiUtils.relations.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
2449
+ const res = await loadRelations({ id: entryId }, targetField, {
2450
+ select: ["id", "documentId", "locale", "publishedAt"],
2451
+ ordering: "desc",
2452
+ page: ctx.request.query.page,
2453
+ pageSize: ctx.request.query.pageSize
2454
+ });
2455
+ const loadedIds = res.results.map((item) => item.id);
2456
+ addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
2457
+ const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
2458
+ ...strapi.get("query-params").transform(targetUid, permissionQuery),
2459
+ ordering: "desc",
2460
+ page: ctx.request.query.page,
2461
+ pageSize: ctx.request.query.pageSize
2462
+ });
2463
+ const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
2464
+ ctx.body = {
2465
+ pagination: res.pagination || {
2466
+ page: 1,
2467
+ pageCount: 1,
2468
+ pageSize: 10,
2469
+ total: relationsUnion.length
2470
+ },
2471
+ results: await addStatusToRelations(targetUid, relationsUnion)
2472
+ };
2473
+ }
2474
+ };
2475
+ const buildPopulateFromQuery = async (query, model) => {
2476
+ return getService$1("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
2477
+ };
2478
+ const findDocument = async (query, uid2, opts = {}) => {
2479
+ const documentManager2 = getService$1("document-manager");
2480
+ const populate = await buildPopulateFromQuery(query, uid2);
2481
+ return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
2482
+ };
2483
+ const createOrUpdateDocument = async (ctx, opts) => {
2484
+ const { user, userAbility } = ctx.state;
2485
+ const { model } = ctx.params;
2486
+ const { body, query } = ctx.request;
2487
+ const documentManager2 = getService$1("document-manager");
2488
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2489
+ if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
2490
+ throw new strapiUtils.errors.ForbiddenError();
2491
+ }
2492
+ const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2493
+ const { locale } = getDocumentLocaleAndStatus(body);
2494
+ const [documentVersion, otherDocumentVersion] = await Promise.all([
2495
+ findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2496
+ // Find the first document to check if it exists
2497
+ strapi.db.query(model).findOne({ select: ["documentId"] })
2498
+ ]);
2499
+ const documentId = otherDocumentVersion?.documentId;
2500
+ const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
2501
+ const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
2502
+ const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
2503
+ if (documentVersion) {
2504
+ if (permissionChecker2.cannot.update(documentVersion)) {
2505
+ throw new strapiUtils.errors.ForbiddenError();
2506
+ }
2507
+ } else if (permissionChecker2.cannot.create()) {
2508
+ throw new strapiUtils.errors.ForbiddenError();
2509
+ }
2510
+ const sanitizedBody = await sanitizeFn(body);
2511
+ if (!documentId) {
2512
+ return documentManager2.create(model, {
2513
+ data: sanitizedBody,
2514
+ ...sanitizedQuery,
2515
+ locale
2516
+ });
2517
+ }
2518
+ return documentManager2.update(documentId, model, {
2519
+ data: sanitizedBody,
2520
+ populate: opts?.populate,
2521
+ locale
2522
+ });
2523
+ };
2524
+ const singleTypes = {
2525
+ async find(ctx) {
2526
+ const { userAbility } = ctx.state;
2527
+ const { model } = ctx.params;
2528
+ const { query = {} } = ctx.request;
2529
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2530
+ const documentMetadata2 = getService$1("document-metadata");
2531
+ if (permissionChecker2.cannot.read()) {
2532
+ return ctx.forbidden();
2533
+ }
2534
+ const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2535
+ const { locale, status } = getDocumentLocaleAndStatus(query);
2536
+ const version = await findDocument(permissionQuery, model, { locale, status });
2537
+ if (!version) {
2538
+ if (permissionChecker2.cannot.create()) {
2539
+ return ctx.forbidden();
2540
+ }
2541
+ const document = await strapi.db.query(model).findOne({});
2542
+ if (!document) {
2543
+ return ctx.notFound();
2544
+ }
2545
+ const { meta } = await documentMetadata2.formatDocumentWithMetadata(
2546
+ model,
2547
+ { id: document.documentId, locale, publishedAt: null },
2548
+ { availableLocales: true, availableStatus: false }
2549
+ );
2550
+ ctx.body = { data: {}, meta };
2551
+ return;
2552
+ }
2553
+ if (permissionChecker2.cannot.read(version)) {
2554
+ return ctx.forbidden();
2555
+ }
2556
+ const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
2557
+ ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2558
+ },
2559
+ async createOrUpdate(ctx) {
2560
+ const { userAbility } = ctx.state;
2561
+ const { model } = ctx.params;
2562
+ const documentMetadata2 = getService$1("document-metadata");
2563
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2564
+ const document = await createOrUpdateDocument(ctx);
2565
+ const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
2566
+ ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2567
+ },
2568
+ async delete(ctx) {
2569
+ const { userAbility } = ctx.state;
2570
+ const { model } = ctx.params;
2571
+ const { query = {} } = ctx.request;
2572
+ const documentManager2 = getService$1("document-manager");
2573
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2574
+ if (permissionChecker2.cannot.delete()) {
2575
+ return ctx.forbidden();
2576
+ }
2577
+ const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2578
+ const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2579
+ const { locale } = getDocumentLocaleAndStatus(query);
2580
+ const documentLocales = await documentManager2.findLocales(void 0, model, {
2581
+ populate,
2582
+ locale
2583
+ });
2584
+ if (documentLocales.length === 0) {
2585
+ return ctx.notFound();
2586
+ }
2587
+ for (const document of documentLocales) {
2588
+ if (permissionChecker2.cannot.delete(document)) {
2589
+ return ctx.forbidden();
2590
+ }
2591
+ }
2592
+ const deletedEntity = await documentManager2.delete(documentLocales.at(0).documentId, model, {
2593
+ locale
2594
+ });
2595
+ ctx.body = await permissionChecker2.sanitizeOutput(deletedEntity);
2596
+ },
2597
+ async publish(ctx) {
2598
+ const { userAbility } = ctx.state;
2599
+ const { model } = ctx.params;
2600
+ const { query = {} } = ctx.request;
2601
+ const documentManager2 = getService$1("document-manager");
2602
+ const documentMetadata2 = getService$1("document-metadata");
2603
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2604
+ if (permissionChecker2.cannot.publish()) {
2605
+ return ctx.forbidden();
2606
+ }
2607
+ const publishedDocument = await strapi.db.transaction(async () => {
2608
+ const sanitizedQuery = await permissionChecker2.sanitizedQuery.publish(query);
2609
+ const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2610
+ const document = await createOrUpdateDocument(ctx, { populate });
2611
+ if (!document) {
2612
+ throw new strapiUtils.errors.NotFoundError();
2613
+ }
2614
+ if (permissionChecker2.cannot.publish(document)) {
2615
+ throw new strapiUtils.errors.ForbiddenError();
2616
+ }
2617
+ const { locale } = getDocumentLocaleAndStatus(document);
2618
+ return documentManager2.publish(document.documentId, model, { locale });
2619
+ });
2620
+ const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
2621
+ ctx.body = await documentMetadata2.formatDocumentWithMetadata(model, sanitizedDocument);
2622
+ },
2623
+ async unpublish(ctx) {
2624
+ const { userAbility } = ctx.state;
2625
+ const { model } = ctx.params;
2626
+ const {
2627
+ body: { discardDraft, ...body },
2628
+ query = {}
2629
+ } = ctx.request;
2630
+ const documentManager2 = getService$1("document-manager");
2631
+ const documentMetadata2 = getService$1("document-metadata");
2632
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2633
+ if (permissionChecker2.cannot.unpublish()) {
2634
+ return ctx.forbidden();
2635
+ }
2636
+ if (discardDraft && permissionChecker2.cannot.discard()) {
2637
+ return ctx.forbidden();
2638
+ }
2639
+ const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2640
+ const { locale } = getDocumentLocaleAndStatus(body);
2641
+ const document = await findDocument(sanitizedQuery, model, { locale });
2642
+ if (!document) {
2643
+ return ctx.notFound();
2644
+ }
2645
+ if (permissionChecker2.cannot.unpublish(document)) {
2646
+ return ctx.forbidden();
2647
+ }
2648
+ if (discardDraft && permissionChecker2.cannot.discard(document)) {
2649
+ return ctx.forbidden();
2650
+ }
2651
+ await strapi.db.transaction(async () => {
2652
+ if (discardDraft) {
2653
+ await documentManager2.discardDraft(document.documentId, model, { locale });
2654
+ }
2655
+ ctx.body = await strapiUtils.async.pipe(
2656
+ (document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
2657
+ permissionChecker2.sanitizeOutput,
2658
+ (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2659
+ )(document);
2660
+ });
2661
+ },
2662
+ async discard(ctx) {
2663
+ const { userAbility } = ctx.state;
2664
+ const { model } = ctx.params;
2665
+ const { body, query = {} } = ctx.request;
2666
+ const documentManager2 = getService$1("document-manager");
2667
+ const documentMetadata2 = getService$1("document-metadata");
2668
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2669
+ if (permissionChecker2.cannot.discard()) {
2670
+ return ctx.forbidden();
2671
+ }
2672
+ const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2673
+ const { locale } = getDocumentLocaleAndStatus(body);
2674
+ const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2675
+ if (!document) {
2676
+ return ctx.notFound();
2677
+ }
2678
+ if (permissionChecker2.cannot.discard(document)) {
2679
+ return ctx.forbidden();
2680
+ }
2681
+ ctx.body = await strapiUtils.async.pipe(
2682
+ (document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
2683
+ permissionChecker2.sanitizeOutput,
2684
+ (document2) => documentMetadata2.formatDocumentWithMetadata(model, document2)
2685
+ )(document);
2686
+ },
2687
+ async countDraftRelations(ctx) {
2688
+ const { userAbility } = ctx.state;
2689
+ const { model } = ctx.params;
2690
+ const { query } = ctx.request;
2691
+ const documentManager2 = getService$1("document-manager");
2692
+ const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2693
+ const { locale } = getDocumentLocaleAndStatus(query);
2694
+ if (permissionChecker2.cannot.read()) {
2695
+ return ctx.forbidden();
2696
+ }
2697
+ const document = await findDocument({}, model);
2698
+ if (!document) {
2699
+ return ctx.notFound();
2700
+ }
2701
+ if (permissionChecker2.cannot.read(document)) {
2702
+ return ctx.forbidden();
2703
+ }
2704
+ const number = await documentManager2.countDraftRelations(document.documentId, model, locale);
2705
+ return {
2706
+ data: number
2707
+ };
2708
+ }
2709
+ };
2710
+ const uid$1 = {
2711
+ async generateUID(ctx) {
2712
+ const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2713
+ const { query = {} } = ctx.request;
2714
+ const { locale } = getDocumentLocaleAndStatus(query);
2715
+ await validateUIDField(contentTypeUID, field);
2716
+ const uidService = getService$1("uid");
2717
+ ctx.body = {
2718
+ data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
2719
+ };
2720
+ },
2721
+ async checkUIDAvailability(ctx) {
2722
+ const { contentTypeUID, field, value } = await validateCheckUIDAvailabilityInput(
2723
+ ctx.request.body
2724
+ );
2725
+ const { query = {} } = ctx.request;
2726
+ const { locale } = getDocumentLocaleAndStatus(query);
2727
+ await validateUIDField(contentTypeUID, field);
2728
+ const uidService = getService$1("uid");
2729
+ const isAvailable = await uidService.checkUIDAvailability({
2730
+ contentTypeUID,
2731
+ field,
2732
+ value,
2733
+ locale
2734
+ });
2735
+ ctx.body = {
2736
+ isAvailable,
2737
+ suggestion: !isAvailable ? await uidService.findUniqueUID({ contentTypeUID, field, value, locale }) : null
2738
+ };
2739
+ }
2740
+ };
2741
+ const controllers = {
2742
+ "collection-types": collectionTypes,
2743
+ components: components$1,
2744
+ "content-types": contentTypes,
2745
+ init,
2746
+ relations,
2747
+ "single-types": singleTypes,
2748
+ uid: uid$1,
2749
+ ...history.controllers ? history.controllers : {}
2750
+ };
2751
+ const keys = {
2752
+ CONFIGURATION: "configuration"
2753
+ };
2754
+ const getStore = () => strapi.store({ type: "plugin", name: "content_manager" });
2755
+ const EMPTY_CONFIG = {
2756
+ settings: {},
2757
+ metadatas: {},
2758
+ layouts: {}
2759
+ };
2760
+ const configurationKey = (key) => `${keys.CONFIGURATION}_${key}`;
2761
+ const getModelConfiguration = async (key) => {
2762
+ const config = await getStore().get({ key: configurationKey(key) });
2763
+ return ___default.default.merge({}, EMPTY_CONFIG, config);
2764
+ };
2765
+ const setModelConfiguration = async (key, value) => {
2766
+ const storedConfig = await getStore().get({ key: configurationKey(key) }) || {};
2767
+ const currentConfig = { ...storedConfig };
2768
+ Object.keys(value).forEach((key2) => {
2769
+ if (value[key2] !== null && value[key2] !== void 0) {
2770
+ ___default.default.set(currentConfig, key2, value[key2]);
2771
+ }
2772
+ });
2773
+ if (!___default.default.isEqual(currentConfig, storedConfig)) {
2774
+ return getStore().set({
2775
+ key: configurationKey(key),
2776
+ value: currentConfig
2777
+ });
2778
+ }
2779
+ };
2780
+ const deleteKey = (key) => {
2781
+ return strapi.db.query("strapi::core-store").delete({ where: { key: `plugin_content_manager_configuration_${key}` } });
2782
+ };
2783
+ const findByKey = async (key) => {
2784
+ const results = await strapi.db.query("strapi::core-store").findMany({
2785
+ where: {
2786
+ key: {
2787
+ $startsWith: key
2788
+ }
2789
+ }
2790
+ });
2791
+ return results.map(({ value }) => JSON.parse(value));
2792
+ };
2793
+ const getAllConfigurations = () => findByKey("plugin_content_manager_configuration");
2794
+ const storeUtils = {
2795
+ getAllConfigurations,
2796
+ findByKey,
2797
+ getModelConfiguration,
2798
+ setModelConfiguration,
2799
+ deleteKey,
2800
+ keys
2801
+ };
2802
+ function createDefaultMetadatas(schema) {
2803
+ return {
2804
+ ...Object.keys(schema.attributes).reduce((acc, name) => {
2805
+ acc[name] = createDefaultMetadata(schema, name);
2806
+ return acc;
2807
+ }, {}),
2808
+ id: {
2809
+ edit: {},
2810
+ list: {
2811
+ label: "id",
2812
+ searchable: true,
2813
+ sortable: true
2814
+ }
2815
+ }
2816
+ };
2817
+ }
2818
+ function createDefaultMetadata(schema, name) {
2819
+ const edit = {
2820
+ label: name,
2821
+ description: "",
2822
+ placeholder: "",
2823
+ visible: isVisible$1(schema, name),
2824
+ editable: true
2825
+ };
2826
+ const fieldAttributes = schema.attributes[name];
2827
+ if (isRelation$1(fieldAttributes)) {
2828
+ const { targetModel } = fieldAttributes;
2829
+ const targetSchema = getTargetSchema(targetModel);
2830
+ if (targetSchema) {
2831
+ edit.mainField = getDefaultMainField(targetSchema);
2832
+ }
2833
+ }
2834
+ ___default.default.assign(
2835
+ edit,
2836
+ ___default.default.pick(___default.default.get(schema, ["config", "metadatas", name, "edit"], {}), [
2837
+ "label",
2838
+ "description",
2839
+ "placeholder",
2840
+ "visible",
2841
+ "editable",
2842
+ "mainField"
2843
+ ])
2844
+ );
2845
+ const list = {
2846
+ // @ts-expect-error we need to specify these properties
2847
+ label: name,
2848
+ // @ts-expect-error we need to specify these properties
2849
+ searchable: isSearchable(schema, name),
2850
+ // @ts-expect-error we need to specify these properties
2851
+ sortable: isSortable(schema, name),
2852
+ ...___default.default.pick(___default.default.get(schema, ["config", "metadatas", name, "list"], {}), [
2853
+ "label",
2854
+ "searchable",
2855
+ "sortable"
2856
+ ])
2857
+ };
2858
+ return { edit, list };
2859
+ }
2860
+ async function syncMetadatas(configuration, schema) {
2861
+ if (___default.default.isEmpty(configuration.metadatas)) {
2862
+ return createDefaultMetadatas(schema);
2863
+ }
2864
+ const metasWithValidKeys = ___default.default.pick(configuration.metadatas, Object.keys(schema.attributes));
2865
+ const metasWithDefaults = ___default.default.merge({}, createDefaultMetadatas(schema), metasWithValidKeys);
2866
+ const updatedMetas = Object.keys(metasWithDefaults).reduce((acc, key) => {
2867
+ const { edit, list } = metasWithDefaults[key];
2868
+ const attr = schema.attributes[key];
2869
+ const updatedMeta = { edit, list };
2870
+ if (list.sortable && !isSortable(schema, key)) {
2871
+ ___default.default.set(updatedMeta, ["list", "sortable"], false);
2872
+ ___default.default.set(acc, [key], updatedMeta);
2873
+ }
2874
+ if (list.searchable && !isSearchable(schema, key)) {
2875
+ ___default.default.set(updatedMeta, ["list", "searchable"], false);
2876
+ ___default.default.set(acc, [key], updatedMeta);
2877
+ }
2878
+ if (!___default.default.has(edit, "mainField"))
2879
+ return acc;
2880
+ if (!isRelation$1(attr)) {
2881
+ ___default.default.set(updatedMeta, "edit", ___default.default.omit(edit, ["mainField"]));
2882
+ ___default.default.set(acc, [key], updatedMeta);
2883
+ return acc;
2884
+ }
2885
+ if (edit.mainField === "id")
2886
+ return acc;
2887
+ const targetSchema = getTargetSchema(attr.targetModel);
2888
+ if (!targetSchema)
2889
+ return acc;
2890
+ if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
2891
+ ___default.default.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
2892
+ ___default.default.set(acc, [key], updatedMeta);
2893
+ return acc;
2894
+ }
2895
+ return acc;
2896
+ }, {});
2897
+ return ___default.default.assign(metasWithDefaults, updatedMetas);
2898
+ }
2899
+ const getTargetSchema = (targetModel) => {
2900
+ return getService$1("content-types").findContentType(targetModel);
2901
+ };
2902
+ const DEFAULT_LIST_LENGTH = 4;
2903
+ const MAX_ROW_SIZE = 12;
2904
+ const isAllowedFieldSize = (type, size) => {
2905
+ const { getFieldSize } = getService$1("field-sizes");
2906
+ const fieldSize = getFieldSize(type);
2907
+ if (!fieldSize.isResizable && size !== fieldSize.default) {
2908
+ return false;
2909
+ }
2910
+ return size <= MAX_ROW_SIZE;
2911
+ };
2912
+ const getDefaultFieldSize = (attribute) => {
2913
+ const { hasFieldSize, getFieldSize } = getService$1("field-sizes");
2914
+ return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
2915
+ };
2916
+ async function createDefaultLayouts(schema) {
2917
+ return {
2918
+ // @ts-expect-error necessary to provide this default layout
2919
+ list: createDefaultListLayout(schema),
2920
+ // @ts-expect-error necessary to provide this default layout
2921
+ edit: createDefaultEditLayout(schema),
2922
+ ...___default.default.pick(___default.default.get(schema, ["config", "layouts"], {}), ["list", "edit"])
2923
+ };
2924
+ }
2925
+ function createDefaultListLayout(schema) {
2926
+ return Object.keys(schema.attributes).filter((name) => isListable(schema, name)).slice(0, DEFAULT_LIST_LENGTH);
2927
+ }
2928
+ const rowSize = (els) => els.reduce((sum, el) => sum + el.size, 0);
2929
+ function createDefaultEditLayout(schema) {
2930
+ const keys2 = Object.keys(schema.attributes).filter((name) => hasEditableAttribute(schema, name));
2931
+ return appendToEditLayout([], keys2, schema);
2932
+ }
2933
+ function syncLayouts(configuration, schema) {
2934
+ if (___default.default.isEmpty(configuration.layouts))
2935
+ return createDefaultLayouts(schema);
2936
+ const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
2937
+ let cleanList = list.filter((attr) => isListable(schema, attr));
2938
+ const cleanEditRelations = editRelations.filter(
2939
+ (attr) => hasRelationAttribute(schema, attr)
2940
+ );
2941
+ const elementsToReAppend = [...cleanEditRelations];
2942
+ let cleanEdit = [];
2943
+ for (const row of edit) {
2944
+ const newRow = [];
2945
+ for (const el of row) {
2946
+ if (!hasEditableAttribute(schema, el.name))
2947
+ continue;
2948
+ const { hasFieldSize } = getService$1("field-sizes");
2949
+ const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
2950
+ if (!isAllowedFieldSize(fieldType, el.size)) {
2951
+ elementsToReAppend.push(el.name);
2952
+ continue;
2953
+ }
2954
+ newRow.push(el);
2955
+ }
2956
+ if (newRow.length > 0) {
2957
+ cleanEdit.push(newRow);
2958
+ }
2959
+ }
2960
+ cleanEdit = appendToEditLayout(cleanEdit, elementsToReAppend, schema);
2961
+ const newAttributes = ___default.default.difference(
2962
+ Object.keys(schema.attributes),
2963
+ Object.keys(configuration.metadatas)
2964
+ );
2965
+ if (cleanList.length < DEFAULT_LIST_LENGTH) {
2966
+ cleanList = ___default.default.uniq(
2967
+ cleanList.concat(newAttributes.filter((key) => isListable(schema, key))).slice(0, DEFAULT_LIST_LENGTH)
2968
+ );
2969
+ }
2970
+ const newEditAttributes = newAttributes.filter((key) => hasEditableAttribute(schema, key));
2971
+ cleanEdit = appendToEditLayout(cleanEdit, newEditAttributes, schema);
2972
+ return {
2973
+ list: cleanList.length > 0 ? cleanList : createDefaultListLayout(schema),
2974
+ edit: cleanEdit.length > 0 ? cleanEdit : createDefaultEditLayout(schema)
2975
+ };
2976
+ }
2977
+ const appendToEditLayout = (layout = [], keysToAppend, schema) => {
2978
+ if (keysToAppend.length === 0)
2979
+ return layout;
2980
+ let currentRowIndex = Math.max(layout.length - 1, 0);
2981
+ if (!layout[currentRowIndex]) {
2982
+ layout[currentRowIndex] = [];
2983
+ }
2984
+ for (const key of keysToAppend) {
2985
+ const attribute = schema.attributes[key];
2986
+ const attributeSize = getDefaultFieldSize(attribute);
2987
+ const currenRowSize = rowSize(layout[currentRowIndex]);
2988
+ if (currenRowSize + attributeSize > MAX_ROW_SIZE) {
2989
+ currentRowIndex += 1;
2990
+ layout[currentRowIndex] = [];
2991
+ }
2992
+ layout[currentRowIndex].push({
2993
+ name: key,
2994
+ size: attributeSize
2995
+ });
2996
+ }
2997
+ return layout;
2998
+ };
2999
+ async function validateCustomConfig(schema) {
3000
+ try {
3001
+ await createModelConfigurationSchema(schema, {
3002
+ allowUndefined: true
3003
+ }).validate(schema.config);
3004
+ } catch (error) {
3005
+ throw new Error(
3006
+ `Invalid Model configuration for model ${schema.uid}. Verify your {{ modelName }}.config.js(on) file:
3007
+ - ${error.message}
3008
+ `
3009
+ );
3010
+ }
3011
+ }
3012
+ async function createDefaultConfiguration(schema) {
3013
+ await validateCustomConfig(schema);
3014
+ return {
3015
+ settings: await createDefaultSettings(schema),
3016
+ metadatas: await createDefaultMetadatas(schema),
3017
+ layouts: await createDefaultLayouts(schema)
3018
+ };
3019
+ }
3020
+ async function syncConfiguration(conf, schema) {
3021
+ await validateCustomConfig(schema);
3022
+ return {
3023
+ settings: await syncSettings(conf, schema),
3024
+ layouts: await syncLayouts(conf, schema),
3025
+ metadatas: await syncMetadatas(conf, schema)
3026
+ };
3027
+ }
3028
+ const createConfigurationService = ({
3029
+ isComponent: isComponent2,
3030
+ prefix,
3031
+ storeUtils: storeUtils2,
3032
+ getModels
3033
+ }) => {
3034
+ const uidToStoreKey = (uid2) => {
3035
+ return `${prefix}::${uid2}`;
3036
+ };
3037
+ const getConfiguration = (uid2) => {
3038
+ const storeKey = uidToStoreKey(uid2);
3039
+ return storeUtils2.getModelConfiguration(storeKey);
3040
+ };
3041
+ const setConfiguration = (uid2, input) => {
3042
+ const configuration = {
3043
+ ...input,
3044
+ uid: uid2,
3045
+ isComponent: isComponent2 ?? void 0
3046
+ };
3047
+ const storeKey = uidToStoreKey(uid2);
3048
+ return storeUtils2.setModelConfiguration(storeKey, configuration);
3049
+ };
3050
+ const deleteConfiguration = (uid2) => {
3051
+ const storeKey = uidToStoreKey(uid2);
3052
+ return storeUtils2.deleteKey(storeKey);
3053
+ };
3054
+ const syncConfigurations = async () => {
3055
+ const models = getModels();
3056
+ const configurations = await storeUtils2.findByKey(
3057
+ `plugin_content_manager_configuration_${prefix}`
3058
+ );
3059
+ const updateConfiguration = async (uid2) => {
3060
+ const conf = configurations.find((conf2) => conf2.uid === uid2);
3061
+ return setConfiguration(uid2, await syncConfiguration(conf, models[uid2]));
3062
+ };
3063
+ const generateNewConfiguration = async (uid2) => {
3064
+ return setConfiguration(uid2, await createDefaultConfiguration(models[uid2]));
3065
+ };
3066
+ const currentUIDS = Object.keys(models);
3067
+ const DBUIDs = configurations.map(({ uid: uid2 }) => uid2);
3068
+ const contentTypesToUpdate = _.intersection(currentUIDS, DBUIDs);
3069
+ const contentTypesToAdd = _.difference(currentUIDS, DBUIDs);
3070
+ const contentTypesToDelete = _.difference(DBUIDs, currentUIDS);
3071
+ await Promise.all(contentTypesToDelete.map((uid2) => deleteConfiguration(uid2)));
3072
+ await Promise.all(contentTypesToAdd.map((uid2) => generateNewConfiguration(uid2)));
3073
+ await Promise.all(contentTypesToUpdate.map((uid2) => updateConfiguration(uid2)));
3074
+ };
3075
+ return {
3076
+ getConfiguration,
3077
+ setConfiguration,
3078
+ deleteConfiguration,
3079
+ syncConfigurations
3080
+ };
3081
+ };
3082
+ const STORE_KEY_PREFIX = "components";
3083
+ const configurationService$1 = createConfigurationService({
3084
+ storeUtils,
3085
+ isComponent: true,
3086
+ prefix: STORE_KEY_PREFIX,
3087
+ getModels() {
3088
+ const { toContentManagerModel } = getService$1("data-mapper");
3089
+ return fp.mapValues(toContentManagerModel, strapi.components);
3090
+ }
3091
+ });
3092
+ const components = ({ strapi: strapi2 }) => ({
3093
+ findAllComponents() {
3094
+ const { toContentManagerModel } = getService$1("data-mapper");
3095
+ return Object.values(strapi2.components).map(toContentManagerModel);
3096
+ },
3097
+ findComponent(uid2) {
3098
+ const { toContentManagerModel } = getService$1("data-mapper");
3099
+ const component = strapi2.components[uid2];
3100
+ return fp.isNil(component) ? component : toContentManagerModel(component);
3101
+ },
3102
+ async findConfiguration(component) {
3103
+ const configuration = await configurationService$1.getConfiguration(component.uid);
3104
+ return {
3105
+ uid: component.uid,
3106
+ category: component.category,
3107
+ ...configuration
3108
+ };
3109
+ },
3110
+ async updateConfiguration(component, newConfiguration) {
3111
+ await configurationService$1.setConfiguration(component.uid, newConfiguration);
3112
+ return this.findConfiguration(component);
3113
+ },
3114
+ async findComponentsConfigurations(model) {
3115
+ const componentsMap = {};
3116
+ const getComponentConfigurations = async (uid2) => {
3117
+ const component = this.findComponent(uid2);
3118
+ if (fp.has(uid2, componentsMap)) {
3119
+ return;
3120
+ }
3121
+ const componentConfiguration = await this.findConfiguration(component);
3122
+ const componentsConfigurations = await this.findComponentsConfigurations(component);
3123
+ Object.assign(componentsMap, {
3124
+ [uid2]: componentConfiguration,
3125
+ ...componentsConfigurations
3126
+ });
3127
+ };
3128
+ for (const key of Object.keys(model.attributes)) {
3129
+ const attribute = model.attributes[key];
3130
+ if (attribute.type === "component") {
3131
+ await getComponentConfigurations(attribute.component);
3132
+ }
3133
+ if (attribute.type === "dynamiczone") {
3134
+ for (const componentUid of attribute.components) {
3135
+ await getComponentConfigurations(componentUid);
3136
+ }
3137
+ }
3138
+ }
3139
+ return componentsMap;
3140
+ },
3141
+ syncConfigurations() {
3142
+ return configurationService$1.syncConfigurations();
3143
+ }
3144
+ });
3145
+ const configurationService = createConfigurationService({
3146
+ storeUtils,
3147
+ prefix: "content_types",
3148
+ getModels() {
3149
+ const { toContentManagerModel } = getService$1("data-mapper");
3150
+ return fp.mapValues(toContentManagerModel, strapi.contentTypes);
3151
+ }
3152
+ });
3153
+ const service = ({ strapi: strapi2 }) => ({
3154
+ findAllContentTypes() {
3155
+ const { toContentManagerModel } = getService$1("data-mapper");
3156
+ return Object.values(strapi2.contentTypes).map(toContentManagerModel);
3157
+ },
3158
+ findContentType(uid2) {
3159
+ const { toContentManagerModel } = getService$1("data-mapper");
3160
+ const contentType = strapi2.contentTypes[uid2];
3161
+ return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
3162
+ },
3163
+ findDisplayedContentTypes() {
3164
+ return this.findAllContentTypes().filter(
3165
+ // TODO
3166
+ // @ts-expect-error should be resolved from data-mapper types
3167
+ ({ isDisplayed }) => isDisplayed === true
3168
+ );
3169
+ },
3170
+ findContentTypesByKind(kind) {
3171
+ if (!kind) {
3172
+ return this.findAllContentTypes();
3173
+ }
3174
+ return this.findAllContentTypes().filter(strapiUtils.contentTypes.isKind(kind));
3175
+ },
3176
+ async findConfiguration(contentType) {
3177
+ const configuration = await configurationService.getConfiguration(contentType.uid);
3178
+ return {
3179
+ uid: contentType.uid,
3180
+ ...configuration
3181
+ };
3182
+ },
3183
+ async updateConfiguration(contentType, newConfiguration) {
3184
+ await configurationService.setConfiguration(contentType.uid, newConfiguration);
3185
+ return this.findConfiguration(contentType);
3186
+ },
3187
+ findComponentsConfigurations(contentType) {
3188
+ return getService$1("components").findComponentsConfigurations(contentType);
3189
+ },
3190
+ syncConfigurations() {
3191
+ return configurationService.syncConfigurations();
3192
+ }
3193
+ });
3194
+ const dtoFields = [
3195
+ "uid",
3196
+ "isDisplayed",
3197
+ "apiID",
3198
+ "kind",
3199
+ "category",
3200
+ "info",
3201
+ "options",
3202
+ "pluginOptions",
3203
+ "attributes",
3204
+ "pluginOptions"
3205
+ ];
3206
+ const dataMapper = () => ({
3207
+ toContentManagerModel(contentType) {
3208
+ return {
3209
+ ...contentType,
3210
+ apiID: contentType.modelName,
3211
+ isDisplayed: isVisible(contentType),
3212
+ attributes: {
3213
+ id: {
3214
+ type: "integer"
3215
+ },
3216
+ ...formatAttributes(contentType)
3217
+ }
3218
+ };
3219
+ },
3220
+ toDto: fp.pick(dtoFields)
3221
+ });
3222
+ const formatAttributes = (contentType) => {
3223
+ const { getVisibleAttributes, getTimestamps, getCreatorFields } = strapiUtils.contentTypes;
3224
+ return getVisibleAttributes(contentType).concat(getTimestamps(contentType)).concat(getCreatorFields(contentType)).reduce((acc, key) => {
3225
+ const attribute = contentType.attributes[key];
3226
+ if (attribute.type === "relation" && attribute.relation.toLowerCase().includes("morph")) {
3227
+ return acc;
3228
+ }
3229
+ acc[key] = formatAttribute(key, attribute);
3230
+ return acc;
3231
+ }, {});
3232
+ };
3233
+ const formatAttribute = (key, attribute) => {
3234
+ if (attribute.type === "relation") {
3235
+ return toRelation(attribute);
3236
+ }
3237
+ return attribute;
3238
+ };
3239
+ const toRelation = (attribute) => {
3240
+ return {
3241
+ ...attribute,
3242
+ type: "relation",
3243
+ targetModel: "target" in attribute ? attribute.target : void 0,
3244
+ relationType: attribute.relation
3245
+ };
3246
+ };
3247
+ const isVisible = (model) => fp.getOr(true, "pluginOptions.content-manager.visible", model) === true;
3248
+ const { ApplicationError: ApplicationError$1 } = strapiUtils.errors;
3249
+ const needsFullSize = {
3250
+ default: 12,
3251
+ isResizable: false
3252
+ };
3253
+ const smallSize = {
3254
+ default: 4,
3255
+ isResizable: true
3256
+ };
3257
+ const defaultSize = {
3258
+ default: 6,
3259
+ isResizable: true
3260
+ };
3261
+ const fieldSizes = {
3262
+ // Full row and not resizable
3263
+ dynamiczone: needsFullSize,
3264
+ component: needsFullSize,
3265
+ json: needsFullSize,
3266
+ richtext: needsFullSize,
3267
+ blocks: needsFullSize,
3268
+ // Small and resizable
3269
+ checkbox: smallSize,
3270
+ boolean: smallSize,
3271
+ date: smallSize,
3272
+ time: smallSize,
3273
+ biginteger: smallSize,
3274
+ decimal: smallSize,
3275
+ float: smallSize,
3276
+ integer: smallSize,
3277
+ number: smallSize,
3278
+ // Medium and resizable
3279
+ datetime: defaultSize,
3280
+ email: defaultSize,
3281
+ enumeration: defaultSize,
3282
+ media: defaultSize,
3283
+ password: defaultSize,
3284
+ relation: defaultSize,
3285
+ string: defaultSize,
3286
+ text: defaultSize,
3287
+ timestamp: defaultSize,
3288
+ uid: defaultSize
3289
+ };
3290
+ const createFieldSizesService = ({ strapi: strapi2 }) => {
3291
+ const fieldSizesService = {
3292
+ getAllFieldSizes() {
3293
+ return fieldSizes;
3294
+ },
3295
+ hasFieldSize(type) {
3296
+ return !!fieldSizes[type];
3297
+ },
3298
+ getFieldSize(type) {
3299
+ if (!type) {
3300
+ throw new ApplicationError$1("The type is required");
3301
+ }
3302
+ const fieldSize = fieldSizes[type];
3303
+ if (!fieldSize) {
3304
+ throw new ApplicationError$1(`Could not find field size for type ${type}`);
3305
+ }
3306
+ return fieldSize;
3307
+ },
3308
+ setFieldSize(type, size) {
3309
+ if (!type) {
3310
+ throw new ApplicationError$1("The type is required");
3311
+ }
3312
+ if (!size) {
3313
+ throw new ApplicationError$1("The size is required");
3314
+ }
3315
+ fieldSizes[type] = size;
3316
+ },
3317
+ setCustomFieldInputSizes() {
3318
+ const customFields = strapi2.get("custom-fields").getAll();
3319
+ Object.entries(customFields).forEach(([uid2, customField]) => {
3320
+ if (customField.inputSize) {
3321
+ fieldSizesService.setFieldSize(uid2, customField.inputSize);
3322
+ }
3323
+ });
3324
+ }
3325
+ };
3326
+ return fieldSizesService;
3327
+ };
3328
+ const { getRelationalFields } = strapiUtils.relations;
3329
+ const metrics = ({ strapi: strapi2 }) => {
3330
+ const sendDidConfigureListView = async (contentType, configuration) => {
3331
+ const displayedFields = fp.prop("length", configuration.layouts.list);
3332
+ const relationalFields = getRelationalFields(contentType);
3333
+ const displayedRelationalFields = fp.intersection(
3334
+ relationalFields,
3335
+ configuration.layouts.list
3336
+ ).length;
3337
+ const data = {
3338
+ eventProperties: { containsRelationalFields: !!displayedRelationalFields }
3339
+ };
3340
+ if (data.eventProperties.containsRelationalFields) {
3341
+ Object.assign(data.eventProperties, {
3342
+ displayedFields,
3343
+ displayedRelationalFields
3344
+ });
3345
+ }
3346
+ try {
3347
+ await strapi2.telemetry.send("didConfigureListView", data);
3348
+ } catch (e) {
3349
+ }
3350
+ };
3351
+ return {
3352
+ sendDidConfigureListView
3353
+ };
3354
+ };
3355
+ const ACTIONS = {
3356
+ read: "plugin::content-manager.explorer.read",
3357
+ create: "plugin::content-manager.explorer.create",
3358
+ update: "plugin::content-manager.explorer.update",
3359
+ delete: "plugin::content-manager.explorer.delete",
3360
+ publish: "plugin::content-manager.explorer.publish",
3361
+ unpublish: "plugin::content-manager.explorer.publish",
3362
+ discard: "plugin::content-manager.explorer.update"
3363
+ };
3364
+ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
3365
+ const permissionsManager = strapi2.service("admin::permission").createPermissionsManager({
3366
+ ability: userAbility,
3367
+ model
3368
+ });
3369
+ const toSubject = (entity) => entity ? permissionsManager.toSubject(entity, model) : model;
3370
+ const can = (action, entity, field) => {
3371
+ return userAbility.can(action, toSubject(entity), field);
3372
+ };
3373
+ const cannot = (action, entity, field) => {
3374
+ return userAbility.cannot(action, toSubject(entity), field);
3375
+ };
3376
+ const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
3377
+ return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
3378
+ };
3379
+ const sanitizeQuery = (query, { action = ACTIONS.read } = {}) => {
3380
+ return permissionsManager.sanitizeQuery(query, { subject: model, action });
3381
+ };
3382
+ const sanitizeInput = (action, data, entity) => {
3383
+ return permissionsManager.sanitizeInput(data, {
3384
+ subject: entity ? toSubject(entity) : model,
3385
+ action
3386
+ });
3387
+ };
3388
+ const validateQuery = (query, { action = ACTIONS.read } = {}) => {
3389
+ return permissionsManager.validateQuery(query, { subject: model, action });
3390
+ };
3391
+ const validateInput = (action, data, entity) => {
3392
+ return permissionsManager.validateInput(data, {
3393
+ subject: entity ? toSubject(entity) : model,
3394
+ action
3395
+ });
3396
+ };
3397
+ const sanitizeCreateInput = (data) => sanitizeInput(ACTIONS.create, data);
3398
+ const sanitizeUpdateInput = (entity) => (data) => sanitizeInput(ACTIONS.update, data, entity);
3399
+ const buildPermissionQuery = (query, action = {}) => {
3400
+ return permissionsManager.addPermissionsQueryTo(query, action);
3401
+ };
3402
+ const sanitizedQuery = (query, action = {}) => {
3403
+ return strapiUtils.async.pipe(
3404
+ (q) => sanitizeQuery(q, action),
3405
+ (q) => buildPermissionQuery(q, action)
3406
+ )(query);
3407
+ };
3408
+ Object.keys(ACTIONS).forEach((action) => {
3409
+ sanitizedQuery[action] = (query) => sanitizedQuery(query, ACTIONS[action]);
3410
+ });
3411
+ Object.keys(ACTIONS).forEach((action) => {
3412
+ can[action] = (...args) => can(ACTIONS[action], ...args);
3413
+ cannot[action] = (...args) => cannot(ACTIONS[action], ...args);
3414
+ });
3415
+ return {
3416
+ // Permission utils
3417
+ can,
3418
+ // check if you have the permission
3419
+ cannot,
3420
+ // check if you don't have the permission
3421
+ // Sanitizers
3422
+ sanitizeOutput,
3423
+ sanitizeQuery,
3424
+ sanitizeCreateInput,
3425
+ sanitizeUpdateInput,
3426
+ // Validators
3427
+ validateQuery,
3428
+ validateInput,
3429
+ // Queries Builder
3430
+ sanitizedQuery
3431
+ };
3432
+ };
3433
+ const permissionChecker = ({ strapi: strapi2 }) => ({
3434
+ create: createPermissionChecker(strapi2)
3435
+ });
3436
+ const permission = ({ strapi: strapi2 }) => ({
3437
+ canConfigureContentType({
3438
+ userAbility,
3439
+ contentType
3440
+ }) {
3441
+ const action = strapiUtils.contentTypes.isSingleType(contentType) ? "plugin::content-manager.single-types.configure-view" : "plugin::content-manager.collection-types.configure-view";
3442
+ return userAbility.can(action);
3443
+ },
3444
+ async registerPermissions() {
3445
+ const displayedContentTypes = getService$1("content-types").findDisplayedContentTypes();
3446
+ const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
3447
+ const actions = [
3448
+ {
3449
+ section: "contentTypes",
3450
+ displayName: "Create",
3451
+ uid: "explorer.create",
3452
+ pluginName: "content-manager",
3453
+ subjects: contentTypesUids,
3454
+ options: {
3455
+ applyToProperties: ["fields"]
3456
+ }
3457
+ },
3458
+ {
3459
+ section: "contentTypes",
3460
+ displayName: "Read",
3461
+ uid: "explorer.read",
3462
+ pluginName: "content-manager",
3463
+ subjects: contentTypesUids,
3464
+ options: {
3465
+ applyToProperties: ["fields"]
3466
+ }
3467
+ },
3468
+ {
3469
+ section: "contentTypes",
3470
+ displayName: "Update",
3471
+ uid: "explorer.update",
3472
+ pluginName: "content-manager",
3473
+ subjects: contentTypesUids,
3474
+ options: {
3475
+ applyToProperties: ["fields"]
3476
+ }
3477
+ },
3478
+ {
3479
+ section: "contentTypes",
3480
+ displayName: "Delete",
3481
+ uid: "explorer.delete",
3482
+ pluginName: "content-manager",
3483
+ subjects: contentTypesUids
3484
+ },
3485
+ {
3486
+ section: "contentTypes",
3487
+ displayName: "Publish",
3488
+ uid: "explorer.publish",
3489
+ pluginName: "content-manager",
3490
+ subjects: contentTypesUids
3491
+ },
3492
+ {
3493
+ section: "plugins",
3494
+ displayName: "Configure view",
3495
+ uid: "single-types.configure-view",
3496
+ subCategory: "single types",
3497
+ pluginName: "content-manager"
3498
+ },
3499
+ {
3500
+ section: "plugins",
3501
+ displayName: "Configure view",
3502
+ uid: "collection-types.configure-view",
3503
+ subCategory: "collection types",
3504
+ pluginName: "content-manager"
3505
+ },
3506
+ {
3507
+ section: "plugins",
3508
+ displayName: "Configure Layout",
3509
+ uid: "components.configure-layout",
3510
+ subCategory: "components",
3511
+ pluginName: "content-manager"
3512
+ }
3513
+ ];
3514
+ await strapi2.service("admin::permission").actionProvider.registerMany(actions);
3515
+ }
3516
+ });
3517
+ const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils__default.default.contentTypes;
3518
+ const { isAnyToMany } = strapiUtils__default.default.relations;
3519
+ const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils__default.default.contentTypes.constants;
3520
+ const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
3521
+ const isMedia = fp.propEq("type", "media");
3522
+ const isRelation = fp.propEq("type", "relation");
3523
+ const isComponent = fp.propEq("type", "component");
3524
+ const isDynamicZone = fp.propEq("type", "dynamiczone");
3525
+ function getPopulateForRelation(attribute, model, attributeName, { countMany, countOne, initialPopulate }) {
3526
+ const isManyRelation = isAnyToMany(attribute);
3527
+ if (initialPopulate) {
3528
+ return initialPopulate;
3529
+ }
3530
+ if (!isVisibleAttribute$1(model, attributeName)) {
3531
+ return true;
3532
+ }
3533
+ if (isManyRelation && countMany || !isManyRelation && countOne) {
3534
+ return { count: true };
3535
+ }
3536
+ return true;
3537
+ }
3538
+ function getPopulateForDZ(attribute, options, level) {
3539
+ const populatedComponents = (attribute.components || []).reduce(
3540
+ (acc, componentUID) => ({
3541
+ ...acc,
3542
+ [componentUID]: {
3543
+ populate: getDeepPopulate(componentUID, options, level + 1)
3544
+ }
3545
+ }),
3546
+ {}
3547
+ );
3548
+ return { on: populatedComponents };
3549
+ }
3550
+ function getPopulateFor(attributeName, model, options, level) {
3551
+ const attribute = model.attributes[attributeName];
3552
+ switch (attribute.type) {
3553
+ case "relation":
3554
+ return {
3555
+ [attributeName]: getPopulateForRelation(attribute, model, attributeName, options)
3556
+ };
3557
+ case "component":
3558
+ return {
3559
+ [attributeName]: {
3560
+ populate: getDeepPopulate(attribute.component, options, level + 1)
3561
+ }
3562
+ };
3563
+ case "media":
3564
+ return {
3565
+ [attributeName]: {
3566
+ populate: {
3567
+ folder: true
3568
+ }
3569
+ }
3570
+ };
3571
+ case "dynamiczone":
3572
+ return {
3573
+ [attributeName]: getPopulateForDZ(attribute, options, level)
3574
+ };
3575
+ default:
3576
+ return {};
3577
+ }
3578
+ }
3579
+ const getDeepPopulate = (uid2, {
3580
+ initialPopulate = {},
3581
+ countMany = false,
3582
+ countOne = false,
3583
+ maxLevel = Infinity
3584
+ } = {}, level = 1) => {
3585
+ if (level > maxLevel) {
3586
+ return {};
3587
+ }
3588
+ const model = strapi.getModel(uid2);
3589
+ return Object.keys(model.attributes).reduce(
3590
+ (populateAcc, attributeName) => fp.merge(
3591
+ populateAcc,
3592
+ getPopulateFor(
3593
+ attributeName,
3594
+ model,
3595
+ {
3596
+ // @ts-expect-error - improve types
3597
+ initialPopulate: initialPopulate?.[attributeName],
3598
+ countMany,
3599
+ countOne,
3600
+ maxLevel
3601
+ },
3602
+ level
3603
+ )
3604
+ ),
3605
+ {}
3606
+ );
3607
+ };
3608
+ const getDeepPopulateDraftCount = (uid2) => {
3609
+ const model = strapi.getModel(uid2);
3610
+ let hasRelations = false;
3611
+ const populate = Object.keys(model.attributes).reduce((populateAcc, attributeName) => {
3612
+ const attribute = model.attributes[attributeName];
3613
+ switch (attribute.type) {
3614
+ case "relation": {
3615
+ if (isVisibleAttribute$1(model, attributeName)) {
3616
+ populateAcc[attributeName] = {
3617
+ count: true,
3618
+ filters: { [PUBLISHED_AT_ATTRIBUTE$1]: { $null: true } }
3619
+ };
3620
+ hasRelations = true;
3621
+ }
3622
+ break;
3623
+ }
3624
+ case "component": {
3625
+ const { populate: populate2, hasRelations: childHasRelations } = getDeepPopulateDraftCount(
3626
+ attribute.component
3627
+ );
3628
+ if (childHasRelations) {
3629
+ populateAcc[attributeName] = { populate: populate2 };
3630
+ hasRelations = true;
3631
+ }
3632
+ break;
3633
+ }
3634
+ case "dynamiczone": {
3635
+ const dzPopulate = (attribute.components || []).reduce((acc, componentUID) => {
3636
+ const { populate: populate2, hasRelations: childHasRelations } = getDeepPopulateDraftCount(componentUID);
3637
+ if (childHasRelations) {
3638
+ hasRelations = true;
3639
+ return fp.merge(acc, populate2);
3640
+ }
3641
+ return acc;
3642
+ }, {});
3643
+ if (!fp.isEmpty(dzPopulate)) {
3644
+ populateAcc[attributeName] = { populate: dzPopulate };
3645
+ }
3646
+ break;
3647
+ }
3648
+ }
3649
+ return populateAcc;
3650
+ }, {});
3651
+ return { populate, hasRelations };
3652
+ };
3653
+ const getQueryPopulate = async (uid2, query) => {
3654
+ let populateQuery = {};
3655
+ await strapiUtils__default.default.traverse.traverseQueryFilters(
3656
+ /**
3657
+ *
3658
+ * @param {Object} param0
3659
+ * @param {string} param0.key - Attribute name
3660
+ * @param {Object} param0.attribute - Attribute definition
3661
+ * @param {string} param0.path - Content Type path to the attribute
3662
+ * @returns
3663
+ */
3664
+ ({ attribute, path }) => {
3665
+ if (!attribute || isDynamicZone(attribute) || isMorphToRelation(attribute)) {
3666
+ return;
3667
+ }
3668
+ if (isRelation(attribute) || isMedia(attribute) || isComponent(attribute)) {
3669
+ const populatePath = path.attribute.replace(/\./g, ".populate.");
3670
+ populateQuery = fp.set(populatePath, {}, populateQuery);
3671
+ }
3672
+ },
3673
+ { schema: strapi.getModel(uid2), getModel: strapi.getModel.bind(strapi) },
3674
+ query
3675
+ );
3676
+ return populateQuery;
3677
+ };
3678
+ const buildDeepPopulate = (uid2) => {
3679
+ return getService$1("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
3680
+ };
3681
+ const populateBuilder = (uid2) => {
3682
+ let getInitialPopulate = async () => {
3683
+ return void 0;
3684
+ };
3685
+ const deepPopulateOptions = {
3686
+ countMany: false,
3687
+ countOne: false,
3688
+ maxLevel: -1
3689
+ };
3690
+ const builder = {
3691
+ /**
3692
+ * Populates all attribute fields present in a query.
3693
+ * @param query - Strapi query object
3694
+ */
3695
+ populateFromQuery(query) {
3696
+ getInitialPopulate = async () => getQueryPopulate(uid2, query);
3697
+ return builder;
3698
+ },
3699
+ /**
3700
+ * Populate relations as count.
3701
+ * @param [options]
3702
+ * @param [options.toMany] - Populate XtoMany relations as count if true.
3703
+ * @param [options.toOne] - Populate XtoOne relations as count if true.
3704
+ */
3705
+ countRelations({ toMany, toOne } = { toMany: true, toOne: true }) {
3706
+ if (!fp.isNil(toMany)) {
3707
+ deepPopulateOptions.countMany = toMany;
3708
+ }
3709
+ if (!fp.isNil(toOne)) {
3710
+ deepPopulateOptions.countOne = toOne;
3711
+ }
3712
+ return builder;
3713
+ },
3714
+ /**
3715
+ * Populate relations deeply, up to a certain level.
3716
+ * @param [level=Infinity] - Max level of nested populate.
3717
+ */
3718
+ populateDeep(level = Infinity) {
3719
+ deepPopulateOptions.maxLevel = level;
3720
+ return builder;
3721
+ },
3722
+ /**
3723
+ * Construct the populate object based on the builder options.
3724
+ * @returns Populate object
3725
+ */
3726
+ async build() {
3727
+ const initialPopulate = await getInitialPopulate();
3728
+ if (deepPopulateOptions.maxLevel === -1) {
3729
+ return initialPopulate;
3730
+ }
3731
+ return getDeepPopulate(uid2, { ...deepPopulateOptions, initialPopulate });
3732
+ }
3733
+ };
3734
+ return builder;
3735
+ };
3736
+ const populateBuilder$1 = () => populateBuilder;
3737
+ const uid = ({ strapi: strapi2 }) => ({
3738
+ async generateUIDField({
3739
+ contentTypeUID,
3740
+ field,
3741
+ data,
3742
+ locale
3743
+ }) {
3744
+ const contentType = strapi2.contentTypes[contentTypeUID];
3745
+ const { attributes } = contentType;
3746
+ const {
3747
+ targetField,
3748
+ default: defaultValue,
3749
+ options
3750
+ } = attributes[field];
3751
+ const targetValue = ___default.default.get(data, targetField);
3752
+ if (!___default.default.isEmpty(targetValue)) {
3753
+ return this.findUniqueUID({
3754
+ contentTypeUID,
3755
+ field,
3756
+ value: slugify__default.default(targetValue, options),
3757
+ locale
3758
+ });
3759
+ }
3760
+ return this.findUniqueUID({
3761
+ contentTypeUID,
3762
+ field,
3763
+ value: slugify__default.default(
3764
+ ___default.default.isFunction(defaultValue) ? defaultValue() : defaultValue || contentType.modelName,
3765
+ options
3766
+ ),
3767
+ locale
3768
+ });
3769
+ },
3770
+ async findUniqueUID({
3771
+ contentTypeUID,
3772
+ field,
3773
+ value,
3774
+ locale
3775
+ }) {
3776
+ const foundDocuments = await strapi2.documents(contentTypeUID).findMany({
3777
+ filters: {
3778
+ [field]: { $startsWith: value }
3779
+ },
3780
+ locale,
3781
+ // TODO: Check UX. When modifying an entry, it only makes sense to check for collisions with other drafts
3782
+ // However, when publishing this "available" UID might collide with another published entry
3783
+ status: "draft"
3784
+ });
3785
+ if (!foundDocuments || foundDocuments.length === 0) {
3786
+ return value;
3787
+ }
3788
+ let possibleCollisions;
3789
+ if (!Array.isArray(foundDocuments)) {
3790
+ possibleCollisions = [foundDocuments[field]];
3791
+ } else {
3792
+ possibleCollisions = foundDocuments.map((doc) => doc[field]);
3793
+ }
3794
+ if (!possibleCollisions.includes(value)) {
3795
+ return value;
3796
+ }
3797
+ let i = 1;
3798
+ let tmpUId = `${value}-${i}`;
3799
+ while (possibleCollisions.includes(tmpUId)) {
3800
+ i += 1;
3801
+ tmpUId = `${value}-${i}`;
3802
+ }
3803
+ return tmpUId;
3804
+ },
3805
+ async checkUIDAvailability({
3806
+ contentTypeUID,
3807
+ field,
3808
+ value,
3809
+ locale
3810
+ }) {
3811
+ const documentCount = await strapi2.documents(contentTypeUID).count({
3812
+ filters: {
3813
+ [field]: value
3814
+ },
3815
+ locale,
3816
+ // TODO: Check UX. When modifying an entry, it only makes sense to check for collisions with other drafts
3817
+ // However, when publishing this "available" UID might collide with another published entry
3818
+ status: "draft"
3819
+ });
3820
+ if (documentCount && documentCount > 0) {
3821
+ return false;
3822
+ }
3823
+ return true;
3824
+ }
3825
+ });
3826
+ const AVAILABLE_STATUS_FIELDS = [
3827
+ "id",
3828
+ "locale",
3829
+ "updatedAt",
3830
+ "createdAt",
3831
+ "publishedAt",
3832
+ "createdBy",
3833
+ "updatedBy",
3834
+ "status"
3835
+ ];
3836
+ const AVAILABLE_LOCALES_FIELDS = ["id", "locale", "updatedAt", "createdAt", "status"];
3837
+ const CONTENT_MANAGER_STATUS = {
3838
+ PUBLISHED: "published",
3839
+ DRAFT: "draft",
3840
+ MODIFIED: "modified"
3841
+ };
3842
+ const areDatesEqual = (date1, date2, threshold) => {
3843
+ if (!date1 || !date2) {
3844
+ return false;
3845
+ }
3846
+ const time1 = new Date(date1).getTime();
3847
+ const time2 = new Date(date2).getTime();
3848
+ const difference = Math.abs(time1 - time2);
3849
+ return difference <= threshold;
3850
+ };
3851
+ const documentMetadata = ({ strapi: strapi2 }) => ({
3852
+ /**
3853
+ * Returns available locales of a document for the current status
3854
+ */
3855
+ getAvailableLocales(uid2, version, allVersions) {
3856
+ const versionsByLocale = fp.groupBy("locale", allVersions);
3857
+ delete versionsByLocale[version.locale];
3858
+ return Object.values(versionsByLocale).map((localeVersions) => {
3859
+ if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2))) {
3860
+ return fp.pick(AVAILABLE_LOCALES_FIELDS, localeVersions[0]);
3861
+ }
3862
+ const draftVersion = localeVersions.find((v) => v.publishedAt === null);
3863
+ const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
3864
+ if (!draftVersion)
3865
+ return;
3866
+ return {
3867
+ ...fp.pick(AVAILABLE_LOCALES_FIELDS, draftVersion),
3868
+ status: this.getStatus(draftVersion, otherVersions)
3869
+ };
3870
+ }).filter(Boolean);
3871
+ },
3872
+ /**
3873
+ * Returns available status of a document for the current locale
3874
+ */
3875
+ getAvailableStatus(version, allVersions) {
3876
+ const status = version.publishedAt !== null ? CONTENT_MANAGER_STATUS.DRAFT : CONTENT_MANAGER_STATUS.PUBLISHED;
3877
+ const availableStatus = allVersions.find((v) => {
3878
+ const matchLocale = v.locale === version.locale;
3879
+ const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
3880
+ return matchLocale && matchStatus;
3881
+ });
3882
+ if (!availableStatus)
3883
+ return availableStatus;
3884
+ return fp.pick(AVAILABLE_STATUS_FIELDS, availableStatus);
3885
+ },
3886
+ /**
3887
+ * Get the available status of many documents, useful for batch operations
3888
+ * @param uid
3889
+ * @param documents
3890
+ * @returns
3891
+ */
3892
+ async getManyAvailableStatus(uid2, documents) {
3893
+ if (!documents.length)
3894
+ return [];
3895
+ const status = documents[0].publishedAt !== null ? "published" : "draft";
3896
+ const locale = documents[0]?.locale;
3897
+ const otherStatus = status === "published" ? "draft" : "published";
3898
+ return strapi2.documents(uid2).findMany({
3899
+ filters: {
3900
+ documentId: { $in: documents.map((d) => d.documentId).filter(Boolean) }
3901
+ },
3902
+ status: otherStatus,
3903
+ locale,
3904
+ fields: ["documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
3905
+ });
3906
+ },
3907
+ getStatus(version, otherDocumentStatuses) {
3908
+ const isDraft = version.publishedAt === null;
3909
+ if (!otherDocumentStatuses?.length) {
3910
+ return isDraft ? CONTENT_MANAGER_STATUS.DRAFT : CONTENT_MANAGER_STATUS.PUBLISHED;
3911
+ }
3912
+ if (isDraft) {
3913
+ const publishedVersion = otherDocumentStatuses?.find((d) => d.publishedAt !== null);
3914
+ if (!publishedVersion) {
3915
+ return CONTENT_MANAGER_STATUS.DRAFT;
3916
+ }
3917
+ }
3918
+ if (areDatesEqual(version.updatedAt, otherDocumentStatuses.at(0)?.updatedAt, 500)) {
3919
+ return CONTENT_MANAGER_STATUS.PUBLISHED;
3920
+ }
3921
+ return CONTENT_MANAGER_STATUS.MODIFIED;
3922
+ },
3923
+ async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
3924
+ const versions = await strapi2.db.query(uid2).findMany({
3925
+ where: { documentId: version.documentId },
3926
+ select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
3927
+ populate: {
3928
+ createdBy: {
3929
+ select: ["id", "firstname", "lastname", "email"]
3930
+ },
3931
+ updatedBy: {
3932
+ select: ["id", "firstname", "lastname", "email"]
3933
+ }
3934
+ }
3935
+ });
3936
+ const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
3937
+ const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
3938
+ return {
3939
+ availableLocales: availableLocalesResult,
3940
+ availableStatus: availableStatusResult ? [availableStatusResult] : []
3941
+ };
3942
+ },
3943
+ /**
3944
+ * Returns associated metadata of a document:
3945
+ * - Available locales of the document for the current status
3946
+ * - Available status of the document for the current locale
3947
+ */
3948
+ async formatDocumentWithMetadata(uid2, document, opts = {}) {
3949
+ if (!document)
3950
+ return document;
3951
+ const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
3952
+ if (!hasDraftAndPublish) {
3953
+ opts.availableStatus = false;
3954
+ }
3955
+ const meta = await this.getMetadata(uid2, document, opts);
3956
+ return {
3957
+ data: {
3958
+ ...document,
3959
+ // Add status to the document only if draft and publish is enabled
3960
+ status: hasDraftAndPublish ? this.getStatus(document, meta.availableStatus) : void 0
3961
+ },
3962
+ meta
3963
+ };
3964
+ }
3965
+ });
3966
+ const { isVisibleAttribute } = strapiUtils__default.default.contentTypes;
3967
+ const sumDraftCounts = (entity, uid2) => {
3968
+ const model = strapi.getModel(uid2);
3969
+ return Object.keys(model.attributes).reduce((sum, attributeName) => {
3970
+ const attribute = model.attributes[attributeName];
3971
+ const value = entity[attributeName];
3972
+ if (!value) {
3973
+ return sum;
3974
+ }
3975
+ switch (attribute.type) {
3976
+ case "relation": {
3977
+ if (isVisibleAttribute(model, attributeName)) {
3978
+ return sum + value.count;
3979
+ }
3980
+ return sum;
3981
+ }
3982
+ case "component": {
3983
+ const compoSum = fp.castArray(value).reduce((acc, componentValue) => {
3984
+ return acc + sumDraftCounts(componentValue, attribute.component);
3985
+ }, 0);
3986
+ return sum + compoSum;
3987
+ }
3988
+ case "dynamiczone": {
3989
+ const dzSum = value.reduce((acc, componentValue) => {
3990
+ return acc + sumDraftCounts(componentValue, componentValue.__component);
3991
+ }, 0);
3992
+ return sum + dzSum;
3993
+ }
3994
+ default:
3995
+ return sum;
3996
+ }
3997
+ }, 0);
3998
+ };
3999
+ const { ApplicationError } = strapiUtils.errors;
4000
+ const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
4001
+ const { PUBLISHED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
4002
+ const omitPublishedAtField = fp.omit(PUBLISHED_AT_ATTRIBUTE);
4003
+ const omitIdField = fp.omit("id");
4004
+ const emitEvent = async (uid2, event, document) => {
4005
+ const modelDef = strapi.getModel(uid2);
4006
+ const sanitizedDocument = await strapiUtils.sanitize.sanitizers.defaultSanitizeOutput(
4007
+ {
4008
+ schema: modelDef,
4009
+ getModel(uid22) {
4010
+ return strapi.getModel(uid22);
4011
+ }
4012
+ },
4013
+ document
4014
+ );
4015
+ strapi.eventHub.emit(event, {
4016
+ model: modelDef.modelName,
4017
+ entry: sanitizedDocument
4018
+ });
4019
+ };
4020
+ const documentManager = ({ strapi: strapi2 }) => {
4021
+ return {
4022
+ async findOne(id, uid2, opts = {}) {
4023
+ return strapi2.documents(uid2).findOne({ ...opts, documentId: id });
4024
+ },
4025
+ /**
4026
+ * Find multiple (or all) locales for a document
4027
+ */
4028
+ async findLocales(id, uid2, opts) {
4029
+ const where = {};
4030
+ if (id) {
4031
+ where.documentId = id;
4032
+ }
4033
+ if (Array.isArray(opts.locale)) {
4034
+ where.locale = { $in: opts.locale };
4035
+ } else if (opts.locale && opts.locale !== "*") {
4036
+ where.locale = opts.locale;
4037
+ }
4038
+ return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
4039
+ },
4040
+ async findMany(opts, uid2) {
4041
+ const params = { ...opts, populate: getDeepPopulate(uid2) };
4042
+ return strapi2.documents(uid2).findMany(params);
4043
+ },
4044
+ async findPage(opts, uid2) {
4045
+ const page = Number(opts?.page) || 1;
4046
+ const pageSize = Number(opts?.pageSize) || 10;
4047
+ const [documents, total = 0] = await Promise.all([
4048
+ strapi2.documents(uid2).findMany(opts),
4049
+ strapi2.documents(uid2).count(opts)
4050
+ ]);
4051
+ return {
4052
+ results: documents,
4053
+ pagination: {
4054
+ page,
4055
+ pageSize,
4056
+ pageCount: Math.ceil(total / pageSize),
4057
+ total
4058
+ }
4059
+ };
4060
+ },
4061
+ async create(uid2, opts = {}) {
4062
+ const populate = opts.populate ?? await buildDeepPopulate(uid2);
4063
+ const params = { ...opts, status: "draft", populate };
4064
+ return strapi2.documents(uid2).create(params);
4065
+ },
4066
+ async update(id, uid2, opts = {}) {
4067
+ const publishData = fp.pipe(omitPublishedAtField, omitIdField)(opts.data || {});
4068
+ const populate = opts.populate ?? await buildDeepPopulate(uid2);
4069
+ const params = { ...opts, data: publishData, populate, status: "draft" };
4070
+ return strapi2.documents(uid2).update({ ...params, documentId: id });
4071
+ },
4072
+ async clone(id, body, uid2) {
4073
+ const populate = await buildDeepPopulate(uid2);
4074
+ const params = {
4075
+ data: {
4076
+ ...omitIdField(body),
4077
+ [PUBLISHED_AT_ATTRIBUTE]: null
4078
+ },
4079
+ populate
4080
+ };
4081
+ return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
4082
+ },
4083
+ /**
4084
+ * Check if a document exists
4085
+ */
4086
+ async exists(uid2, id) {
4087
+ if (id) {
4088
+ const count2 = await strapi2.db.query(uid2).count({ where: { documentId: id } });
4089
+ return count2 > 0;
4090
+ }
4091
+ const count = await strapi2.db.query(uid2).count();
4092
+ return count > 0;
4093
+ },
4094
+ async delete(id, uid2, opts = {}) {
4095
+ const populate = await buildDeepPopulate(uid2);
4096
+ await strapi2.documents(uid2).delete({
4097
+ ...opts,
4098
+ documentId: id,
4099
+ populate
4100
+ });
4101
+ return {};
4102
+ },
4103
+ // FIXME: handle relations
4104
+ async deleteMany(opts, uid2) {
4105
+ const docs = await strapi2.documents(uid2).findMany(opts);
4106
+ for (const doc of docs) {
4107
+ await strapi2.documents(uid2).delete({ documentId: doc.documentId });
4108
+ }
4109
+ return { count: docs.length };
4110
+ },
4111
+ async publish(id, uid2, opts = {}) {
4112
+ const populate = await buildDeepPopulate(uid2);
4113
+ const params = { ...opts, populate };
4114
+ return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries.at(0));
4115
+ },
4116
+ async publishMany(entities, uid2) {
4117
+ if (!entities.length) {
4118
+ return null;
4119
+ }
4120
+ await Promise.all(
4121
+ entities.map((document) => {
4122
+ return strapi2.entityValidator.validateEntityCreation(
4123
+ strapi2.getModel(uid2),
4124
+ document,
4125
+ void 0,
4126
+ // @ts-expect-error - FIXME: entity here is unnecessary
4127
+ document
4128
+ );
4129
+ })
4130
+ );
4131
+ const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
4132
+ const filters = { id: { $in: entitiesToPublish } };
4133
+ const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
4134
+ const populate = await buildDeepPopulate(uid2);
4135
+ const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
4136
+ where: filters,
4137
+ data
4138
+ });
4139
+ const publishedEntities = await strapi2.db.query(uid2).findMany({
4140
+ where: filters,
4141
+ populate
4142
+ });
4143
+ await Promise.all(
4144
+ publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
4145
+ );
4146
+ return publishedEntitiesCount;
4147
+ },
4148
+ async unpublishMany(documents, uid2) {
4149
+ if (!documents.length) {
4150
+ return null;
4151
+ }
4152
+ const entitiesToUnpublish = documents.filter((doc) => doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
4153
+ const filters = { id: { $in: entitiesToUnpublish } };
4154
+ const data = { [PUBLISHED_AT_ATTRIBUTE]: null };
4155
+ const populate = await buildDeepPopulate(uid2);
4156
+ const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
4157
+ where: filters,
4158
+ data
4159
+ });
4160
+ const unpublishedEntities = await strapi2.db.query(uid2).findMany({
4161
+ where: filters,
4162
+ populate
4163
+ });
4164
+ await Promise.all(
4165
+ unpublishedEntities.map((doc) => emitEvent(uid2, ENTRY_UNPUBLISH, doc))
4166
+ );
4167
+ return unpublishedEntitiesCount;
4168
+ },
4169
+ async unpublish(id, uid2, opts = {}) {
4170
+ const populate = await buildDeepPopulate(uid2);
4171
+ const params = { ...opts, populate };
4172
+ return strapi2.documents(uid2).unpublish({ ...params, documentId: id }).then((result) => result?.entries.at(0));
4173
+ },
4174
+ async discardDraft(id, uid2, opts = {}) {
4175
+ const populate = await buildDeepPopulate(uid2);
4176
+ const params = { ...opts, populate };
4177
+ return strapi2.documents(uid2).discardDraft({ ...params, documentId: id }).then((result) => result?.entries.at(0));
4178
+ },
4179
+ async countDraftRelations(id, uid2, locale) {
4180
+ const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
4181
+ if (!hasRelations) {
4182
+ return 0;
4183
+ }
4184
+ const document = await strapi2.documents(uid2).findOne({ documentId: id, populate, locale });
4185
+ if (!document) {
4186
+ throw new ApplicationError(
4187
+ `Unable to count draft relations, document with id ${id} and locale ${locale} not found`
4188
+ );
4189
+ }
4190
+ return sumDraftCounts(document, uid2);
4191
+ },
4192
+ async countManyEntriesDraftRelations(ids, uid2, locale) {
4193
+ const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
4194
+ if (!hasRelations) {
4195
+ return 0;
4196
+ }
4197
+ const entities = await strapi2.db.query(uid2).findMany({
4198
+ populate,
4199
+ where: {
4200
+ id: { $in: ids },
4201
+ ...locale ? { locale } : {}
4202
+ }
4203
+ });
4204
+ const totalNumberDraftRelations = entities.reduce(
4205
+ (count, entity) => sumDraftCounts(entity, uid2) + count,
4206
+ 0
4207
+ );
4208
+ return totalNumberDraftRelations;
4209
+ }
4210
+ };
4211
+ };
4212
+ const services = {
4213
+ components,
4214
+ "content-types": service,
4215
+ "data-mapper": dataMapper,
4216
+ "document-metadata": documentMetadata,
4217
+ "document-manager": documentManager,
4218
+ "field-sizes": createFieldSizesService,
4219
+ metrics,
4220
+ "permission-checker": permissionChecker,
4221
+ permission,
4222
+ "populate-builder": populateBuilder$1,
4223
+ uid,
4224
+ ...history.services ? history.services : {}
4225
+ };
4226
+ const index = () => {
4227
+ return {
4228
+ register,
4229
+ bootstrap,
4230
+ destroy,
4231
+ controllers,
4232
+ routes,
4233
+ policies,
4234
+ services
4235
+ };
4236
+ };
4237
+ module.exports = index;
4238
+ //# sourceMappingURL=index.js.map