@strapi/content-manager 5.60.0 → 5.61.1

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 (256) hide show
  1. package/dist/admin/constants/customOrder.js +14 -0
  2. package/dist/admin/constants/customOrder.js.map +1 -0
  3. package/dist/admin/constants/customOrder.mjs +10 -0
  4. package/dist/admin/constants/customOrder.mjs.map +1 -0
  5. package/dist/admin/hooks/useDocument.js +22 -11
  6. package/dist/admin/hooks/useDocument.js.map +1 -1
  7. package/dist/admin/hooks/useDocument.mjs +22 -11
  8. package/dist/admin/hooks/useDocument.mjs.map +1 -1
  9. package/dist/admin/hooks/useDocumentLayout.js.map +1 -1
  10. package/dist/admin/hooks/useDocumentLayout.mjs.map +1 -1
  11. package/dist/admin/hooks/useHasBeenNearViewport.js +70 -0
  12. package/dist/admin/hooks/useHasBeenNearViewport.js.map +1 -0
  13. package/dist/admin/hooks/useHasBeenNearViewport.mjs +46 -0
  14. package/dist/admin/hooks/useHasBeenNearViewport.mjs.map +1 -0
  15. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.js +102 -32
  16. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.js.map +1 -1
  17. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.mjs +104 -35
  18. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.mjs.map +1 -1
  19. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js +20 -17
  20. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js.map +1 -1
  21. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs +20 -17
  22. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs.map +1 -1
  23. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js +15 -1
  24. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js.map +1 -1
  25. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs +17 -3
  26. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs.map +1 -1
  27. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.js +21 -0
  28. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.js.map +1 -1
  29. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.mjs +22 -1
  30. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.mjs.map +1 -1
  31. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js +4 -7
  32. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js.map +1 -1
  33. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs +4 -7
  34. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs.map +1 -1
  35. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +46 -10
  36. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
  37. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +47 -11
  38. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
  39. package/dist/admin/pages/EditView/components/FormLayout.js +201 -51
  40. package/dist/admin/pages/EditView/components/FormLayout.js.map +1 -1
  41. package/dist/admin/pages/EditView/components/FormLayout.mjs +202 -53
  42. package/dist/admin/pages/EditView/components/FormLayout.mjs.map +1 -1
  43. package/dist/admin/pages/ListConfiguration/components/Settings.js +31 -2
  44. package/dist/admin/pages/ListConfiguration/components/Settings.js.map +1 -1
  45. package/dist/admin/pages/ListConfiguration/components/Settings.mjs +31 -2
  46. package/dist/admin/pages/ListConfiguration/components/Settings.mjs.map +1 -1
  47. package/dist/admin/pages/ListView/ListViewPage.js +196 -132
  48. package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
  49. package/dist/admin/pages/ListView/ListViewPage.mjs +196 -132
  50. package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
  51. package/dist/admin/pages/ListView/components/CustomOrder.js +571 -0
  52. package/dist/admin/pages/ListView/components/CustomOrder.js.map +1 -0
  53. package/dist/admin/pages/ListView/components/CustomOrder.mjs +546 -0
  54. package/dist/admin/pages/ListView/components/CustomOrder.mjs.map +1 -0
  55. package/dist/admin/pages/ListView/components/TableActions.js +4 -1
  56. package/dist/admin/pages/ListView/components/TableActions.js.map +1 -1
  57. package/dist/admin/pages/ListView/components/TableActions.mjs +4 -1
  58. package/dist/admin/pages/ListView/components/TableActions.mjs.map +1 -1
  59. package/dist/admin/services/documents.js +22 -1
  60. package/dist/admin/services/documents.js.map +1 -1
  61. package/dist/admin/services/documents.mjs +21 -2
  62. package/dist/admin/services/documents.mjs.map +1 -1
  63. package/dist/admin/src/constants/customOrder.d.ts +8 -0
  64. package/dist/admin/src/exports.d.ts +1 -1
  65. package/dist/admin/src/hooks/useDocument.d.ts +4 -0
  66. package/dist/admin/src/hooks/useDocumentLayout.d.ts +6 -2
  67. package/dist/admin/src/hooks/useHasBeenNearViewport.d.ts +13 -0
  68. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.d.ts +13 -1
  69. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +11 -1
  70. package/dist/admin/src/pages/ListView/components/CustomOrder.d.ts +72 -0
  71. package/dist/admin/src/services/documents.d.ts +10 -2
  72. package/dist/admin/translations/en.json.js +9 -0
  73. package/dist/admin/translations/en.json.js.map +1 -1
  74. package/dist/admin/translations/en.json.mjs +9 -0
  75. package/dist/admin/translations/en.json.mjs.map +1 -1
  76. package/dist/server/audit-logs.js +36 -0
  77. package/dist/server/audit-logs.js.map +1 -0
  78. package/dist/server/audit-logs.mjs +33 -0
  79. package/dist/server/audit-logs.mjs.map +1 -0
  80. package/dist/server/bootstrap.js +8 -0
  81. package/dist/server/bootstrap.js.map +1 -1
  82. package/dist/server/bootstrap.mjs +8 -0
  83. package/dist/server/bootstrap.mjs.map +1 -1
  84. package/dist/server/controllers/collection-types.js +8 -0
  85. package/dist/server/controllers/collection-types.js.map +1 -1
  86. package/dist/server/controllers/collection-types.mjs +8 -0
  87. package/dist/server/controllers/collection-types.mjs.map +1 -1
  88. package/dist/server/controllers/content-types.js +15 -0
  89. package/dist/server/controllers/content-types.js.map +1 -1
  90. package/dist/server/controllers/content-types.mjs +16 -1
  91. package/dist/server/controllers/content-types.mjs.map +1 -1
  92. package/dist/server/controllers/index.js +3 -1
  93. package/dist/server/controllers/index.js.map +1 -1
  94. package/dist/server/controllers/index.mjs +2 -0
  95. package/dist/server/controllers/index.mjs.map +1 -1
  96. package/dist/server/controllers/relations.js +5 -1
  97. package/dist/server/controllers/relations.js.map +1 -1
  98. package/dist/server/controllers/relations.mjs +5 -1
  99. package/dist/server/controllers/relations.mjs.map +1 -1
  100. package/dist/server/controllers/single-types.js +10 -1
  101. package/dist/server/controllers/single-types.js.map +1 -1
  102. package/dist/server/controllers/single-types.mjs +10 -1
  103. package/dist/server/controllers/single-types.mjs.map +1 -1
  104. package/dist/server/controllers/validation/model-configuration.js +2 -1
  105. package/dist/server/controllers/validation/model-configuration.js.map +1 -1
  106. package/dist/server/controllers/validation/model-configuration.mjs +2 -1
  107. package/dist/server/controllers/validation/model-configuration.mjs.map +1 -1
  108. package/dist/server/custom-order/constants.js +21 -0
  109. package/dist/server/custom-order/constants.js.map +1 -0
  110. package/dist/server/custom-order/constants.mjs +17 -0
  111. package/dist/server/custom-order/constants.mjs.map +1 -0
  112. package/dist/server/custom-order/controllers/custom-order.js +77 -0
  113. package/dist/server/custom-order/controllers/custom-order.js.map +1 -0
  114. package/dist/server/custom-order/controllers/custom-order.mjs +75 -0
  115. package/dist/server/custom-order/controllers/custom-order.mjs.map +1 -0
  116. package/dist/server/custom-order/controllers/index.js +10 -0
  117. package/dist/server/custom-order/controllers/index.js.map +1 -0
  118. package/dist/server/custom-order/controllers/index.mjs +8 -0
  119. package/dist/server/custom-order/controllers/index.mjs.map +1 -0
  120. package/dist/server/custom-order/index.js +71 -0
  121. package/dist/server/custom-order/index.js.map +1 -0
  122. package/dist/server/custom-order/index.mjs +69 -0
  123. package/dist/server/custom-order/index.mjs.map +1 -0
  124. package/dist/server/custom-order/routes/custom-order.js +38 -0
  125. package/dist/server/custom-order/routes/custom-order.js.map +1 -0
  126. package/dist/server/custom-order/routes/custom-order.mjs +36 -0
  127. package/dist/server/custom-order/routes/custom-order.mjs.map +1 -0
  128. package/dist/server/custom-order/routes/index.js +13 -0
  129. package/dist/server/custom-order/routes/index.js.map +1 -0
  130. package/dist/server/custom-order/routes/index.mjs +11 -0
  131. package/dist/server/custom-order/routes/index.mjs.map +1 -0
  132. package/dist/server/custom-order/services/custom-order.js +286 -0
  133. package/dist/server/custom-order/services/custom-order.js.map +1 -0
  134. package/dist/server/custom-order/services/custom-order.mjs +284 -0
  135. package/dist/server/custom-order/services/custom-order.mjs.map +1 -0
  136. package/dist/server/custom-order/services/document-middleware.js +83 -0
  137. package/dist/server/custom-order/services/document-middleware.js.map +1 -0
  138. package/dist/server/custom-order/services/document-middleware.mjs +81 -0
  139. package/dist/server/custom-order/services/document-middleware.mjs.map +1 -0
  140. package/dist/server/custom-order/services/index.js +10 -0
  141. package/dist/server/custom-order/services/index.js.map +1 -0
  142. package/dist/server/custom-order/services/index.mjs +8 -0
  143. package/dist/server/custom-order/services/index.mjs.map +1 -0
  144. package/dist/server/custom-order/services/utils.js +152 -0
  145. package/dist/server/custom-order/services/utils.js.map +1 -0
  146. package/dist/server/custom-order/services/utils.mjs +148 -0
  147. package/dist/server/custom-order/services/utils.mjs.map +1 -0
  148. package/dist/server/custom-order/utils.js +13 -0
  149. package/dist/server/custom-order/utils.js.map +1 -0
  150. package/dist/server/custom-order/utils.mjs +10 -0
  151. package/dist/server/custom-order/utils.mjs.map +1 -0
  152. package/dist/server/history/constants.js +2 -1
  153. package/dist/server/history/constants.js.map +1 -1
  154. package/dist/server/history/constants.mjs +2 -1
  155. package/dist/server/history/constants.mjs.map +1 -1
  156. package/dist/server/history/controllers/history-version.js +6 -2
  157. package/dist/server/history/controllers/history-version.js.map +1 -1
  158. package/dist/server/history/controllers/history-version.mjs +6 -2
  159. package/dist/server/history/controllers/history-version.mjs.map +1 -1
  160. package/dist/server/history/services/history.js +23 -6
  161. package/dist/server/history/services/history.js.map +1 -1
  162. package/dist/server/history/services/history.mjs +24 -7
  163. package/dist/server/history/services/history.mjs.map +1 -1
  164. package/dist/server/history/services/lifecycles.js +2 -16
  165. package/dist/server/history/services/lifecycles.js.map +1 -1
  166. package/dist/server/history/services/lifecycles.mjs +2 -16
  167. package/dist/server/history/services/lifecycles.mjs.map +1 -1
  168. package/dist/server/register.js +4 -0
  169. package/dist/server/register.js.map +1 -1
  170. package/dist/server/register.mjs +4 -0
  171. package/dist/server/register.mjs.map +1 -1
  172. package/dist/server/routes/index.js +3 -1
  173. package/dist/server/routes/index.js.map +1 -1
  174. package/dist/server/routes/index.mjs +2 -0
  175. package/dist/server/routes/index.mjs.map +1 -1
  176. package/dist/server/services/content-types.js +2 -2
  177. package/dist/server/services/content-types.js.map +1 -1
  178. package/dist/server/services/content-types.mjs +2 -2
  179. package/dist/server/services/content-types.mjs.map +1 -1
  180. package/dist/server/services/document-manager.js +13 -0
  181. package/dist/server/services/document-manager.js.map +1 -1
  182. package/dist/server/services/document-manager.mjs +14 -1
  183. package/dist/server/services/document-manager.mjs.map +1 -1
  184. package/dist/server/services/index.js +3 -1
  185. package/dist/server/services/index.js.map +1 -1
  186. package/dist/server/services/index.mjs +2 -0
  187. package/dist/server/services/index.mjs.map +1 -1
  188. package/dist/server/services/utils/configuration/settings.js +2 -1
  189. package/dist/server/services/utils/configuration/settings.js.map +1 -1
  190. package/dist/server/services/utils/configuration/settings.mjs +2 -1
  191. package/dist/server/services/utils/configuration/settings.mjs.map +1 -1
  192. package/dist/server/src/audit-logs.d.ts +40 -0
  193. package/dist/server/src/audit-logs.d.ts.map +1 -0
  194. package/dist/server/src/bootstrap.d.ts.map +1 -1
  195. package/dist/server/src/controllers/collection-types.d.ts +1 -1
  196. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  197. package/dist/server/src/controllers/content-types.d.ts.map +1 -1
  198. package/dist/server/src/controllers/index.d.ts +21 -3
  199. package/dist/server/src/controllers/index.d.ts.map +1 -1
  200. package/dist/server/src/controllers/relations.d.ts +19 -1
  201. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  202. package/dist/server/src/controllers/single-types.d.ts +1 -1
  203. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  204. package/dist/server/src/custom-order/constants.d.ts +18 -0
  205. package/dist/server/src/custom-order/constants.d.ts.map +1 -0
  206. package/dist/server/src/custom-order/controllers/custom-order.d.ts +8 -0
  207. package/dist/server/src/custom-order/controllers/custom-order.d.ts.map +1 -0
  208. package/dist/server/src/custom-order/controllers/index.d.ts +3 -0
  209. package/dist/server/src/custom-order/controllers/index.d.ts.map +1 -0
  210. package/dist/server/src/custom-order/index.d.ts +8 -0
  211. package/dist/server/src/custom-order/index.d.ts.map +1 -0
  212. package/dist/server/src/custom-order/routes/custom-order.d.ts +4 -0
  213. package/dist/server/src/custom-order/routes/custom-order.d.ts.map +1 -0
  214. package/dist/server/src/custom-order/routes/index.d.ts +10 -0
  215. package/dist/server/src/custom-order/routes/index.d.ts.map +1 -0
  216. package/dist/server/src/custom-order/services/custom-order.d.ts +43 -0
  217. package/dist/server/src/custom-order/services/custom-order.d.ts.map +1 -0
  218. package/dist/server/src/custom-order/services/document-middleware.d.ts +16 -0
  219. package/dist/server/src/custom-order/services/document-middleware.d.ts.map +1 -0
  220. package/dist/server/src/custom-order/services/index.d.ts +24 -0
  221. package/dist/server/src/custom-order/services/index.d.ts.map +1 -0
  222. package/dist/server/src/custom-order/services/utils.d.ts +34 -0
  223. package/dist/server/src/custom-order/services/utils.d.ts.map +1 -0
  224. package/dist/server/src/custom-order/utils.d.ts +6 -0
  225. package/dist/server/src/custom-order/utils.d.ts.map +1 -0
  226. package/dist/server/src/history/constants.d.ts.map +1 -1
  227. package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
  228. package/dist/server/src/history/services/history.d.ts.map +1 -1
  229. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  230. package/dist/server/src/index.d.ts +22 -6
  231. package/dist/server/src/index.d.ts.map +1 -1
  232. package/dist/server/src/register.d.ts.map +1 -1
  233. package/dist/server/src/routes/index.d.ts.map +1 -1
  234. package/dist/server/src/services/content-types.d.ts +1 -3
  235. package/dist/server/src/services/content-types.d.ts.map +1 -1
  236. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  237. package/dist/server/src/services/index.d.ts +1 -3
  238. package/dist/server/src/services/index.d.ts.map +1 -1
  239. package/dist/server/src/services/utils/configuration/settings.d.ts.map +1 -1
  240. package/dist/shared/contracts/content-types.d.ts +5 -0
  241. package/dist/shared/contracts/content-types.d.ts.map +1 -1
  242. package/dist/shared/contracts/custom-order.d.ts +33 -0
  243. package/dist/shared/contracts/custom-order.d.ts.map +1 -0
  244. package/dist/shared/contracts/custom-order.js +3 -0
  245. package/dist/shared/contracts/custom-order.js.map +1 -0
  246. package/dist/shared/contracts/custom-order.mjs +2 -0
  247. package/dist/shared/contracts/custom-order.mjs.map +1 -0
  248. package/dist/shared/contracts/history-versions.d.ts +0 -1
  249. package/dist/shared/contracts/history-versions.d.ts.map +1 -1
  250. package/dist/shared/contracts/index.d.ts +1 -0
  251. package/dist/shared/contracts/index.d.ts.map +1 -1
  252. package/dist/shared/contracts/index.js +2 -0
  253. package/dist/shared/contracts/index.js.map +1 -1
  254. package/dist/shared/contracts/index.mjs +2 -0
  255. package/dist/shared/contracts/index.mjs.map +1 -1
  256. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"history.js","sources":["../../../../server/src/history/services/history.ts"],"sourcesContent":["import type { Core, Data, Modules, Schema } from '@strapi/types';\nimport { errors, traverseEntity } from '@strapi/utils';\nimport { omit } from 'lodash';\n\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\nimport type { HistoryVersions } from '../../../../shared/contracts';\nimport type {\n CreateHistoryVersion,\n HistoryVersionDataResponse,\n} from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\nimport { getService as getContentManagerService } from '../../utils';\n\n// Needed because the query engine doesn't return any types yet\ntype HistoryVersionQueryResult = Omit<HistoryVersionDataResponse, 'locale'> &\n Pick<CreateHistoryVersion, 'locale'>;\n\nconst createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => {\n const query = strapi.db.query(HISTORY_VERSION_UID);\n const serviceUtils = createServiceUtils({ strapi });\n\n return {\n async createVersion(historyVersionData: HistoryVersions.CreateHistoryVersion) {\n await query.create({\n data: {\n ...historyVersionData,\n createdAt: new Date(),\n createdBy: strapi.requestContext.get()?.state?.user.id,\n },\n });\n },\n\n async findVersionsPage(params: HistoryVersions.GetHistoryVersions.Request): Promise<{\n results: HistoryVersions.HistoryVersionDataResponse[];\n pagination: HistoryVersions.Pagination;\n }> {\n const schema = strapi.getModel(params.query.contentType);\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(schema);\n const defaultLocale = await serviceUtils.getDefaultLocale();\n\n let locale = null;\n if (isLocalizedContentType) {\n locale = params.query.locale || defaultLocale;\n }\n\n // NOTE: We get the IDs first because sorting full rows runs MySQL/MariaDB out of sort memory\n // See: https://github.com/strapi/strapi/issues/27393\n const [{ results: versionRows, pagination }, localeDictionary] = await Promise.all([\n query.findPage({\n ...params.query,\n select: ['id'],\n where: {\n $and: [\n { contentType: params.query.contentType },\n ...(params.query.documentId ? [{ relatedDocumentId: params.query.documentId }] : []),\n ...(locale ? [{ locale }] : []),\n ],\n },\n orderBy: [{ createdAt: 'desc' }],\n }),\n serviceUtils.getLocaleDictionary(),\n ]);\n\n const ids = versionRows.map((version) => version.id);\n const versions = ids.length\n ? await query.findMany({\n where: { id: { $in: ids } },\n populate: ['createdBy'],\n })\n : [];\n const versionsById = new Map(versions.map((version) => [version.id, version]));\n const results = ids.map((id) => versionsById.get(id)).filter(Boolean);\n\n const populateEntry = async (entry: HistoryVersionQueryResult) => {\n return traverseEntity(\n async (options, utils) => {\n if (!options.attribute) return;\n if (!options.value) return;\n\n const currentValue: any[] = Array.isArray(options.value)\n ? options.value\n : [options.value];\n\n if (options.attribute.type === 'component') {\n // Ids on components throw an error when restoring\n utils.remove('id');\n }\n\n if (\n options.attribute.type === 'relation' &&\n // TODO: handle polymorphic relations\n options.attribute.relation !== 'morphToOne' &&\n options.attribute.relation !== 'morphToMany'\n ) {\n if (options.attribute.target === 'admin::user') {\n const adminUsers = await Promise.all(\n currentValue.map((userToPopulate) => {\n if (userToPopulate == null) {\n return null;\n }\n\n return strapi.db.query('admin::user').findOne({\n where: {\n ...(userToPopulate.id ? { id: userToPopulate.id } : {}),\n ...(userToPopulate.documentId\n ? { documentId: userToPopulate.documentId }\n : {}),\n },\n });\n })\n );\n\n utils.set(options.key, adminUsers as any);\n }\n\n const permissionChecker = getContentManagerService('permission-checker').create({\n userAbility: params.state.userAbility,\n model: options.attribute.target,\n });\n\n const response = await serviceUtils.buildRelationReponse(\n currentValue,\n options.attribute as Schema.Attribute.RelationWithTarget\n );\n const sanitizedResults = await Promise.all(\n response.results.map((media) => permissionChecker.sanitizeOutput(media))\n );\n\n utils.set(options.key, {\n results: sanitizedResults,\n meta: response.meta,\n });\n }\n\n if (options.attribute.type === 'media') {\n const permissionChecker = getContentManagerService('permission-checker').create({\n userAbility: params.state.userAbility,\n model: 'plugin::upload.file',\n });\n\n const response = await serviceUtils.buildMediaResponse(currentValue);\n const sanitizedResults = await Promise.all(\n response.results.map((media) => permissionChecker.sanitizeOutput(media))\n );\n\n utils.set(options.key, {\n results: sanitizedResults,\n meta: response.meta,\n });\n }\n },\n {\n schema,\n getModel: strapi.getModel.bind(strapi),\n },\n entry.data\n );\n };\n\n const formattedResults: any[] = await Promise.all(\n (results as HistoryVersionQueryResult[]).map(async (result) => {\n return {\n ...result,\n data: await populateEntry(result),\n meta: {\n unknownAttributes: serviceUtils.getSchemaAttributesDiff(\n result.schema,\n strapi.getModel(params.query.contentType).attributes\n ),\n },\n locale: result.locale ? localeDictionary[result.locale] : null,\n };\n })\n );\n\n return {\n results: formattedResults,\n pagination,\n };\n },\n\n async restoreVersion(versionId: Data.ID) {\n const version = await query.findOne({ where: { id: versionId } });\n const contentTypeSchemaAttributes = strapi.getModel(version.contentType).attributes;\n const schemaDiff = serviceUtils.getSchemaAttributesDiff(\n version.schema,\n contentTypeSchemaAttributes\n );\n\n // Set all added attribute values to null\n const dataWithoutAddedAttributes = Object.keys(schemaDiff.added).reduce(\n (currentData, addedKey) => {\n currentData[addedKey] = null;\n return currentData;\n },\n // Clone to avoid mutating the original version data\n structuredClone(version.data)\n );\n\n // Remove the schema attributes history should ignore\n const schema = structuredClone(version.schema);\n schema.attributes = omit(contentTypeSchemaAttributes, FIELDS_TO_IGNORE);\n\n const dataWithoutMissingRelations = await traverseEntity(\n async (options, utils) => {\n if (!options.attribute) return;\n\n if (options.attribute.type === 'component') {\n // Ids on components throw an error when restoring\n utils.remove('id');\n\n if (options.attribute.repeatable && options.value === null) {\n // Repeatable Components should always be an array\n utils.set(options.key, [] as any);\n }\n }\n\n if (options.attribute.type === 'dynamiczone') {\n if (options.value === null) {\n // Dynamic zones should always be an array\n utils.set(options.key, [] as any);\n }\n }\n\n if (\n options.attribute.type === 'relation' &&\n // TODO: handle polymorphic relations\n options.attribute.relation !== 'morphToOne' &&\n options.attribute.relation !== 'morphToMany'\n ) {\n if (!options.value) return;\n\n const data = await serviceUtils.getRelationRestoreValue(\n options.value as Modules.Documents.AnyDocument,\n options.attribute as Schema.Attribute.RelationWithTarget\n );\n\n utils.set(options.key, data as Modules.Documents.AnyDocument);\n }\n\n if (options.attribute.type === 'media') {\n if (!options.value) return;\n\n const data = await serviceUtils.getMediaRestoreValue(\n options.value as Modules.Documents.AnyDocument\n );\n\n utils.set(options.key, data);\n }\n },\n {\n schema,\n getModel: strapi.getModel.bind(strapi),\n },\n dataWithoutAddedAttributes\n );\n\n const data = omit(dataWithoutMissingRelations, ['id', ...Object.keys(schemaDiff.removed)]);\n const restoredDocument = await strapi.documents(version.contentType).update({\n documentId: version.relatedDocumentId,\n locale: version.locale,\n data,\n });\n\n if (!restoredDocument) {\n throw new errors.ApplicationError('Failed to restore version');\n }\n\n return restoredDocument;\n },\n };\n};\n\nexport { createHistoryService };\n"],"names":["createHistoryService","strapi","query","db","HISTORY_VERSION_UID","serviceUtils","createServiceUtils","createVersion","historyVersionData","create","data","createdAt","Date","createdBy","requestContext","get","state","user","id","findVersionsPage","params","schema","getModel","contentType","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","results","versionRows","pagination","localeDictionary","Promise","all","findPage","select","where","$and","documentId","relatedDocumentId","orderBy","getLocaleDictionary","ids","map","version","versions","length","findMany","$in","populate","versionsById","Map","filter","Boolean","populateEntry","entry","traverseEntity","options","utils","attribute","value","currentValue","Array","isArray","type","remove","relation","target","adminUsers","userToPopulate","findOne","set","key","permissionChecker","getContentManagerService","userAbility","model","response","buildRelationReponse","sanitizedResults","media","sanitizeOutput","meta","buildMediaResponse","bind","formattedResults","result","unknownAttributes","getSchemaAttributesDiff","attributes","restoreVersion","versionId","contentTypeSchemaAttributes","schemaDiff","dataWithoutAddedAttributes","Object","keys","added","reduce","currentData","addedKey","structuredClone","omit","FIELDS_TO_IGNORE","dataWithoutMissingRelations","repeatable","getRelationRestoreValue","getMediaRestoreValue","removed","restoredDocument","documents","update","errors","ApplicationError"],"mappings":"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"}
1
+ {"version":3,"file":"history.js","sources":["../../../../server/src/history/services/history.ts"],"sourcesContent":["import type { Core, Data, Modules, Schema } from '@strapi/types';\nimport { emitAudit, errors, traverseEntity } from '@strapi/utils';\nimport { omit } from 'lodash';\n\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\nimport type { HistoryVersions } from '../../../../shared/contracts';\nimport type {\n CreateHistoryVersion,\n HistoryVersionDataResponse,\n} from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\nimport { getService as getContentManagerService } from '../../utils';\nimport { AUDITED_EVENTS, type HistoryRestoreEvent } from '../../audit-logs';\n\n// Needed because the query engine doesn't return any types yet\ntype HistoryVersionQueryResult = Omit<HistoryVersionDataResponse, 'locale'> &\n Pick<CreateHistoryVersion, 'locale'>;\n\nconst createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => {\n const query = strapi.db.query(HISTORY_VERSION_UID);\n const serviceUtils = createServiceUtils({ strapi });\n\n return {\n async createVersion(historyVersionData: HistoryVersions.CreateHistoryVersion) {\n await query.create({\n data: {\n ...historyVersionData,\n createdAt: new Date(),\n createdBy: strapi.requestContext.get()?.state?.user.id,\n },\n });\n },\n\n async findVersionsPage(params: HistoryVersions.GetHistoryVersions.Request): Promise<{\n results: HistoryVersions.HistoryVersionDataResponse[];\n pagination: HistoryVersions.Pagination;\n }> {\n const schema = strapi.getModel(params.query.contentType);\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(schema);\n const defaultLocale = await serviceUtils.getDefaultLocale();\n\n let locale = null;\n if (isLocalizedContentType) {\n locale = params.query.locale || defaultLocale;\n }\n\n // NOTE: We get the IDs first because sorting full rows runs MySQL/MariaDB out of sort memory\n // See: https://github.com/strapi/strapi/issues/27393\n const [{ results: versionRows, pagination }, localeDictionary] = await Promise.all([\n query.findPage({\n ...params.query,\n select: ['id'],\n where: {\n $and: [\n { contentType: params.query.contentType },\n ...(params.query.documentId ? [{ relatedDocumentId: params.query.documentId }] : []),\n ...(locale ? [{ locale }] : []),\n ],\n },\n orderBy: [{ createdAt: 'desc' }],\n }),\n serviceUtils.getLocaleDictionary(),\n ]);\n\n const ids = versionRows.map((version) => version.id);\n const versions = ids.length\n ? await query.findMany({\n where: { id: { $in: ids } },\n populate: ['createdBy'],\n })\n : [];\n const versionsById = new Map(versions.map((version) => [version.id, version]));\n const results = ids.map((id) => versionsById.get(id)).filter(Boolean);\n\n const populateEntry = async (entry: HistoryVersionQueryResult) => {\n return traverseEntity(\n async (options, utils) => {\n if (options.key === 'id' && options.schema.modelType === 'component') {\n // Ids on components throw an error when restoring\n utils.remove('id');\n return;\n }\n\n if (!options.attribute) return;\n if (!options.value) return;\n\n const currentValue: any[] = Array.isArray(options.value)\n ? options.value\n : [options.value];\n\n if (\n options.attribute.type === 'relation' &&\n // TODO: handle polymorphic relations\n options.attribute.relation !== 'morphToOne' &&\n options.attribute.relation !== 'morphToMany'\n ) {\n if (options.attribute.target === 'admin::user') {\n const adminUsers = await Promise.all(\n currentValue.map((userToPopulate) => {\n if (userToPopulate == null) {\n return null;\n }\n\n return strapi.db.query('admin::user').findOne({\n where: {\n ...(userToPopulate.id ? { id: userToPopulate.id } : {}),\n ...(userToPopulate.documentId\n ? { documentId: userToPopulate.documentId }\n : {}),\n },\n });\n })\n );\n\n utils.set(options.key, adminUsers as any);\n }\n\n const permissionChecker = getContentManagerService('permission-checker').create({\n userAbility: params.state.userAbility,\n model: options.attribute.target,\n });\n\n const response = await serviceUtils.buildRelationReponse(\n currentValue,\n options.attribute as Schema.Attribute.RelationWithTarget\n );\n const sanitizedResults = await Promise.all(\n response.results.map((media) => permissionChecker.sanitizeOutput(media))\n );\n\n utils.set(options.key, {\n results: sanitizedResults,\n meta: response.meta,\n });\n }\n\n if (options.attribute.type === 'media') {\n const permissionChecker = getContentManagerService('permission-checker').create({\n userAbility: params.state.userAbility,\n model: 'plugin::upload.file',\n });\n\n const response = await serviceUtils.buildMediaResponse(currentValue);\n const sanitizedResults = await Promise.all(\n response.results.map((media) => permissionChecker.sanitizeOutput(media))\n );\n\n utils.set(options.key, {\n results: sanitizedResults,\n meta: response.meta,\n });\n }\n },\n {\n schema,\n getModel: strapi.getModel.bind(strapi),\n },\n entry.data\n );\n };\n\n const formattedResults: any[] = await Promise.all(\n (results as HistoryVersionQueryResult[]).map(async (result) => {\n return {\n ...result,\n data: await populateEntry(result),\n meta: {\n unknownAttributes: serviceUtils.getSchemaAttributesDiff(\n result.schema,\n strapi.getModel(params.query.contentType).attributes\n ),\n },\n locale: result.locale ? localeDictionary[result.locale] : null,\n };\n })\n );\n\n return {\n results: formattedResults,\n pagination,\n };\n },\n\n async restoreVersion(versionId: Data.ID) {\n const version = await query.findOne({ where: { id: versionId } });\n\n if (version === null) {\n throw new errors.NotFoundError('History version not found');\n }\n\n const contentTypeSchemaAttributes = strapi.getModel(version.contentType).attributes;\n const schemaDiff = serviceUtils.getSchemaAttributesDiff(\n version.schema,\n contentTypeSchemaAttributes\n );\n\n // Set all added attribute values to null\n const dataWithoutAddedAttributes = Object.keys(schemaDiff.added).reduce(\n (currentData, addedKey) => {\n currentData[addedKey] = null;\n return currentData;\n },\n // Clone to avoid mutating the original version data\n structuredClone(version.data)\n );\n\n // Remove the schema attributes history should ignore\n const schema = structuredClone(version.schema);\n schema.attributes = omit(contentTypeSchemaAttributes, FIELDS_TO_IGNORE);\n\n const dataWithoutMissingRelations = await traverseEntity(\n async (options, utils) => {\n if (options.key === 'id' && options.schema.modelType === 'component') {\n // Ids on components throw an error when restoring\n utils.remove('id');\n return;\n }\n\n if (!options.attribute) return;\n\n if (options.attribute.type === 'component') {\n if (options.attribute.repeatable && options.value === null) {\n // Repeatable Components should always be an array\n utils.set(options.key, [] as any);\n }\n }\n\n if (options.attribute.type === 'dynamiczone') {\n if (options.value === null) {\n // Dynamic zones should always be an array\n utils.set(options.key, [] as any);\n }\n }\n\n if (\n options.attribute.type === 'relation' &&\n // TODO: handle polymorphic relations\n options.attribute.relation !== 'morphToOne' &&\n options.attribute.relation !== 'morphToMany'\n ) {\n if (!options.value) return;\n\n const data = await serviceUtils.getRelationRestoreValue(\n options.value as Modules.Documents.AnyDocument,\n options.attribute as Schema.Attribute.RelationWithTarget\n );\n\n utils.set(options.key, data as Modules.Documents.AnyDocument);\n }\n\n if (options.attribute.type === 'media') {\n if (!options.value) return;\n\n const data = await serviceUtils.getMediaRestoreValue(\n options.value as Modules.Documents.AnyDocument\n );\n\n utils.set(options.key, data);\n }\n },\n {\n schema,\n getModel: strapi.getModel.bind(strapi),\n },\n dataWithoutAddedAttributes\n );\n\n const data = omit(dataWithoutMissingRelations, ['id', ...Object.keys(schemaDiff.removed)]);\n const restoredDocument = await strapi.documents(version.contentType).update({\n documentId: version.relatedDocumentId,\n locale: version.locale,\n data,\n });\n\n if (!restoredDocument) {\n throw new errors.ApplicationError('Failed to restore version');\n }\n\n await emitAudit({ strapi }, AUDITED_EVENTS.ENTRY_HISTORY_RESTORE, {\n uid: version.contentType,\n documentId: restoredDocument.documentId,\n locale: version.locale ?? null,\n versionId: version.id,\n versionCreatedAt: new Date(version.createdAt).toISOString(),\n } satisfies HistoryRestoreEvent);\n\n return restoredDocument;\n },\n };\n};\n\nexport { createHistoryService };\n"],"names":["createHistoryService","strapi","query","db","HISTORY_VERSION_UID","serviceUtils","createServiceUtils","createVersion","historyVersionData","create","data","createdAt","Date","createdBy","requestContext","get","state","user","id","findVersionsPage","params","schema","getModel","contentType","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","results","versionRows","pagination","localeDictionary","Promise","all","findPage","select","where","$and","documentId","relatedDocumentId","orderBy","getLocaleDictionary","ids","map","version","versions","length","findMany","$in","populate","versionsById","Map","filter","Boolean","populateEntry","entry","traverseEntity","options","utils","key","modelType","remove","attribute","value","currentValue","Array","isArray","type","relation","target","adminUsers","userToPopulate","findOne","set","permissionChecker","getContentManagerService","userAbility","model","response","buildRelationReponse","sanitizedResults","media","sanitizeOutput","meta","buildMediaResponse","bind","formattedResults","result","unknownAttributes","getSchemaAttributesDiff","attributes","restoreVersion","versionId","errors","NotFoundError","contentTypeSchemaAttributes","schemaDiff","dataWithoutAddedAttributes","Object","keys","added","reduce","currentData","addedKey","structuredClone","omit","FIELDS_TO_IGNORE","dataWithoutMissingRelations","repeatable","getRelationRestoreValue","getMediaRestoreValue","removed","restoredDocument","documents","update","ApplicationError","emitAudit","AUDITED_EVENTS","ENTRY_HISTORY_RESTORE","uid","versionCreatedAt","toISOString"],"mappings":"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"}
@@ -1,8 +1,9 @@
1
- import { traverseEntity, errors } from '@strapi/utils';
1
+ import { errors, traverseEntity, emitAudit } from '@strapi/utils';
2
2
  import { omit } from 'lodash';
3
3
  import { HISTORY_VERSION_UID, FIELDS_TO_IGNORE } from '../constants.mjs';
4
4
  import { createServiceUtils } from './utils.mjs';
5
5
  import { getService } from '../../utils/index.mjs';
6
+ import { AUDITED_EVENTS } from '../../audit-logs.mjs';
6
7
 
7
8
  const createHistoryService = ({ strapi })=>{
8
9
  const query = strapi.db.query(HISTORY_VERSION_UID);
@@ -78,15 +79,16 @@ const createHistoryService = ({ strapi })=>{
78
79
  const results = ids.map((id)=>versionsById.get(id)).filter(Boolean);
79
80
  const populateEntry = async (entry)=>{
80
81
  return traverseEntity(async (options, utils)=>{
82
+ if (options.key === 'id' && options.schema.modelType === 'component') {
83
+ // Ids on components throw an error when restoring
84
+ utils.remove('id');
85
+ return;
86
+ }
81
87
  if (!options.attribute) return;
82
88
  if (!options.value) return;
83
89
  const currentValue = Array.isArray(options.value) ? options.value : [
84
90
  options.value
85
91
  ];
86
- if (options.attribute.type === 'component') {
87
- // Ids on components throw an error when restoring
88
- utils.remove('id');
89
- }
90
92
  if (options.attribute.type === 'relation' && // TODO: handle polymorphic relations
91
93
  options.attribute.relation !== 'morphToOne' && options.attribute.relation !== 'morphToMany') {
92
94
  if (options.attribute.target === 'admin::user') {
@@ -156,6 +158,9 @@ const createHistoryService = ({ strapi })=>{
156
158
  id: versionId
157
159
  }
158
160
  });
161
+ if (version === null) {
162
+ throw new errors.NotFoundError('History version not found');
163
+ }
159
164
  const contentTypeSchemaAttributes = strapi.getModel(version.contentType).attributes;
160
165
  const schemaDiff = serviceUtils.getSchemaAttributesDiff(version.schema, contentTypeSchemaAttributes);
161
166
  // Set all added attribute values to null
@@ -168,10 +173,13 @@ const createHistoryService = ({ strapi })=>{
168
173
  const schema = structuredClone(version.schema);
169
174
  schema.attributes = omit(contentTypeSchemaAttributes, FIELDS_TO_IGNORE);
170
175
  const dataWithoutMissingRelations = await traverseEntity(async (options, utils)=>{
171
- if (!options.attribute) return;
172
- if (options.attribute.type === 'component') {
176
+ if (options.key === 'id' && options.schema.modelType === 'component') {
173
177
  // Ids on components throw an error when restoring
174
178
  utils.remove('id');
179
+ return;
180
+ }
181
+ if (!options.attribute) return;
182
+ if (options.attribute.type === 'component') {
175
183
  if (options.attribute.repeatable && options.value === null) {
176
184
  // Repeatable Components should always be an array
177
185
  utils.set(options.key, []);
@@ -210,6 +218,15 @@ const createHistoryService = ({ strapi })=>{
210
218
  if (!restoredDocument) {
211
219
  throw new errors.ApplicationError('Failed to restore version');
212
220
  }
221
+ await emitAudit({
222
+ strapi
223
+ }, AUDITED_EVENTS.ENTRY_HISTORY_RESTORE, {
224
+ uid: version.contentType,
225
+ documentId: restoredDocument.documentId,
226
+ locale: version.locale ?? null,
227
+ versionId: version.id,
228
+ versionCreatedAt: new Date(version.createdAt).toISOString()
229
+ });
213
230
  return restoredDocument;
214
231
  }
215
232
  };
@@ -1 +1 @@
1
- {"version":3,"file":"history.mjs","sources":["../../../../server/src/history/services/history.ts"],"sourcesContent":["import type { Core, Data, Modules, Schema } from '@strapi/types';\nimport { errors, traverseEntity } from '@strapi/utils';\nimport { omit } from 'lodash';\n\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\nimport type { HistoryVersions } from '../../../../shared/contracts';\nimport type {\n CreateHistoryVersion,\n HistoryVersionDataResponse,\n} from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\nimport { getService as getContentManagerService } from '../../utils';\n\n// Needed because the query engine doesn't return any types yet\ntype HistoryVersionQueryResult = Omit<HistoryVersionDataResponse, 'locale'> &\n Pick<CreateHistoryVersion, 'locale'>;\n\nconst createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => {\n const query = strapi.db.query(HISTORY_VERSION_UID);\n const serviceUtils = createServiceUtils({ strapi });\n\n return {\n async createVersion(historyVersionData: HistoryVersions.CreateHistoryVersion) {\n await query.create({\n data: {\n ...historyVersionData,\n createdAt: new Date(),\n createdBy: strapi.requestContext.get()?.state?.user.id,\n },\n });\n },\n\n async findVersionsPage(params: HistoryVersions.GetHistoryVersions.Request): Promise<{\n results: HistoryVersions.HistoryVersionDataResponse[];\n pagination: HistoryVersions.Pagination;\n }> {\n const schema = strapi.getModel(params.query.contentType);\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(schema);\n const defaultLocale = await serviceUtils.getDefaultLocale();\n\n let locale = null;\n if (isLocalizedContentType) {\n locale = params.query.locale || defaultLocale;\n }\n\n // NOTE: We get the IDs first because sorting full rows runs MySQL/MariaDB out of sort memory\n // See: https://github.com/strapi/strapi/issues/27393\n const [{ results: versionRows, pagination }, localeDictionary] = await Promise.all([\n query.findPage({\n ...params.query,\n select: ['id'],\n where: {\n $and: [\n { contentType: params.query.contentType },\n ...(params.query.documentId ? [{ relatedDocumentId: params.query.documentId }] : []),\n ...(locale ? [{ locale }] : []),\n ],\n },\n orderBy: [{ createdAt: 'desc' }],\n }),\n serviceUtils.getLocaleDictionary(),\n ]);\n\n const ids = versionRows.map((version) => version.id);\n const versions = ids.length\n ? await query.findMany({\n where: { id: { $in: ids } },\n populate: ['createdBy'],\n })\n : [];\n const versionsById = new Map(versions.map((version) => [version.id, version]));\n const results = ids.map((id) => versionsById.get(id)).filter(Boolean);\n\n const populateEntry = async (entry: HistoryVersionQueryResult) => {\n return traverseEntity(\n async (options, utils) => {\n if (!options.attribute) return;\n if (!options.value) return;\n\n const currentValue: any[] = Array.isArray(options.value)\n ? options.value\n : [options.value];\n\n if (options.attribute.type === 'component') {\n // Ids on components throw an error when restoring\n utils.remove('id');\n }\n\n if (\n options.attribute.type === 'relation' &&\n // TODO: handle polymorphic relations\n options.attribute.relation !== 'morphToOne' &&\n options.attribute.relation !== 'morphToMany'\n ) {\n if (options.attribute.target === 'admin::user') {\n const adminUsers = await Promise.all(\n currentValue.map((userToPopulate) => {\n if (userToPopulate == null) {\n return null;\n }\n\n return strapi.db.query('admin::user').findOne({\n where: {\n ...(userToPopulate.id ? { id: userToPopulate.id } : {}),\n ...(userToPopulate.documentId\n ? { documentId: userToPopulate.documentId }\n : {}),\n },\n });\n })\n );\n\n utils.set(options.key, adminUsers as any);\n }\n\n const permissionChecker = getContentManagerService('permission-checker').create({\n userAbility: params.state.userAbility,\n model: options.attribute.target,\n });\n\n const response = await serviceUtils.buildRelationReponse(\n currentValue,\n options.attribute as Schema.Attribute.RelationWithTarget\n );\n const sanitizedResults = await Promise.all(\n response.results.map((media) => permissionChecker.sanitizeOutput(media))\n );\n\n utils.set(options.key, {\n results: sanitizedResults,\n meta: response.meta,\n });\n }\n\n if (options.attribute.type === 'media') {\n const permissionChecker = getContentManagerService('permission-checker').create({\n userAbility: params.state.userAbility,\n model: 'plugin::upload.file',\n });\n\n const response = await serviceUtils.buildMediaResponse(currentValue);\n const sanitizedResults = await Promise.all(\n response.results.map((media) => permissionChecker.sanitizeOutput(media))\n );\n\n utils.set(options.key, {\n results: sanitizedResults,\n meta: response.meta,\n });\n }\n },\n {\n schema,\n getModel: strapi.getModel.bind(strapi),\n },\n entry.data\n );\n };\n\n const formattedResults: any[] = await Promise.all(\n (results as HistoryVersionQueryResult[]).map(async (result) => {\n return {\n ...result,\n data: await populateEntry(result),\n meta: {\n unknownAttributes: serviceUtils.getSchemaAttributesDiff(\n result.schema,\n strapi.getModel(params.query.contentType).attributes\n ),\n },\n locale: result.locale ? localeDictionary[result.locale] : null,\n };\n })\n );\n\n return {\n results: formattedResults,\n pagination,\n };\n },\n\n async restoreVersion(versionId: Data.ID) {\n const version = await query.findOne({ where: { id: versionId } });\n const contentTypeSchemaAttributes = strapi.getModel(version.contentType).attributes;\n const schemaDiff = serviceUtils.getSchemaAttributesDiff(\n version.schema,\n contentTypeSchemaAttributes\n );\n\n // Set all added attribute values to null\n const dataWithoutAddedAttributes = Object.keys(schemaDiff.added).reduce(\n (currentData, addedKey) => {\n currentData[addedKey] = null;\n return currentData;\n },\n // Clone to avoid mutating the original version data\n structuredClone(version.data)\n );\n\n // Remove the schema attributes history should ignore\n const schema = structuredClone(version.schema);\n schema.attributes = omit(contentTypeSchemaAttributes, FIELDS_TO_IGNORE);\n\n const dataWithoutMissingRelations = await traverseEntity(\n async (options, utils) => {\n if (!options.attribute) return;\n\n if (options.attribute.type === 'component') {\n // Ids on components throw an error when restoring\n utils.remove('id');\n\n if (options.attribute.repeatable && options.value === null) {\n // Repeatable Components should always be an array\n utils.set(options.key, [] as any);\n }\n }\n\n if (options.attribute.type === 'dynamiczone') {\n if (options.value === null) {\n // Dynamic zones should always be an array\n utils.set(options.key, [] as any);\n }\n }\n\n if (\n options.attribute.type === 'relation' &&\n // TODO: handle polymorphic relations\n options.attribute.relation !== 'morphToOne' &&\n options.attribute.relation !== 'morphToMany'\n ) {\n if (!options.value) return;\n\n const data = await serviceUtils.getRelationRestoreValue(\n options.value as Modules.Documents.AnyDocument,\n options.attribute as Schema.Attribute.RelationWithTarget\n );\n\n utils.set(options.key, data as Modules.Documents.AnyDocument);\n }\n\n if (options.attribute.type === 'media') {\n if (!options.value) return;\n\n const data = await serviceUtils.getMediaRestoreValue(\n options.value as Modules.Documents.AnyDocument\n );\n\n utils.set(options.key, data);\n }\n },\n {\n schema,\n getModel: strapi.getModel.bind(strapi),\n },\n dataWithoutAddedAttributes\n );\n\n const data = omit(dataWithoutMissingRelations, ['id', ...Object.keys(schemaDiff.removed)]);\n const restoredDocument = await strapi.documents(version.contentType).update({\n documentId: version.relatedDocumentId,\n locale: version.locale,\n data,\n });\n\n if (!restoredDocument) {\n throw new errors.ApplicationError('Failed to restore version');\n }\n\n return restoredDocument;\n },\n };\n};\n\nexport { createHistoryService };\n"],"names":["createHistoryService","strapi","query","db","HISTORY_VERSION_UID","serviceUtils","createServiceUtils","createVersion","historyVersionData","create","data","createdAt","Date","createdBy","requestContext","get","state","user","id","findVersionsPage","params","schema","getModel","contentType","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","results","versionRows","pagination","localeDictionary","Promise","all","findPage","select","where","$and","documentId","relatedDocumentId","orderBy","getLocaleDictionary","ids","map","version","versions","length","findMany","$in","populate","versionsById","Map","filter","Boolean","populateEntry","entry","traverseEntity","options","utils","attribute","value","currentValue","Array","isArray","type","remove","relation","target","adminUsers","userToPopulate","findOne","set","key","permissionChecker","getContentManagerService","userAbility","model","response","buildRelationReponse","sanitizedResults","media","sanitizeOutput","meta","buildMediaResponse","bind","formattedResults","result","unknownAttributes","getSchemaAttributesDiff","attributes","restoreVersion","versionId","contentTypeSchemaAttributes","schemaDiff","dataWithoutAddedAttributes","Object","keys","added","reduce","currentData","addedKey","structuredClone","omit","FIELDS_TO_IGNORE","dataWithoutMissingRelations","repeatable","getRelationRestoreValue","getMediaRestoreValue","removed","restoredDocument","documents","update","errors","ApplicationError"],"mappings":"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"}
1
+ {"version":3,"file":"history.mjs","sources":["../../../../server/src/history/services/history.ts"],"sourcesContent":["import type { Core, Data, Modules, Schema } from '@strapi/types';\nimport { emitAudit, errors, traverseEntity } from '@strapi/utils';\nimport { omit } from 'lodash';\n\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\nimport type { HistoryVersions } from '../../../../shared/contracts';\nimport type {\n CreateHistoryVersion,\n HistoryVersionDataResponse,\n} from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\nimport { getService as getContentManagerService } from '../../utils';\nimport { AUDITED_EVENTS, type HistoryRestoreEvent } from '../../audit-logs';\n\n// Needed because the query engine doesn't return any types yet\ntype HistoryVersionQueryResult = Omit<HistoryVersionDataResponse, 'locale'> &\n Pick<CreateHistoryVersion, 'locale'>;\n\nconst createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => {\n const query = strapi.db.query(HISTORY_VERSION_UID);\n const serviceUtils = createServiceUtils({ strapi });\n\n return {\n async createVersion(historyVersionData: HistoryVersions.CreateHistoryVersion) {\n await query.create({\n data: {\n ...historyVersionData,\n createdAt: new Date(),\n createdBy: strapi.requestContext.get()?.state?.user.id,\n },\n });\n },\n\n async findVersionsPage(params: HistoryVersions.GetHistoryVersions.Request): Promise<{\n results: HistoryVersions.HistoryVersionDataResponse[];\n pagination: HistoryVersions.Pagination;\n }> {\n const schema = strapi.getModel(params.query.contentType);\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(schema);\n const defaultLocale = await serviceUtils.getDefaultLocale();\n\n let locale = null;\n if (isLocalizedContentType) {\n locale = params.query.locale || defaultLocale;\n }\n\n // NOTE: We get the IDs first because sorting full rows runs MySQL/MariaDB out of sort memory\n // See: https://github.com/strapi/strapi/issues/27393\n const [{ results: versionRows, pagination }, localeDictionary] = await Promise.all([\n query.findPage({\n ...params.query,\n select: ['id'],\n where: {\n $and: [\n { contentType: params.query.contentType },\n ...(params.query.documentId ? [{ relatedDocumentId: params.query.documentId }] : []),\n ...(locale ? [{ locale }] : []),\n ],\n },\n orderBy: [{ createdAt: 'desc' }],\n }),\n serviceUtils.getLocaleDictionary(),\n ]);\n\n const ids = versionRows.map((version) => version.id);\n const versions = ids.length\n ? await query.findMany({\n where: { id: { $in: ids } },\n populate: ['createdBy'],\n })\n : [];\n const versionsById = new Map(versions.map((version) => [version.id, version]));\n const results = ids.map((id) => versionsById.get(id)).filter(Boolean);\n\n const populateEntry = async (entry: HistoryVersionQueryResult) => {\n return traverseEntity(\n async (options, utils) => {\n if (options.key === 'id' && options.schema.modelType === 'component') {\n // Ids on components throw an error when restoring\n utils.remove('id');\n return;\n }\n\n if (!options.attribute) return;\n if (!options.value) return;\n\n const currentValue: any[] = Array.isArray(options.value)\n ? options.value\n : [options.value];\n\n if (\n options.attribute.type === 'relation' &&\n // TODO: handle polymorphic relations\n options.attribute.relation !== 'morphToOne' &&\n options.attribute.relation !== 'morphToMany'\n ) {\n if (options.attribute.target === 'admin::user') {\n const adminUsers = await Promise.all(\n currentValue.map((userToPopulate) => {\n if (userToPopulate == null) {\n return null;\n }\n\n return strapi.db.query('admin::user').findOne({\n where: {\n ...(userToPopulate.id ? { id: userToPopulate.id } : {}),\n ...(userToPopulate.documentId\n ? { documentId: userToPopulate.documentId }\n : {}),\n },\n });\n })\n );\n\n utils.set(options.key, adminUsers as any);\n }\n\n const permissionChecker = getContentManagerService('permission-checker').create({\n userAbility: params.state.userAbility,\n model: options.attribute.target,\n });\n\n const response = await serviceUtils.buildRelationReponse(\n currentValue,\n options.attribute as Schema.Attribute.RelationWithTarget\n );\n const sanitizedResults = await Promise.all(\n response.results.map((media) => permissionChecker.sanitizeOutput(media))\n );\n\n utils.set(options.key, {\n results: sanitizedResults,\n meta: response.meta,\n });\n }\n\n if (options.attribute.type === 'media') {\n const permissionChecker = getContentManagerService('permission-checker').create({\n userAbility: params.state.userAbility,\n model: 'plugin::upload.file',\n });\n\n const response = await serviceUtils.buildMediaResponse(currentValue);\n const sanitizedResults = await Promise.all(\n response.results.map((media) => permissionChecker.sanitizeOutput(media))\n );\n\n utils.set(options.key, {\n results: sanitizedResults,\n meta: response.meta,\n });\n }\n },\n {\n schema,\n getModel: strapi.getModel.bind(strapi),\n },\n entry.data\n );\n };\n\n const formattedResults: any[] = await Promise.all(\n (results as HistoryVersionQueryResult[]).map(async (result) => {\n return {\n ...result,\n data: await populateEntry(result),\n meta: {\n unknownAttributes: serviceUtils.getSchemaAttributesDiff(\n result.schema,\n strapi.getModel(params.query.contentType).attributes\n ),\n },\n locale: result.locale ? localeDictionary[result.locale] : null,\n };\n })\n );\n\n return {\n results: formattedResults,\n pagination,\n };\n },\n\n async restoreVersion(versionId: Data.ID) {\n const version = await query.findOne({ where: { id: versionId } });\n\n if (version === null) {\n throw new errors.NotFoundError('History version not found');\n }\n\n const contentTypeSchemaAttributes = strapi.getModel(version.contentType).attributes;\n const schemaDiff = serviceUtils.getSchemaAttributesDiff(\n version.schema,\n contentTypeSchemaAttributes\n );\n\n // Set all added attribute values to null\n const dataWithoutAddedAttributes = Object.keys(schemaDiff.added).reduce(\n (currentData, addedKey) => {\n currentData[addedKey] = null;\n return currentData;\n },\n // Clone to avoid mutating the original version data\n structuredClone(version.data)\n );\n\n // Remove the schema attributes history should ignore\n const schema = structuredClone(version.schema);\n schema.attributes = omit(contentTypeSchemaAttributes, FIELDS_TO_IGNORE);\n\n const dataWithoutMissingRelations = await traverseEntity(\n async (options, utils) => {\n if (options.key === 'id' && options.schema.modelType === 'component') {\n // Ids on components throw an error when restoring\n utils.remove('id');\n return;\n }\n\n if (!options.attribute) return;\n\n if (options.attribute.type === 'component') {\n if (options.attribute.repeatable && options.value === null) {\n // Repeatable Components should always be an array\n utils.set(options.key, [] as any);\n }\n }\n\n if (options.attribute.type === 'dynamiczone') {\n if (options.value === null) {\n // Dynamic zones should always be an array\n utils.set(options.key, [] as any);\n }\n }\n\n if (\n options.attribute.type === 'relation' &&\n // TODO: handle polymorphic relations\n options.attribute.relation !== 'morphToOne' &&\n options.attribute.relation !== 'morphToMany'\n ) {\n if (!options.value) return;\n\n const data = await serviceUtils.getRelationRestoreValue(\n options.value as Modules.Documents.AnyDocument,\n options.attribute as Schema.Attribute.RelationWithTarget\n );\n\n utils.set(options.key, data as Modules.Documents.AnyDocument);\n }\n\n if (options.attribute.type === 'media') {\n if (!options.value) return;\n\n const data = await serviceUtils.getMediaRestoreValue(\n options.value as Modules.Documents.AnyDocument\n );\n\n utils.set(options.key, data);\n }\n },\n {\n schema,\n getModel: strapi.getModel.bind(strapi),\n },\n dataWithoutAddedAttributes\n );\n\n const data = omit(dataWithoutMissingRelations, ['id', ...Object.keys(schemaDiff.removed)]);\n const restoredDocument = await strapi.documents(version.contentType).update({\n documentId: version.relatedDocumentId,\n locale: version.locale,\n data,\n });\n\n if (!restoredDocument) {\n throw new errors.ApplicationError('Failed to restore version');\n }\n\n await emitAudit({ strapi }, AUDITED_EVENTS.ENTRY_HISTORY_RESTORE, {\n uid: version.contentType,\n documentId: restoredDocument.documentId,\n locale: version.locale ?? null,\n versionId: version.id,\n versionCreatedAt: new Date(version.createdAt).toISOString(),\n } satisfies HistoryRestoreEvent);\n\n return restoredDocument;\n },\n };\n};\n\nexport { createHistoryService };\n"],"names":["createHistoryService","strapi","query","db","HISTORY_VERSION_UID","serviceUtils","createServiceUtils","createVersion","historyVersionData","create","data","createdAt","Date","createdBy","requestContext","get","state","user","id","findVersionsPage","params","schema","getModel","contentType","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","results","versionRows","pagination","localeDictionary","Promise","all","findPage","select","where","$and","documentId","relatedDocumentId","orderBy","getLocaleDictionary","ids","map","version","versions","length","findMany","$in","populate","versionsById","Map","filter","Boolean","populateEntry","entry","traverseEntity","options","utils","key","modelType","remove","attribute","value","currentValue","Array","isArray","type","relation","target","adminUsers","userToPopulate","findOne","set","permissionChecker","getContentManagerService","userAbility","model","response","buildRelationReponse","sanitizedResults","media","sanitizeOutput","meta","buildMediaResponse","bind","formattedResults","result","unknownAttributes","getSchemaAttributesDiff","attributes","restoreVersion","versionId","errors","NotFoundError","contentTypeSchemaAttributes","schemaDiff","dataWithoutAddedAttributes","Object","keys","added","reduce","currentData","addedKey","structuredClone","omit","FIELDS_TO_IGNORE","dataWithoutMissingRelations","repeatable","getRelationRestoreValue","getMediaRestoreValue","removed","restoredDocument","documents","update","ApplicationError","emitAudit","AUDITED_EVENTS","ENTRY_HISTORY_RESTORE","uid","versionCreatedAt","toISOString"],"mappings":"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"}
@@ -32,27 +32,13 @@ var utils$1 = require('./utils.js');
32
32
  return true;
33
33
  };
34
34
  /**
35
- * Returns the content type schema (and its components schemas).
35
+ * Returns the content type schema.
36
36
  * Used to determine if changes were made in the content type builder since a history version was created.
37
37
  * And therefore which fields can be restored and which cannot.
38
38
  */ const getSchemas = (uid)=>{
39
39
  const attributesSchema = strapi.getModel(uid).attributes;
40
- // TODO: Handle nested components
41
- const componentsSchemas = Object.keys(attributesSchema).reduce((currentComponentSchemas, key)=>{
42
- const fieldSchema = attributesSchema[key];
43
- if (fieldSchema.type === 'component') {
44
- const componentSchema = strapi.getModel(fieldSchema.component).attributes;
45
- return {
46
- ...currentComponentSchemas,
47
- [fieldSchema.component]: componentSchema
48
- };
49
- }
50
- // Ignore anything that's not a component
51
- return currentComponentSchemas;
52
- }, {});
53
40
  return {
54
- schema: _.omit(attributesSchema, constants.FIELDS_TO_IGNORE),
55
- componentsSchemas
41
+ schema: _.omit(attributesSchema, constants.FIELDS_TO_IGNORE)
56
42
  };
57
43
  };
58
44
  const createLifecyclesService = ({ strapi: strapi1 })=>{
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycles.js","sources":["../../../../server/src/history/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\nimport { omit, castArray } from 'lodash';\n\nimport { getService } from '../utils';\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\n\nimport type { CreateHistoryVersion } from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\n\n/**\n * Filters out actions that should not create a history version.\n */\nconst shouldCreateHistoryVersion = (\n context: Modules.Documents.Middleware.Context\n): context is Modules.Documents.Middleware.Context & {\n action: 'create' | 'update' | 'clone' | 'publish' | 'unpublish' | 'discardDraft';\n contentType: UID.CollectionType;\n} => {\n // Ignore requests that are not related to the content manager\n if (!strapi.requestContext.get()?.request.url.startsWith('/content-manager')) {\n return false;\n }\n\n // NOTE: cannot do type narrowing with array includes\n if (\n context.action !== 'create' &&\n context.action !== 'update' &&\n context.action !== 'clone' &&\n context.action !== 'publish' &&\n context.action !== 'unpublish' &&\n context.action !== 'discardDraft'\n ) {\n return false;\n }\n\n /**\n * When a document is published, the draft version of the document is also updated.\n * It creates confusion for users because they see two history versions each publish action.\n * To avoid this, we silence the update action during a publish request,\n * so that they only see the published version of the document in the history.\n */\n if (\n context.action === 'update' &&\n strapi.requestContext.get()?.request.url.split('?')[0].endsWith('/actions/publish')\n ) {\n return false;\n }\n\n // Ignore content types not created by the user\n if (!context.contentType.uid.startsWith('api::')) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Returns the content type schema (and its components schemas).\n * Used to determine if changes were made in the content type builder since a history version was created.\n * And therefore which fields can be restored and which cannot.\n */\nconst getSchemas = (uid: UID.CollectionType) => {\n const attributesSchema = strapi.getModel(uid).attributes;\n\n // TODO: Handle nested components\n const componentsSchemas = Object.keys(attributesSchema).reduce(\n (currentComponentSchemas, key) => {\n const fieldSchema = attributesSchema[key];\n\n if (fieldSchema.type === 'component') {\n const componentSchema = strapi.getModel(fieldSchema.component).attributes;\n return {\n ...currentComponentSchemas,\n [fieldSchema.component]: componentSchema,\n };\n }\n\n // Ignore anything that's not a component\n return currentComponentSchemas;\n },\n {} as CreateHistoryVersion['componentsSchemas']\n );\n\n return {\n schema: omit(attributesSchema, FIELDS_TO_IGNORE) as CreateHistoryVersion['schema'],\n componentsSchemas,\n };\n};\n\nconst createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {\n const state: {\n isInitialized: boolean;\n } = {\n isInitialized: false,\n };\n\n const serviceUtils = createServiceUtils({ strapi });\n const { persistTablesWithPrefix } = strapi.service('admin::persist-tables');\n\n return {\n async bootstrap() {\n // Prevent initializing the service twice\n if (state.isInitialized) {\n return;\n }\n\n // Avoid data loss in case users temporarily don't have a license\n await persistTablesWithPrefix('strapi_history_versions');\n\n strapi.documents.use(async (context, next) => {\n const result = (await next()) as any;\n\n if (!shouldCreateHistoryVersion(context)) {\n return result;\n }\n\n // On create/clone actions, the documentId is not available before creating the action is executed\n const documentId =\n context.action === 'create' || context.action === 'clone'\n ? result.documentId\n : context.params.documentId;\n\n // Apply default locale if not available in the request\n const defaultLocale = await serviceUtils.getDefaultLocale();\n const locales = castArray(context.params?.locale || defaultLocale);\n if (!locales.length) {\n return result;\n }\n\n // All schemas related to the content type\n const uid = context.contentType.uid;\n const schemas = getSchemas(uid);\n const model = strapi.getModel(uid);\n\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);\n\n // Find all affected entries\n const localeEntries = await strapi.db.query(uid).findMany({\n where: {\n documentId,\n ...(isLocalizedContentType ? { locale: { $in: locales } } : {}),\n ...(contentTypes.hasDraftAndPublish(strapi.contentTypes[uid])\n ? { publishedAt: null }\n : {}),\n },\n populate: serviceUtils.getDeepPopulate(uid, true /* use database syntax */),\n });\n\n await strapi.db.transaction(async ({ onCommit }) => {\n // .createVersion() is executed asynchronously,\n // onCommit prevents creating a history version\n // when the transaction has already been committed\n onCommit(async () => {\n for (const entry of localeEntries) {\n const status = await serviceUtils.getVersionStatus(uid, entry);\n\n await getService(strapi, 'history').createVersion({\n contentType: uid,\n data: omit(entry, FIELDS_TO_IGNORE) as Modules.Documents.AnyDocument,\n relatedDocumentId: documentId,\n locale: entry.locale,\n status,\n ...schemas,\n });\n }\n });\n });\n\n return result;\n });\n\n // Schedule a job to delete expired history versions every day at midnight\n strapi.cron.add({\n deleteHistoryDaily: {\n async task() {\n const BATCH_SIZE = 1000;\n\n const retentionDaysInMilliseconds =\n serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;\n const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);\n\n // Delete in batches of 1000 to avoid a single query that\n // exhausts the DB connection pool and blocks other operations.\n let deleted: number;\n do {\n // Fetch up to BATCH_SIZE expired IDs\n const expiredVersions = await strapi.db.query(HISTORY_VERSION_UID).findMany({\n select: ['id'],\n where: {\n created_at: {\n $lt: expirationDate,\n },\n },\n limit: BATCH_SIZE,\n });\n\n const ids = expiredVersions.map((v: { id: number | string }) => v.id);\n deleted = ids.length;\n\n // Delete this batch by ID\n if (deleted > 0) {\n await strapi.db.query(HISTORY_VERSION_UID).deleteMany({\n where: {\n id: { $in: ids },\n },\n });\n }\n\n // If we got a full batch, there are likely more rows to delete — loop again.\n // If we got fewer, we've handled everything and can stop.\n } while (deleted >= BATCH_SIZE);\n },\n options: '0 0 * * *',\n },\n });\n\n state.isInitialized = true;\n },\n\n async destroy() {\n strapi.cron.remove('deleteHistoryDaily');\n },\n };\n};\n\nexport { createLifecyclesService };\n"],"names":["shouldCreateHistoryVersion","context","strapi","requestContext","get","request","url","startsWith","action","split","endsWith","contentType","uid","getSchemas","attributesSchema","getModel","attributes","componentsSchemas","Object","keys","reduce","currentComponentSchemas","key","fieldSchema","type","componentSchema","component","schema","omit","FIELDS_TO_IGNORE","createLifecyclesService","state","isInitialized","serviceUtils","createServiceUtils","persistTablesWithPrefix","service","bootstrap","documents","use","next","result","documentId","params","defaultLocale","getDefaultLocale","locales","castArray","locale","length","schemas","model","isLocalizedContentType","localeEntries","db","query","findMany","where","$in","contentTypes","hasDraftAndPublish","publishedAt","populate","getDeepPopulate","transaction","onCommit","entry","status","getVersionStatus","getService","createVersion","data","relatedDocumentId","cron","add","deleteHistoryDaily","task","BATCH_SIZE","retentionDaysInMilliseconds","getRetentionDays","expirationDate","Date","now","deleted","expiredVersions","HISTORY_VERSION_UID","select","created_at","$lt","limit","ids","map","v","id","deleteMany","options","destroy","remove"],"mappings":"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"}
1
+ {"version":3,"file":"lifecycles.js","sources":["../../../../server/src/history/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\nimport { omit, castArray } from 'lodash';\n\nimport { getService } from '../utils';\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\n\nimport type { CreateHistoryVersion } from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\n\n/**\n * Filters out actions that should not create a history version.\n */\nconst shouldCreateHistoryVersion = (\n context: Modules.Documents.Middleware.Context\n): context is Modules.Documents.Middleware.Context & {\n action: 'create' | 'update' | 'clone' | 'publish' | 'unpublish' | 'discardDraft';\n contentType: UID.CollectionType;\n} => {\n // Ignore requests that are not related to the content manager\n if (!strapi.requestContext.get()?.request.url.startsWith('/content-manager')) {\n return false;\n }\n\n // NOTE: cannot do type narrowing with array includes\n if (\n context.action !== 'create' &&\n context.action !== 'update' &&\n context.action !== 'clone' &&\n context.action !== 'publish' &&\n context.action !== 'unpublish' &&\n context.action !== 'discardDraft'\n ) {\n return false;\n }\n\n /**\n * When a document is published, the draft version of the document is also updated.\n * It creates confusion for users because they see two history versions each publish action.\n * To avoid this, we silence the update action during a publish request,\n * so that they only see the published version of the document in the history.\n */\n if (\n context.action === 'update' &&\n strapi.requestContext.get()?.request.url.split('?')[0].endsWith('/actions/publish')\n ) {\n return false;\n }\n\n // Ignore content types not created by the user\n if (!context.contentType.uid.startsWith('api::')) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Returns the content type schema.\n * Used to determine if changes were made in the content type builder since a history version was created.\n * And therefore which fields can be restored and which cannot.\n */\nconst getSchemas = (uid: UID.CollectionType) => {\n const attributesSchema = strapi.getModel(uid).attributes;\n\n return {\n schema: omit(attributesSchema, FIELDS_TO_IGNORE) as CreateHistoryVersion['schema'],\n };\n};\n\nconst createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {\n const state: {\n isInitialized: boolean;\n } = {\n isInitialized: false,\n };\n\n const serviceUtils = createServiceUtils({ strapi });\n const { persistTablesWithPrefix } = strapi.service('admin::persist-tables');\n\n return {\n async bootstrap() {\n // Prevent initializing the service twice\n if (state.isInitialized) {\n return;\n }\n\n // Avoid data loss in case users temporarily don't have a license\n await persistTablesWithPrefix('strapi_history_versions');\n\n strapi.documents.use(async (context, next) => {\n const result = (await next()) as any;\n\n if (!shouldCreateHistoryVersion(context)) {\n return result;\n }\n\n // On create/clone actions, the documentId is not available before creating the action is executed\n const documentId =\n context.action === 'create' || context.action === 'clone'\n ? result.documentId\n : context.params.documentId;\n\n // Apply default locale if not available in the request\n const defaultLocale = await serviceUtils.getDefaultLocale();\n const locales = castArray(context.params?.locale || defaultLocale);\n if (!locales.length) {\n return result;\n }\n\n // All schemas related to the content type\n const uid = context.contentType.uid;\n const schemas = getSchemas(uid);\n const model = strapi.getModel(uid);\n\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);\n\n // Find all affected entries\n const localeEntries = await strapi.db.query(uid).findMany({\n where: {\n documentId,\n ...(isLocalizedContentType ? { locale: { $in: locales } } : {}),\n ...(contentTypes.hasDraftAndPublish(strapi.contentTypes[uid])\n ? { publishedAt: null }\n : {}),\n },\n populate: serviceUtils.getDeepPopulate(uid, true /* use database syntax */),\n });\n\n await strapi.db.transaction(async ({ onCommit }) => {\n // .createVersion() is executed asynchronously,\n // onCommit prevents creating a history version\n // when the transaction has already been committed\n onCommit(async () => {\n for (const entry of localeEntries) {\n const status = await serviceUtils.getVersionStatus(uid, entry);\n\n await getService(strapi, 'history').createVersion({\n contentType: uid,\n data: omit(entry, FIELDS_TO_IGNORE) as Modules.Documents.AnyDocument,\n relatedDocumentId: documentId,\n locale: entry.locale,\n status,\n ...schemas,\n });\n }\n });\n });\n\n return result;\n });\n\n // Schedule a job to delete expired history versions every day at midnight\n strapi.cron.add({\n deleteHistoryDaily: {\n async task() {\n const BATCH_SIZE = 1000;\n\n const retentionDaysInMilliseconds =\n serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;\n const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);\n\n // Delete in batches of 1000 to avoid a single query that\n // exhausts the DB connection pool and blocks other operations.\n let deleted: number;\n do {\n // Fetch up to BATCH_SIZE expired IDs\n const expiredVersions = await strapi.db.query(HISTORY_VERSION_UID).findMany({\n select: ['id'],\n where: {\n created_at: {\n $lt: expirationDate,\n },\n },\n limit: BATCH_SIZE,\n });\n\n const ids = expiredVersions.map((v: { id: number | string }) => v.id);\n deleted = ids.length;\n\n // Delete this batch by ID\n if (deleted > 0) {\n await strapi.db.query(HISTORY_VERSION_UID).deleteMany({\n where: {\n id: { $in: ids },\n },\n });\n }\n\n // If we got a full batch, there are likely more rows to delete — loop again.\n // If we got fewer, we've handled everything and can stop.\n } while (deleted >= BATCH_SIZE);\n },\n options: '0 0 * * *',\n },\n });\n\n state.isInitialized = true;\n },\n\n async destroy() {\n strapi.cron.remove('deleteHistoryDaily');\n },\n };\n};\n\nexport { createLifecyclesService };\n"],"names":["shouldCreateHistoryVersion","context","strapi","requestContext","get","request","url","startsWith","action","split","endsWith","contentType","uid","getSchemas","attributesSchema","getModel","attributes","schema","omit","FIELDS_TO_IGNORE","createLifecyclesService","state","isInitialized","serviceUtils","createServiceUtils","persistTablesWithPrefix","service","bootstrap","documents","use","next","result","documentId","params","defaultLocale","getDefaultLocale","locales","castArray","locale","length","schemas","model","isLocalizedContentType","localeEntries","db","query","findMany","where","$in","contentTypes","hasDraftAndPublish","publishedAt","populate","getDeepPopulate","transaction","onCommit","entry","status","getVersionStatus","getService","createVersion","data","relatedDocumentId","cron","add","deleteHistoryDaily","task","BATCH_SIZE","retentionDaysInMilliseconds","getRetentionDays","expirationDate","Date","now","deleted","expiredVersions","HISTORY_VERSION_UID","select","created_at","$lt","limit","ids","map","v","id","deleteMany","options","destroy","remove"],"mappings":"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"}
@@ -30,27 +30,13 @@ import { createServiceUtils } from './utils.mjs';
30
30
  return true;
31
31
  };
32
32
  /**
33
- * Returns the content type schema (and its components schemas).
33
+ * Returns the content type schema.
34
34
  * Used to determine if changes were made in the content type builder since a history version was created.
35
35
  * And therefore which fields can be restored and which cannot.
36
36
  */ const getSchemas = (uid)=>{
37
37
  const attributesSchema = strapi.getModel(uid).attributes;
38
- // TODO: Handle nested components
39
- const componentsSchemas = Object.keys(attributesSchema).reduce((currentComponentSchemas, key)=>{
40
- const fieldSchema = attributesSchema[key];
41
- if (fieldSchema.type === 'component') {
42
- const componentSchema = strapi.getModel(fieldSchema.component).attributes;
43
- return {
44
- ...currentComponentSchemas,
45
- [fieldSchema.component]: componentSchema
46
- };
47
- }
48
- // Ignore anything that's not a component
49
- return currentComponentSchemas;
50
- }, {});
51
38
  return {
52
- schema: omit(attributesSchema, FIELDS_TO_IGNORE),
53
- componentsSchemas
39
+ schema: omit(attributesSchema, FIELDS_TO_IGNORE)
54
40
  };
55
41
  };
56
42
  const createLifecyclesService = ({ strapi: strapi1 })=>{
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycles.mjs","sources":["../../../../server/src/history/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\nimport { omit, castArray } from 'lodash';\n\nimport { getService } from '../utils';\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\n\nimport type { CreateHistoryVersion } from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\n\n/**\n * Filters out actions that should not create a history version.\n */\nconst shouldCreateHistoryVersion = (\n context: Modules.Documents.Middleware.Context\n): context is Modules.Documents.Middleware.Context & {\n action: 'create' | 'update' | 'clone' | 'publish' | 'unpublish' | 'discardDraft';\n contentType: UID.CollectionType;\n} => {\n // Ignore requests that are not related to the content manager\n if (!strapi.requestContext.get()?.request.url.startsWith('/content-manager')) {\n return false;\n }\n\n // NOTE: cannot do type narrowing with array includes\n if (\n context.action !== 'create' &&\n context.action !== 'update' &&\n context.action !== 'clone' &&\n context.action !== 'publish' &&\n context.action !== 'unpublish' &&\n context.action !== 'discardDraft'\n ) {\n return false;\n }\n\n /**\n * When a document is published, the draft version of the document is also updated.\n * It creates confusion for users because they see two history versions each publish action.\n * To avoid this, we silence the update action during a publish request,\n * so that they only see the published version of the document in the history.\n */\n if (\n context.action === 'update' &&\n strapi.requestContext.get()?.request.url.split('?')[0].endsWith('/actions/publish')\n ) {\n return false;\n }\n\n // Ignore content types not created by the user\n if (!context.contentType.uid.startsWith('api::')) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Returns the content type schema (and its components schemas).\n * Used to determine if changes were made in the content type builder since a history version was created.\n * And therefore which fields can be restored and which cannot.\n */\nconst getSchemas = (uid: UID.CollectionType) => {\n const attributesSchema = strapi.getModel(uid).attributes;\n\n // TODO: Handle nested components\n const componentsSchemas = Object.keys(attributesSchema).reduce(\n (currentComponentSchemas, key) => {\n const fieldSchema = attributesSchema[key];\n\n if (fieldSchema.type === 'component') {\n const componentSchema = strapi.getModel(fieldSchema.component).attributes;\n return {\n ...currentComponentSchemas,\n [fieldSchema.component]: componentSchema,\n };\n }\n\n // Ignore anything that's not a component\n return currentComponentSchemas;\n },\n {} as CreateHistoryVersion['componentsSchemas']\n );\n\n return {\n schema: omit(attributesSchema, FIELDS_TO_IGNORE) as CreateHistoryVersion['schema'],\n componentsSchemas,\n };\n};\n\nconst createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {\n const state: {\n isInitialized: boolean;\n } = {\n isInitialized: false,\n };\n\n const serviceUtils = createServiceUtils({ strapi });\n const { persistTablesWithPrefix } = strapi.service('admin::persist-tables');\n\n return {\n async bootstrap() {\n // Prevent initializing the service twice\n if (state.isInitialized) {\n return;\n }\n\n // Avoid data loss in case users temporarily don't have a license\n await persistTablesWithPrefix('strapi_history_versions');\n\n strapi.documents.use(async (context, next) => {\n const result = (await next()) as any;\n\n if (!shouldCreateHistoryVersion(context)) {\n return result;\n }\n\n // On create/clone actions, the documentId is not available before creating the action is executed\n const documentId =\n context.action === 'create' || context.action === 'clone'\n ? result.documentId\n : context.params.documentId;\n\n // Apply default locale if not available in the request\n const defaultLocale = await serviceUtils.getDefaultLocale();\n const locales = castArray(context.params?.locale || defaultLocale);\n if (!locales.length) {\n return result;\n }\n\n // All schemas related to the content type\n const uid = context.contentType.uid;\n const schemas = getSchemas(uid);\n const model = strapi.getModel(uid);\n\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);\n\n // Find all affected entries\n const localeEntries = await strapi.db.query(uid).findMany({\n where: {\n documentId,\n ...(isLocalizedContentType ? { locale: { $in: locales } } : {}),\n ...(contentTypes.hasDraftAndPublish(strapi.contentTypes[uid])\n ? { publishedAt: null }\n : {}),\n },\n populate: serviceUtils.getDeepPopulate(uid, true /* use database syntax */),\n });\n\n await strapi.db.transaction(async ({ onCommit }) => {\n // .createVersion() is executed asynchronously,\n // onCommit prevents creating a history version\n // when the transaction has already been committed\n onCommit(async () => {\n for (const entry of localeEntries) {\n const status = await serviceUtils.getVersionStatus(uid, entry);\n\n await getService(strapi, 'history').createVersion({\n contentType: uid,\n data: omit(entry, FIELDS_TO_IGNORE) as Modules.Documents.AnyDocument,\n relatedDocumentId: documentId,\n locale: entry.locale,\n status,\n ...schemas,\n });\n }\n });\n });\n\n return result;\n });\n\n // Schedule a job to delete expired history versions every day at midnight\n strapi.cron.add({\n deleteHistoryDaily: {\n async task() {\n const BATCH_SIZE = 1000;\n\n const retentionDaysInMilliseconds =\n serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;\n const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);\n\n // Delete in batches of 1000 to avoid a single query that\n // exhausts the DB connection pool and blocks other operations.\n let deleted: number;\n do {\n // Fetch up to BATCH_SIZE expired IDs\n const expiredVersions = await strapi.db.query(HISTORY_VERSION_UID).findMany({\n select: ['id'],\n where: {\n created_at: {\n $lt: expirationDate,\n },\n },\n limit: BATCH_SIZE,\n });\n\n const ids = expiredVersions.map((v: { id: number | string }) => v.id);\n deleted = ids.length;\n\n // Delete this batch by ID\n if (deleted > 0) {\n await strapi.db.query(HISTORY_VERSION_UID).deleteMany({\n where: {\n id: { $in: ids },\n },\n });\n }\n\n // If we got a full batch, there are likely more rows to delete — loop again.\n // If we got fewer, we've handled everything and can stop.\n } while (deleted >= BATCH_SIZE);\n },\n options: '0 0 * * *',\n },\n });\n\n state.isInitialized = true;\n },\n\n async destroy() {\n strapi.cron.remove('deleteHistoryDaily');\n },\n };\n};\n\nexport { createLifecyclesService };\n"],"names":["shouldCreateHistoryVersion","context","strapi","requestContext","get","request","url","startsWith","action","split","endsWith","contentType","uid","getSchemas","attributesSchema","getModel","attributes","componentsSchemas","Object","keys","reduce","currentComponentSchemas","key","fieldSchema","type","componentSchema","component","schema","omit","FIELDS_TO_IGNORE","createLifecyclesService","state","isInitialized","serviceUtils","createServiceUtils","persistTablesWithPrefix","service","bootstrap","documents","use","next","result","documentId","params","defaultLocale","getDefaultLocale","locales","castArray","locale","length","schemas","model","isLocalizedContentType","localeEntries","db","query","findMany","where","$in","contentTypes","hasDraftAndPublish","publishedAt","populate","getDeepPopulate","transaction","onCommit","entry","status","getVersionStatus","getService","createVersion","data","relatedDocumentId","cron","add","deleteHistoryDaily","task","BATCH_SIZE","retentionDaysInMilliseconds","getRetentionDays","expirationDate","Date","now","deleted","expiredVersions","HISTORY_VERSION_UID","select","created_at","$lt","limit","ids","map","v","id","deleteMany","options","destroy","remove"],"mappings":"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"}
1
+ {"version":3,"file":"lifecycles.mjs","sources":["../../../../server/src/history/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\nimport { omit, castArray } from 'lodash';\n\nimport { getService } from '../utils';\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\n\nimport type { CreateHistoryVersion } from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\n\n/**\n * Filters out actions that should not create a history version.\n */\nconst shouldCreateHistoryVersion = (\n context: Modules.Documents.Middleware.Context\n): context is Modules.Documents.Middleware.Context & {\n action: 'create' | 'update' | 'clone' | 'publish' | 'unpublish' | 'discardDraft';\n contentType: UID.CollectionType;\n} => {\n // Ignore requests that are not related to the content manager\n if (!strapi.requestContext.get()?.request.url.startsWith('/content-manager')) {\n return false;\n }\n\n // NOTE: cannot do type narrowing with array includes\n if (\n context.action !== 'create' &&\n context.action !== 'update' &&\n context.action !== 'clone' &&\n context.action !== 'publish' &&\n context.action !== 'unpublish' &&\n context.action !== 'discardDraft'\n ) {\n return false;\n }\n\n /**\n * When a document is published, the draft version of the document is also updated.\n * It creates confusion for users because they see two history versions each publish action.\n * To avoid this, we silence the update action during a publish request,\n * so that they only see the published version of the document in the history.\n */\n if (\n context.action === 'update' &&\n strapi.requestContext.get()?.request.url.split('?')[0].endsWith('/actions/publish')\n ) {\n return false;\n }\n\n // Ignore content types not created by the user\n if (!context.contentType.uid.startsWith('api::')) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Returns the content type schema.\n * Used to determine if changes were made in the content type builder since a history version was created.\n * And therefore which fields can be restored and which cannot.\n */\nconst getSchemas = (uid: UID.CollectionType) => {\n const attributesSchema = strapi.getModel(uid).attributes;\n\n return {\n schema: omit(attributesSchema, FIELDS_TO_IGNORE) as CreateHistoryVersion['schema'],\n };\n};\n\nconst createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {\n const state: {\n isInitialized: boolean;\n } = {\n isInitialized: false,\n };\n\n const serviceUtils = createServiceUtils({ strapi });\n const { persistTablesWithPrefix } = strapi.service('admin::persist-tables');\n\n return {\n async bootstrap() {\n // Prevent initializing the service twice\n if (state.isInitialized) {\n return;\n }\n\n // Avoid data loss in case users temporarily don't have a license\n await persistTablesWithPrefix('strapi_history_versions');\n\n strapi.documents.use(async (context, next) => {\n const result = (await next()) as any;\n\n if (!shouldCreateHistoryVersion(context)) {\n return result;\n }\n\n // On create/clone actions, the documentId is not available before creating the action is executed\n const documentId =\n context.action === 'create' || context.action === 'clone'\n ? result.documentId\n : context.params.documentId;\n\n // Apply default locale if not available in the request\n const defaultLocale = await serviceUtils.getDefaultLocale();\n const locales = castArray(context.params?.locale || defaultLocale);\n if (!locales.length) {\n return result;\n }\n\n // All schemas related to the content type\n const uid = context.contentType.uid;\n const schemas = getSchemas(uid);\n const model = strapi.getModel(uid);\n\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);\n\n // Find all affected entries\n const localeEntries = await strapi.db.query(uid).findMany({\n where: {\n documentId,\n ...(isLocalizedContentType ? { locale: { $in: locales } } : {}),\n ...(contentTypes.hasDraftAndPublish(strapi.contentTypes[uid])\n ? { publishedAt: null }\n : {}),\n },\n populate: serviceUtils.getDeepPopulate(uid, true /* use database syntax */),\n });\n\n await strapi.db.transaction(async ({ onCommit }) => {\n // .createVersion() is executed asynchronously,\n // onCommit prevents creating a history version\n // when the transaction has already been committed\n onCommit(async () => {\n for (const entry of localeEntries) {\n const status = await serviceUtils.getVersionStatus(uid, entry);\n\n await getService(strapi, 'history').createVersion({\n contentType: uid,\n data: omit(entry, FIELDS_TO_IGNORE) as Modules.Documents.AnyDocument,\n relatedDocumentId: documentId,\n locale: entry.locale,\n status,\n ...schemas,\n });\n }\n });\n });\n\n return result;\n });\n\n // Schedule a job to delete expired history versions every day at midnight\n strapi.cron.add({\n deleteHistoryDaily: {\n async task() {\n const BATCH_SIZE = 1000;\n\n const retentionDaysInMilliseconds =\n serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;\n const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);\n\n // Delete in batches of 1000 to avoid a single query that\n // exhausts the DB connection pool and blocks other operations.\n let deleted: number;\n do {\n // Fetch up to BATCH_SIZE expired IDs\n const expiredVersions = await strapi.db.query(HISTORY_VERSION_UID).findMany({\n select: ['id'],\n where: {\n created_at: {\n $lt: expirationDate,\n },\n },\n limit: BATCH_SIZE,\n });\n\n const ids = expiredVersions.map((v: { id: number | string }) => v.id);\n deleted = ids.length;\n\n // Delete this batch by ID\n if (deleted > 0) {\n await strapi.db.query(HISTORY_VERSION_UID).deleteMany({\n where: {\n id: { $in: ids },\n },\n });\n }\n\n // If we got a full batch, there are likely more rows to delete — loop again.\n // If we got fewer, we've handled everything and can stop.\n } while (deleted >= BATCH_SIZE);\n },\n options: '0 0 * * *',\n },\n });\n\n state.isInitialized = true;\n },\n\n async destroy() {\n strapi.cron.remove('deleteHistoryDaily');\n },\n };\n};\n\nexport { createLifecyclesService };\n"],"names":["shouldCreateHistoryVersion","context","strapi","requestContext","get","request","url","startsWith","action","split","endsWith","contentType","uid","getSchemas","attributesSchema","getModel","attributes","schema","omit","FIELDS_TO_IGNORE","createLifecyclesService","state","isInitialized","serviceUtils","createServiceUtils","persistTablesWithPrefix","service","bootstrap","documents","use","next","result","documentId","params","defaultLocale","getDefaultLocale","locales","castArray","locale","length","schemas","model","isLocalizedContentType","localeEntries","db","query","findMany","where","$in","contentTypes","hasDraftAndPublish","publishedAt","populate","getDeepPopulate","transaction","onCommit","entry","status","getVersionStatus","getService","createVersion","data","relatedDocumentId","cron","add","deleteHistoryDaily","task","BATCH_SIZE","retentionDaysInMilliseconds","getRetentionDays","expirationDate","Date","now","deleted","expiredVersions","HISTORY_VERSION_UID","select","created_at","$lt","limit","ids","map","v","id","deleteMany","options","destroy","remove"],"mappings":"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"}
@@ -2,6 +2,7 @@
2
2
 
3
3
  var index = require('./history/index.js');
4
4
  var index$1 = require('./preview/index.js');
5
+ var index$2 = require('./custom-order/index.js');
5
6
  var renameFields = require('./services/configuration/rename-fields.js');
6
7
 
7
8
  const register = async ({ strapi })=>{
@@ -16,6 +17,9 @@ const register = async ({ strapi })=>{
16
17
  await index$1.register?.({
17
18
  strapi
18
19
  });
20
+ await index$2.register?.({
21
+ strapi
22
+ });
19
23
  };
20
24
 
21
25
  module.exports = register;
@@ -1 +1 @@
1
- {"version":3,"file":"register.js","sources":["../../server/src/register.ts"],"sourcesContent":["import type { Plugin } from '@strapi/types';\nimport history from './history';\nimport preview from './preview';\nimport { createContentManagerConfigurationRenamer } from './services/configuration/rename-fields';\n\nconst register: Plugin.LoadedPlugin['register'] = async ({ strapi }) => {\n // Before user migrations run, so a generated rename migration can rewrite the\n // saved layouts and leave the old-to-new map for each admin's browser.\n strapi.db.schema.registerAttributeRenameHandler(\n createContentManagerConfigurationRenamer({ strapi })\n );\n\n await history.register?.({ strapi });\n await preview.register?.({ strapi });\n};\n\nexport default register;\n"],"names":["register","strapi","db","schema","registerAttributeRenameHandler","createContentManagerConfigurationRenamer","history","preview"],"mappings":";;;;;;AAKA,MAAMA,QAAAA,GAA4C,OAAO,EAAEC,MAAM,EAAE,GAAA;;;AAGjEA,IAAAA,MAAAA,CAAOC,EAAE,CAACC,MAAM,CAACC,8BAA8B,CAC7CC,qDAAAA,CAAyC;AAAEJ,QAAAA;AAAO,KAAA,CAAA,CAAA;IAGpD,MAAMK,KAAAA,CAAQN,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;IAClC,MAAMM,OAAAA,CAAQP,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;AACpC;;;;"}
1
+ {"version":3,"file":"register.js","sources":["../../server/src/register.ts"],"sourcesContent":["import type { Plugin } from '@strapi/types';\nimport history from './history';\nimport preview from './preview';\nimport customOrder from './custom-order';\nimport { createContentManagerConfigurationRenamer } from './services/configuration/rename-fields';\n\nconst register: Plugin.LoadedPlugin['register'] = async ({ strapi }) => {\n // Before user migrations run, so a generated rename migration can rewrite the\n // saved layouts and leave the old-to-new map for each admin's browser.\n strapi.db.schema.registerAttributeRenameHandler(\n createContentManagerConfigurationRenamer({ strapi })\n );\n\n await history.register?.({ strapi });\n await preview.register?.({ strapi });\n await customOrder.register?.({ strapi });\n};\n\nexport default register;\n"],"names":["register","strapi","db","schema","registerAttributeRenameHandler","createContentManagerConfigurationRenamer","history","preview","customOrder"],"mappings":";;;;;;;AAMA,MAAMA,QAAAA,GAA4C,OAAO,EAAEC,MAAM,EAAE,GAAA;;;AAGjEA,IAAAA,MAAAA,CAAOC,EAAE,CAACC,MAAM,CAACC,8BAA8B,CAC7CC,qDAAAA,CAAyC;AAAEJ,QAAAA;AAAO,KAAA,CAAA,CAAA;IAGpD,MAAMK,KAAAA,CAAQN,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;IAClC,MAAMM,OAAAA,CAAQP,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;IAClC,MAAMO,OAAAA,CAAYR,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;AACxC;;;;"}
@@ -1,5 +1,6 @@
1
1
  import history from './history/index.mjs';
2
2
  import preview from './preview/index.mjs';
3
+ import feature from './custom-order/index.mjs';
3
4
  import { createContentManagerConfigurationRenamer } from './services/configuration/rename-fields.mjs';
4
5
 
5
6
  const register = async ({ strapi })=>{
@@ -14,6 +15,9 @@ const register = async ({ strapi })=>{
14
15
  await preview.register?.({
15
16
  strapi
16
17
  });
18
+ await feature.register?.({
19
+ strapi
20
+ });
17
21
  };
18
22
 
19
23
  export { register as default };
@@ -1 +1 @@
1
- {"version":3,"file":"register.mjs","sources":["../../server/src/register.ts"],"sourcesContent":["import type { Plugin } from '@strapi/types';\nimport history from './history';\nimport preview from './preview';\nimport { createContentManagerConfigurationRenamer } from './services/configuration/rename-fields';\n\nconst register: Plugin.LoadedPlugin['register'] = async ({ strapi }) => {\n // Before user migrations run, so a generated rename migration can rewrite the\n // saved layouts and leave the old-to-new map for each admin's browser.\n strapi.db.schema.registerAttributeRenameHandler(\n createContentManagerConfigurationRenamer({ strapi })\n );\n\n await history.register?.({ strapi });\n await preview.register?.({ strapi });\n};\n\nexport default register;\n"],"names":["register","strapi","db","schema","registerAttributeRenameHandler","createContentManagerConfigurationRenamer","history","preview"],"mappings":";;;;AAKA,MAAMA,QAAAA,GAA4C,OAAO,EAAEC,MAAM,EAAE,GAAA;;;AAGjEA,IAAAA,MAAAA,CAAOC,EAAE,CAACC,MAAM,CAACC,8BAA8B,CAC7CC,wCAAAA,CAAyC;AAAEJ,QAAAA;AAAO,KAAA,CAAA,CAAA;IAGpD,MAAMK,OAAAA,CAAQN,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;IAClC,MAAMM,OAAAA,CAAQP,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;AACpC;;;;"}
1
+ {"version":3,"file":"register.mjs","sources":["../../server/src/register.ts"],"sourcesContent":["import type { Plugin } from '@strapi/types';\nimport history from './history';\nimport preview from './preview';\nimport customOrder from './custom-order';\nimport { createContentManagerConfigurationRenamer } from './services/configuration/rename-fields';\n\nconst register: Plugin.LoadedPlugin['register'] = async ({ strapi }) => {\n // Before user migrations run, so a generated rename migration can rewrite the\n // saved layouts and leave the old-to-new map for each admin's browser.\n strapi.db.schema.registerAttributeRenameHandler(\n createContentManagerConfigurationRenamer({ strapi })\n );\n\n await history.register?.({ strapi });\n await preview.register?.({ strapi });\n await customOrder.register?.({ strapi });\n};\n\nexport default register;\n"],"names":["register","strapi","db","schema","registerAttributeRenameHandler","createContentManagerConfigurationRenamer","history","preview","customOrder"],"mappings":";;;;;AAMA,MAAMA,QAAAA,GAA4C,OAAO,EAAEC,MAAM,EAAE,GAAA;;;AAGjEA,IAAAA,MAAAA,CAAOC,EAAE,CAACC,MAAM,CAACC,8BAA8B,CAC7CC,wCAAAA,CAAyC;AAAEJ,QAAAA;AAAO,KAAA,CAAA,CAAA;IAGpD,MAAMK,OAAAA,CAAQN,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;IAClC,MAAMM,OAAAA,CAAQP,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;IAClC,MAAMO,OAAAA,CAAYR,QAAQ,GAAG;AAAEC,QAAAA;AAAO,KAAA,CAAA;AACxC;;;;"}
@@ -2,12 +2,14 @@
2
2
 
3
3
  var admin = require('./admin.js');
4
4
  var index = require('../history/index.js');
5
- var index$2 = require('../preview/index.js');
5
+ var index$3 = require('../preview/index.js');
6
6
  var index$1 = require('../homepage/index.js');
7
+ var index$2 = require('../custom-order/index.js');
7
8
 
8
9
  var routes = {
9
10
  admin,
10
11
  ...index.routes ? index.routes : {},
12
+ ...index$3.routes ? index$3.routes : {},
11
13
  ...index$2.routes ? index$2.routes : {},
12
14
  ...index$1.routes
13
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../server/src/routes/index.ts"],"sourcesContent":["import admin from './admin';\nimport history from '../history';\nimport preview from '../preview';\nimport homepage from '../homepage';\n\nexport default {\n admin,\n ...(history.routes ? history.routes : {}),\n ...(preview.routes ? preview.routes : {}),\n ...homepage.routes,\n};\n"],"names":["admin","history","routes","preview","homepage"],"mappings":";;;;;;;AAKA,aAAe;AACbA,IAAAA,KAAAA;AACA,IAAA,GAAIC,MAAQC,MAAM,GAAGD,MAAQC,MAAM,GAAG,EAAE;AACxC,IAAA,GAAIC,QAAQD,MAAM,GAAGC,QAAQD,MAAM,GAAG,EAAE;AACxC,IAAA,GAAGE,QAASF;AACd,CAAA;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../server/src/routes/index.ts"],"sourcesContent":["import admin from './admin';\nimport history from '../history';\nimport preview from '../preview';\nimport homepage from '../homepage';\nimport customOrder from '../custom-order';\n\nexport default {\n admin,\n ...(history.routes ? history.routes : {}),\n ...(preview.routes ? preview.routes : {}),\n ...(customOrder.routes ? customOrder.routes : {}),\n ...homepage.routes,\n};\n"],"names":["admin","history","routes","preview","customOrder","homepage"],"mappings":";;;;;;;;AAMA,aAAe;AACbA,IAAAA,KAAAA;AACA,IAAA,GAAIC,MAAQC,MAAM,GAAGD,MAAQC,MAAM,GAAG,EAAE;AACxC,IAAA,GAAIC,QAAQD,MAAM,GAAGC,QAAQD,MAAM,GAAG,EAAE;AACxC,IAAA,GAAIE,QAAYF,MAAM,GAAGE,QAAYF,MAAM,GAAG,EAAE;AAChD,IAAA,GAAGG,QAASH;AACd,CAAA;;;;"}
@@ -2,11 +2,13 @@ import admin from './admin.mjs';
2
2
  import history from '../history/index.mjs';
3
3
  import preview from '../preview/index.mjs';
4
4
  import homepage from '../homepage/index.mjs';
5
+ import feature from '../custom-order/index.mjs';
5
6
 
6
7
  var routes = {
7
8
  admin,
8
9
  ...history.routes ? history.routes : {},
9
10
  ...preview.routes ? preview.routes : {},
11
+ ...feature.routes ? feature.routes : {},
10
12
  ...homepage.routes
11
13
  };
12
14
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../server/src/routes/index.ts"],"sourcesContent":["import admin from './admin';\nimport history from '../history';\nimport preview from '../preview';\nimport homepage from '../homepage';\n\nexport default {\n admin,\n ...(history.routes ? history.routes : {}),\n ...(preview.routes ? preview.routes : {}),\n ...homepage.routes,\n};\n"],"names":["admin","history","routes","preview","homepage"],"mappings":";;;;;AAKA,aAAe;AACbA,IAAAA,KAAAA;AACA,IAAA,GAAIC,QAAQC,MAAM,GAAGD,QAAQC,MAAM,GAAG,EAAE;AACxC,IAAA,GAAIC,QAAQD,MAAM,GAAGC,QAAQD,MAAM,GAAG,EAAE;AACxC,IAAA,GAAGE,SAASF;AACd,CAAA;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../server/src/routes/index.ts"],"sourcesContent":["import admin from './admin';\nimport history from '../history';\nimport preview from '../preview';\nimport homepage from '../homepage';\nimport customOrder from '../custom-order';\n\nexport default {\n admin,\n ...(history.routes ? history.routes : {}),\n ...(preview.routes ? preview.routes : {}),\n ...(customOrder.routes ? customOrder.routes : {}),\n ...homepage.routes,\n};\n"],"names":["admin","history","routes","preview","customOrder","homepage"],"mappings":";;;;;;AAMA,aAAe;AACbA,IAAAA,KAAAA;AACA,IAAA,GAAIC,QAAQC,MAAM,GAAGD,QAAQC,MAAM,GAAG,EAAE;AACxC,IAAA,GAAIC,QAAQD,MAAM,GAAGC,QAAQD,MAAM,GAAG,EAAE;AACxC,IAAA,GAAIE,QAAYF,MAAM,GAAGE,QAAYF,MAAM,GAAG,EAAE;AAChD,IAAA,GAAGG,SAASH;AACd,CAAA;;;;"}
@@ -30,10 +30,10 @@ const service = ({ strapi: strapi1 })=>({
30
30
  ({ isDisplayed })=>isDisplayed === true);
31
31
  },
32
32
  findContentTypesByKind (kind) {
33
- if (!kind) {
33
+ if (kind === undefined || kind === null) {
34
34
  return this.findAllContentTypes();
35
35
  }
36
- // @ts-expect-error TODO when adding types
36
+ // @ts-expect-error should be resolved from data-mapper types
37
37
  return this.findAllContentTypes().filter(strapiUtils.contentTypes.isKind(kind));
38
38
  },
39
39
  async findConfiguration (contentType) {