@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.
- package/dist/admin/constants/customOrder.js +14 -0
- package/dist/admin/constants/customOrder.js.map +1 -0
- package/dist/admin/constants/customOrder.mjs +10 -0
- package/dist/admin/constants/customOrder.mjs.map +1 -0
- package/dist/admin/hooks/useDocument.js +22 -11
- package/dist/admin/hooks/useDocument.js.map +1 -1
- package/dist/admin/hooks/useDocument.mjs +22 -11
- package/dist/admin/hooks/useDocument.mjs.map +1 -1
- package/dist/admin/hooks/useDocumentLayout.js.map +1 -1
- package/dist/admin/hooks/useDocumentLayout.mjs.map +1 -1
- package/dist/admin/hooks/useHasBeenNearViewport.js +70 -0
- package/dist/admin/hooks/useHasBeenNearViewport.js.map +1 -0
- package/dist/admin/hooks/useHasBeenNearViewport.mjs +46 -0
- package/dist/admin/hooks/useHasBeenNearViewport.mjs.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.js +102 -32
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.mjs +104 -35
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js +20 -17
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs +20 -17
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js +15 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs +17 -3
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.js +21 -0
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.mjs +22 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js +4 -7
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs +4 -7
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +46 -10
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +47 -11
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.js +201 -51
- package/dist/admin/pages/EditView/components/FormLayout.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.mjs +202 -53
- package/dist/admin/pages/EditView/components/FormLayout.mjs.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/Settings.js +31 -2
- package/dist/admin/pages/ListConfiguration/components/Settings.js.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/Settings.mjs +31 -2
- package/dist/admin/pages/ListConfiguration/components/Settings.mjs.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.js +196 -132
- package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.mjs +196 -132
- package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/CustomOrder.js +571 -0
- package/dist/admin/pages/ListView/components/CustomOrder.js.map +1 -0
- package/dist/admin/pages/ListView/components/CustomOrder.mjs +546 -0
- package/dist/admin/pages/ListView/components/CustomOrder.mjs.map +1 -0
- package/dist/admin/pages/ListView/components/TableActions.js +4 -1
- package/dist/admin/pages/ListView/components/TableActions.js.map +1 -1
- package/dist/admin/pages/ListView/components/TableActions.mjs +4 -1
- package/dist/admin/pages/ListView/components/TableActions.mjs.map +1 -1
- package/dist/admin/services/documents.js +22 -1
- package/dist/admin/services/documents.js.map +1 -1
- package/dist/admin/services/documents.mjs +21 -2
- package/dist/admin/services/documents.mjs.map +1 -1
- package/dist/admin/src/constants/customOrder.d.ts +8 -0
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +4 -0
- package/dist/admin/src/hooks/useDocumentLayout.d.ts +6 -2
- package/dist/admin/src/hooks/useHasBeenNearViewport.d.ts +13 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.d.ts +13 -1
- package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +11 -1
- package/dist/admin/src/pages/ListView/components/CustomOrder.d.ts +72 -0
- package/dist/admin/src/services/documents.d.ts +10 -2
- package/dist/admin/translations/en.json.js +9 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +9 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/audit-logs.js +36 -0
- package/dist/server/audit-logs.js.map +1 -0
- package/dist/server/audit-logs.mjs +33 -0
- package/dist/server/audit-logs.mjs.map +1 -0
- package/dist/server/bootstrap.js +8 -0
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/server/bootstrap.mjs +8 -0
- package/dist/server/bootstrap.mjs.map +1 -1
- package/dist/server/controllers/collection-types.js +8 -0
- package/dist/server/controllers/collection-types.js.map +1 -1
- package/dist/server/controllers/collection-types.mjs +8 -0
- package/dist/server/controllers/collection-types.mjs.map +1 -1
- package/dist/server/controllers/content-types.js +15 -0
- package/dist/server/controllers/content-types.js.map +1 -1
- package/dist/server/controllers/content-types.mjs +16 -1
- package/dist/server/controllers/content-types.mjs.map +1 -1
- package/dist/server/controllers/index.js +3 -1
- package/dist/server/controllers/index.js.map +1 -1
- package/dist/server/controllers/index.mjs +2 -0
- package/dist/server/controllers/index.mjs.map +1 -1
- package/dist/server/controllers/relations.js +5 -1
- package/dist/server/controllers/relations.js.map +1 -1
- package/dist/server/controllers/relations.mjs +5 -1
- package/dist/server/controllers/relations.mjs.map +1 -1
- package/dist/server/controllers/single-types.js +10 -1
- package/dist/server/controllers/single-types.js.map +1 -1
- package/dist/server/controllers/single-types.mjs +10 -1
- package/dist/server/controllers/single-types.mjs.map +1 -1
- package/dist/server/controllers/validation/model-configuration.js +2 -1
- package/dist/server/controllers/validation/model-configuration.js.map +1 -1
- package/dist/server/controllers/validation/model-configuration.mjs +2 -1
- package/dist/server/controllers/validation/model-configuration.mjs.map +1 -1
- package/dist/server/custom-order/constants.js +21 -0
- package/dist/server/custom-order/constants.js.map +1 -0
- package/dist/server/custom-order/constants.mjs +17 -0
- package/dist/server/custom-order/constants.mjs.map +1 -0
- package/dist/server/custom-order/controllers/custom-order.js +77 -0
- package/dist/server/custom-order/controllers/custom-order.js.map +1 -0
- package/dist/server/custom-order/controllers/custom-order.mjs +75 -0
- package/dist/server/custom-order/controllers/custom-order.mjs.map +1 -0
- package/dist/server/custom-order/controllers/index.js +10 -0
- package/dist/server/custom-order/controllers/index.js.map +1 -0
- package/dist/server/custom-order/controllers/index.mjs +8 -0
- package/dist/server/custom-order/controllers/index.mjs.map +1 -0
- package/dist/server/custom-order/index.js +71 -0
- package/dist/server/custom-order/index.js.map +1 -0
- package/dist/server/custom-order/index.mjs +69 -0
- package/dist/server/custom-order/index.mjs.map +1 -0
- package/dist/server/custom-order/routes/custom-order.js +38 -0
- package/dist/server/custom-order/routes/custom-order.js.map +1 -0
- package/dist/server/custom-order/routes/custom-order.mjs +36 -0
- package/dist/server/custom-order/routes/custom-order.mjs.map +1 -0
- package/dist/server/custom-order/routes/index.js +13 -0
- package/dist/server/custom-order/routes/index.js.map +1 -0
- package/dist/server/custom-order/routes/index.mjs +11 -0
- package/dist/server/custom-order/routes/index.mjs.map +1 -0
- package/dist/server/custom-order/services/custom-order.js +286 -0
- package/dist/server/custom-order/services/custom-order.js.map +1 -0
- package/dist/server/custom-order/services/custom-order.mjs +284 -0
- package/dist/server/custom-order/services/custom-order.mjs.map +1 -0
- package/dist/server/custom-order/services/document-middleware.js +83 -0
- package/dist/server/custom-order/services/document-middleware.js.map +1 -0
- package/dist/server/custom-order/services/document-middleware.mjs +81 -0
- package/dist/server/custom-order/services/document-middleware.mjs.map +1 -0
- package/dist/server/custom-order/services/index.js +10 -0
- package/dist/server/custom-order/services/index.js.map +1 -0
- package/dist/server/custom-order/services/index.mjs +8 -0
- package/dist/server/custom-order/services/index.mjs.map +1 -0
- package/dist/server/custom-order/services/utils.js +152 -0
- package/dist/server/custom-order/services/utils.js.map +1 -0
- package/dist/server/custom-order/services/utils.mjs +148 -0
- package/dist/server/custom-order/services/utils.mjs.map +1 -0
- package/dist/server/custom-order/utils.js +13 -0
- package/dist/server/custom-order/utils.js.map +1 -0
- package/dist/server/custom-order/utils.mjs +10 -0
- package/dist/server/custom-order/utils.mjs.map +1 -0
- package/dist/server/history/constants.js +2 -1
- package/dist/server/history/constants.js.map +1 -1
- package/dist/server/history/constants.mjs +2 -1
- package/dist/server/history/constants.mjs.map +1 -1
- package/dist/server/history/controllers/history-version.js +6 -2
- package/dist/server/history/controllers/history-version.js.map +1 -1
- package/dist/server/history/controllers/history-version.mjs +6 -2
- package/dist/server/history/controllers/history-version.mjs.map +1 -1
- package/dist/server/history/services/history.js +23 -6
- package/dist/server/history/services/history.js.map +1 -1
- package/dist/server/history/services/history.mjs +24 -7
- package/dist/server/history/services/history.mjs.map +1 -1
- package/dist/server/history/services/lifecycles.js +2 -16
- package/dist/server/history/services/lifecycles.js.map +1 -1
- package/dist/server/history/services/lifecycles.mjs +2 -16
- package/dist/server/history/services/lifecycles.mjs.map +1 -1
- package/dist/server/register.js +4 -0
- package/dist/server/register.js.map +1 -1
- package/dist/server/register.mjs +4 -0
- package/dist/server/register.mjs.map +1 -1
- package/dist/server/routes/index.js +3 -1
- package/dist/server/routes/index.js.map +1 -1
- package/dist/server/routes/index.mjs +2 -0
- package/dist/server/routes/index.mjs.map +1 -1
- package/dist/server/services/content-types.js +2 -2
- package/dist/server/services/content-types.js.map +1 -1
- package/dist/server/services/content-types.mjs +2 -2
- package/dist/server/services/content-types.mjs.map +1 -1
- package/dist/server/services/document-manager.js +13 -0
- package/dist/server/services/document-manager.js.map +1 -1
- package/dist/server/services/document-manager.mjs +14 -1
- package/dist/server/services/document-manager.mjs.map +1 -1
- package/dist/server/services/index.js +3 -1
- package/dist/server/services/index.js.map +1 -1
- package/dist/server/services/index.mjs +2 -0
- package/dist/server/services/index.mjs.map +1 -1
- package/dist/server/services/utils/configuration/settings.js +2 -1
- package/dist/server/services/utils/configuration/settings.js.map +1 -1
- package/dist/server/services/utils/configuration/settings.mjs +2 -1
- package/dist/server/services/utils/configuration/settings.mjs.map +1 -1
- package/dist/server/src/audit-logs.d.ts +40 -0
- package/dist/server/src/audit-logs.d.ts.map +1 -0
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/content-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +21 -3
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts +19 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/single-types.d.ts +1 -1
- package/dist/server/src/controllers/single-types.d.ts.map +1 -1
- package/dist/server/src/custom-order/constants.d.ts +18 -0
- package/dist/server/src/custom-order/constants.d.ts.map +1 -0
- package/dist/server/src/custom-order/controllers/custom-order.d.ts +8 -0
- package/dist/server/src/custom-order/controllers/custom-order.d.ts.map +1 -0
- package/dist/server/src/custom-order/controllers/index.d.ts +3 -0
- package/dist/server/src/custom-order/controllers/index.d.ts.map +1 -0
- package/dist/server/src/custom-order/index.d.ts +8 -0
- package/dist/server/src/custom-order/index.d.ts.map +1 -0
- package/dist/server/src/custom-order/routes/custom-order.d.ts +4 -0
- package/dist/server/src/custom-order/routes/custom-order.d.ts.map +1 -0
- package/dist/server/src/custom-order/routes/index.d.ts +10 -0
- package/dist/server/src/custom-order/routes/index.d.ts.map +1 -0
- package/dist/server/src/custom-order/services/custom-order.d.ts +43 -0
- package/dist/server/src/custom-order/services/custom-order.d.ts.map +1 -0
- package/dist/server/src/custom-order/services/document-middleware.d.ts +16 -0
- package/dist/server/src/custom-order/services/document-middleware.d.ts.map +1 -0
- package/dist/server/src/custom-order/services/index.d.ts +24 -0
- package/dist/server/src/custom-order/services/index.d.ts.map +1 -0
- package/dist/server/src/custom-order/services/utils.d.ts +34 -0
- package/dist/server/src/custom-order/services/utils.d.ts.map +1 -0
- package/dist/server/src/custom-order/utils.d.ts +6 -0
- package/dist/server/src/custom-order/utils.d.ts.map +1 -0
- package/dist/server/src/history/constants.d.ts.map +1 -1
- package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +22 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/content-types.d.ts +1 -3
- package/dist/server/src/services/content-types.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +1 -3
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/settings.d.ts.map +1 -1
- package/dist/shared/contracts/content-types.d.ts +5 -0
- package/dist/shared/contracts/content-types.d.ts.map +1 -1
- package/dist/shared/contracts/custom-order.d.ts +33 -0
- package/dist/shared/contracts/custom-order.d.ts.map +1 -0
- package/dist/shared/contracts/custom-order.js +3 -0
- package/dist/shared/contracts/custom-order.js.map +1 -0
- package/dist/shared/contracts/custom-order.mjs +2 -0
- package/dist/shared/contracts/custom-order.mjs.map +1 -0
- package/dist/shared/contracts/history-versions.d.ts +0 -1
- package/dist/shared/contracts/history-versions.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/index.js +2 -0
- package/dist/shared/contracts/index.js.map +1 -1
- package/dist/shared/contracts/index.mjs +2 -0
- package/dist/shared/contracts/index.mjs.map +1 -1
- 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,
|
|
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 (
|
|
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
|
|
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":";;;;;;;;AAWA;;IAGA,MAAMA,6BAA6B,CACjCC,OAAAA,GAAAA;;IAMA,IAAI,CAACC,OAAOC,cAAc,CAACC,GAAG,EAAA,EAAIC,OAAAA,CAAQC,GAAAA,CAAIC,UAAAA,CAAW,kBAAA,CAAA,EAAqB;QAC5E,OAAO,KAAA;AACT,IAAA;;IAGA,IACEN,OAAAA,CAAQO,MAAM,KAAK,QAAA,IACnBP,QAAQO,MAAM,KAAK,QAAA,IACnBP,OAAAA,CAAQO,MAAM,KAAK,WACnBP,OAAAA,CAAQO,MAAM,KAAK,SAAA,IACnBP,OAAAA,CAAQO,MAAM,KAAK,WAAA,IACnBP,OAAAA,CAAQO,MAAM,KAAK,cAAA,EACnB;QACA,OAAO,KAAA;AACT,IAAA;AAEA;;;;;AAKC,MACD,IACEP,OAAAA,CAAQO,MAAM,KAAK,QAAA,IACnBN,MAAAA,CAAOC,cAAc,CAACC,GAAG,EAAA,EAAIC,OAAAA,CAAQC,IAAIG,KAAAA,CAAM,GAAA,CAAI,CAAC,CAAA,CAAE,CAACC,SAAS,kBAAA,CAAA,EAChE;QACA,OAAO,KAAA;AACT,IAAA;;IAGA,IAAI,CAACT,QAAQU,WAAW,CAACC,GAAG,CAACL,UAAU,CAAC,OAAA,CAAA,EAAU;QAChD,OAAO,KAAA;AACT,IAAA;IAEA,OAAO,IAAA;AACT,CAAA;AAEA;;;;IAKA,MAAMM,aAAa,CAACD,GAAAA,GAAAA;AAClB,IAAA,MAAME,gBAAAA,GAAmBZ,MAAAA,CAAOa,QAAQ,CAACH,KAAKI,UAAU;;IAGxD,MAAMC,iBAAAA,GAAoBC,OAAOC,IAAI,CAACL,kBAAkBM,MAAM,CAC5D,CAACC,uBAAAA,EAAyBC,GAAAA,GAAAA;QACxB,MAAMC,WAAAA,GAAcT,gBAAgB,CAACQ,GAAAA,CAAI;QAEzC,IAAIC,WAAAA,CAAYC,IAAI,KAAK,WAAA,EAAa;AACpC,YAAA,MAAMC,kBAAkBvB,MAAAA,CAAOa,QAAQ,CAACQ,WAAAA,CAAYG,SAAS,EAAEV,UAAU;YACzE,OAAO;AACL,gBAAA,GAAGK,uBAAuB;gBAC1B,CAACE,WAAAA,CAAYG,SAAS,GAAGD;AAC3B,aAAA;AACF,QAAA;;QAGA,OAAOJ,uBAAAA;AACT,IAAA,CAAA,EACA,EAAC,CAAA;IAGH,OAAO;AACLM,QAAAA,MAAAA,EAAQC,OAAKd,gBAAAA,EAAkBe,0BAAAA,CAAAA;AAC/BZ,QAAAA;AACF,KAAA;AACF,CAAA;AAEA,MAAMa,uBAAAA,GAA0B,CAAC,EAAE5B,MAAAA,EAAAA,OAAM,EAA2B,GAAA;AAClE,IAAA,MAAM6B,KAAAA,GAEF;QACFC,aAAAA,EAAe;AACjB,KAAA;AAEA,IAAA,MAAMC,eAAeC,0BAAAA,CAAmB;QAAEhC,MAAAA,EAAAA;AAAO,KAAA,CAAA;AACjD,IAAA,MAAM,EAAEiC,uBAAuB,EAAE,GAAGjC,OAAAA,CAAOkC,OAAO,CAAC,uBAAA,CAAA;IAEnD,OAAO;QACL,MAAMC,SAAAA,CAAAA,GAAAA;;YAEJ,IAAIN,KAAAA,CAAMC,aAAa,EAAE;AACvB,gBAAA;AACF,YAAA;;AAGA,YAAA,MAAMG,uBAAAA,CAAwB,yBAAA,CAAA;AAE9BjC,YAAAA,OAAAA,CAAOoC,SAAS,CAACC,GAAG,CAAC,OAAOtC,OAAAA,EAASuC,IAAAA,GAAAA;AACnC,gBAAA,MAAMC,SAAU,MAAMD,IAAAA,EAAAA;gBAEtB,IAAI,CAACxC,2BAA2BC,OAAAA,CAAAA,EAAU;oBACxC,OAAOwC,MAAAA;AACT,gBAAA;;AAGA,gBAAA,MAAMC,UAAAA,GACJzC,OAAAA,CAAQO,MAAM,KAAK,YAAYP,OAAAA,CAAQO,MAAM,KAAK,OAAA,GAC9CiC,OAAOC,UAAU,GACjBzC,OAAAA,CAAQ0C,MAAM,CAACD,UAAU;;gBAG/B,MAAME,aAAAA,GAAgB,MAAMX,YAAAA,CAAaY,gBAAgB,EAAA;AACzD,gBAAA,MAAMC,OAAAA,GAAUC,WAAAA,CAAU9C,OAAAA,CAAQ0C,MAAM,EAAEK,MAAAA,IAAUJ,aAAAA,CAAAA;gBACpD,IAAI,CAACE,OAAAA,CAAQG,MAAM,EAAE;oBACnB,OAAOR,MAAAA;AACT,gBAAA;;AAGA,gBAAA,MAAM7B,GAAAA,GAAMX,OAAAA,CAAQU,WAAW,CAACC,GAAG;AACnC,gBAAA,MAAMsC,UAAUrC,UAAAA,CAAWD,GAAAA,CAAAA;gBAC3B,MAAMuC,KAAAA,GAAQjD,OAAAA,CAAOa,QAAQ,CAACH,GAAAA,CAAAA;gBAE9B,MAAMwC,sBAAAA,GAAyBnB,YAAAA,CAAamB,sBAAsB,CAACD,KAAAA,CAAAA;;gBAGnE,MAAME,aAAAA,GAAgB,MAAMnD,OAAAA,CAAOoD,EAAE,CAACC,KAAK,CAAC3C,GAAAA,CAAAA,CAAK4C,QAAQ,CAAC;oBACxDC,KAAAA,EAAO;AACLf,wBAAAA,UAAAA;AACA,wBAAA,GAAIU,sBAAAA,GAAyB;4BAAEJ,MAAAA,EAAQ;gCAAEU,GAAAA,EAAKZ;AAAQ;AAAE,yBAAA,GAAI,EAAE;AAC9D,wBAAA,GAAIa,yBAAaC,kBAAkB,CAAC1D,QAAOyD,YAAY,CAAC/C,IAAI,CAAA,GACxD;4BAAEiD,WAAAA,EAAa;AAAK,yBAAA,GACpB;AACN,qBAAA;oBACAC,QAAAA,EAAU7B,YAAAA,CAAa8B,eAAe,CAACnD,GAAAA,EAAK,IAAA;AAC9C,iBAAA,CAAA;gBAEA,MAAMV,OAAAA,CAAOoD,EAAE,CAACU,WAAW,CAAC,OAAO,EAAEC,QAAQ,EAAE,GAAA;;;;oBAI7CA,QAAAA,CAAS,UAAA;wBACP,KAAK,MAAMC,SAASb,aAAAA,CAAe;AACjC,4BAAA,MAAMc,MAAAA,GAAS,MAAMlC,YAAAA,CAAamC,gBAAgB,CAACxD,GAAAA,EAAKsD,KAAAA,CAAAA;AAExD,4BAAA,MAAMG,gBAAAA,CAAWnE,OAAAA,EAAQ,SAAA,CAAA,CAAWoE,aAAa,CAAC;gCAChD3D,WAAAA,EAAaC,GAAAA;AACb2D,gCAAAA,IAAAA,EAAM3C,OAAKsC,KAAAA,EAAOrC,0BAAAA,CAAAA;gCAClB2C,iBAAAA,EAAmB9B,UAAAA;AACnBM,gCAAAA,MAAAA,EAAQkB,MAAMlB,MAAM;AACpBmB,gCAAAA,MAAAA;AACA,gCAAA,GAAGjB;AACL,6BAAA,CAAA;AACF,wBAAA;AACF,oBAAA,CAAA,CAAA;AACF,gBAAA,CAAA,CAAA;gBAEA,OAAOT,MAAAA;AACT,YAAA,CAAA,CAAA;;YAGAvC,OAAAA,CAAOuE,IAAI,CAACC,GAAG,CAAC;gBACdC,kBAAAA,EAAoB;oBAClB,MAAMC,IAAAA,CAAAA,GAAAA;AACJ,wBAAA,MAAMC,UAAAA,GAAa,IAAA;AAEnB,wBAAA,MAAMC,8BACJ7C,YAAAA,CAAa8C,gBAAgB,EAAA,GAAK,EAAA,GAAK,KAAK,EAAA,GAAK,IAAA;AACnD,wBAAA,MAAMC,cAAAA,GAAiB,IAAIC,IAAAA,CAAKA,IAAAA,CAAKC,GAAG,EAAA,GAAKJ,2BAAAA,CAAAA;;;wBAI7C,IAAIK,OAAAA;wBACJ,GAAG;;4BAED,MAAMC,eAAAA,GAAkB,MAAMlF,OAAAA,CAAOoD,EAAE,CAACC,KAAK,CAAC8B,6BAAAA,CAAAA,CAAqB7B,QAAQ,CAAC;gCAC1E8B,MAAAA,EAAQ;AAAC,oCAAA;AAAK,iCAAA;gCACd7B,KAAAA,EAAO;oCACL8B,UAAAA,EAAY;wCACVC,GAAAA,EAAKR;AACP;AACF,iCAAA;gCACAS,KAAAA,EAAOZ;AACT,6BAAA,CAAA;AAEA,4BAAA,MAAMa,MAAMN,eAAAA,CAAgBO,GAAG,CAAC,CAACC,CAAAA,GAA+BA,EAAEC,EAAE,CAAA;AACpEV,4BAAAA,OAAAA,GAAUO,IAAIzC,MAAM;;AAGpB,4BAAA,IAAIkC,UAAU,CAAA,EAAG;AACf,gCAAA,MAAMjF,QAAOoD,EAAE,CAACC,KAAK,CAAC8B,6BAAAA,CAAAA,CAAqBS,UAAU,CAAC;oCACpDrC,KAAAA,EAAO;wCACLoC,EAAAA,EAAI;4CAAEnC,GAAAA,EAAKgC;AAAI;AACjB;AACF,iCAAA,CAAA;AACF,4BAAA;;;AAIF,wBAAA,CAAA,OAASP,WAAWN,UAAAA;AACtB,oBAAA,CAAA;oBACAkB,OAAAA,EAAS;AACX;AACF,aAAA,CAAA;AAEAhE,YAAAA,KAAAA,CAAMC,aAAa,GAAG,IAAA;AACxB,QAAA,CAAA;QAEA,MAAMgE,OAAAA,CAAAA,GAAAA;YACJ9F,OAAAA,CAAOuE,IAAI,CAACwB,MAAM,CAAC,oBAAA,CAAA;AACrB,QAAA;AACF,KAAA;AACF;;;;"}
|
|
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
|
|
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":";;;;;;AAWA;;IAGA,MAAMA,6BAA6B,CACjCC,OAAAA,GAAAA;;IAMA,IAAI,CAACC,OAAOC,cAAc,CAACC,GAAG,EAAA,EAAIC,OAAAA,CAAQC,GAAAA,CAAIC,UAAAA,CAAW,kBAAA,CAAA,EAAqB;QAC5E,OAAO,KAAA;AACT,IAAA;;IAGA,IACEN,OAAAA,CAAQO,MAAM,KAAK,QAAA,IACnBP,QAAQO,MAAM,KAAK,QAAA,IACnBP,OAAAA,CAAQO,MAAM,KAAK,WACnBP,OAAAA,CAAQO,MAAM,KAAK,SAAA,IACnBP,OAAAA,CAAQO,MAAM,KAAK,WAAA,IACnBP,OAAAA,CAAQO,MAAM,KAAK,cAAA,EACnB;QACA,OAAO,KAAA;AACT,IAAA;AAEA;;;;;AAKC,MACD,IACEP,OAAAA,CAAQO,MAAM,KAAK,QAAA,IACnBN,MAAAA,CAAOC,cAAc,CAACC,GAAG,EAAA,EAAIC,OAAAA,CAAQC,IAAIG,KAAAA,CAAM,GAAA,CAAI,CAAC,CAAA,CAAE,CAACC,SAAS,kBAAA,CAAA,EAChE;QACA,OAAO,KAAA;AACT,IAAA;;IAGA,IAAI,CAACT,QAAQU,WAAW,CAACC,GAAG,CAACL,UAAU,CAAC,OAAA,CAAA,EAAU;QAChD,OAAO,KAAA;AACT,IAAA;IAEA,OAAO,IAAA;AACT,CAAA;AAEA;;;;IAKA,MAAMM,aAAa,CAACD,GAAAA,GAAAA;AAClB,IAAA,MAAME,gBAAAA,GAAmBZ,MAAAA,CAAOa,QAAQ,CAACH,KAAKI,UAAU;;IAGxD,MAAMC,iBAAAA,GAAoBC,OAAOC,IAAI,CAACL,kBAAkBM,MAAM,CAC5D,CAACC,uBAAAA,EAAyBC,GAAAA,GAAAA;QACxB,MAAMC,WAAAA,GAAcT,gBAAgB,CAACQ,GAAAA,CAAI;QAEzC,IAAIC,WAAAA,CAAYC,IAAI,KAAK,WAAA,EAAa;AACpC,YAAA,MAAMC,kBAAkBvB,MAAAA,CAAOa,QAAQ,CAACQ,WAAAA,CAAYG,SAAS,EAAEV,UAAU;YACzE,OAAO;AACL,gBAAA,GAAGK,uBAAuB;gBAC1B,CAACE,WAAAA,CAAYG,SAAS,GAAGD;AAC3B,aAAA;AACF,QAAA;;QAGA,OAAOJ,uBAAAA;AACT,IAAA,CAAA,EACA,EAAC,CAAA;IAGH,OAAO;AACLM,QAAAA,MAAAA,EAAQC,KAAKd,gBAAAA,EAAkBe,gBAAAA,CAAAA;AAC/BZ,QAAAA;AACF,KAAA;AACF,CAAA;AAEA,MAAMa,uBAAAA,GAA0B,CAAC,EAAE5B,MAAAA,EAAAA,OAAM,EAA2B,GAAA;AAClE,IAAA,MAAM6B,KAAAA,GAEF;QACFC,aAAAA,EAAe;AACjB,KAAA;AAEA,IAAA,MAAMC,eAAeC,kBAAAA,CAAmB;QAAEhC,MAAAA,EAAAA;AAAO,KAAA,CAAA;AACjD,IAAA,MAAM,EAAEiC,uBAAuB,EAAE,GAAGjC,OAAAA,CAAOkC,OAAO,CAAC,uBAAA,CAAA;IAEnD,OAAO;QACL,MAAMC,SAAAA,CAAAA,GAAAA;;YAEJ,IAAIN,KAAAA,CAAMC,aAAa,EAAE;AACvB,gBAAA;AACF,YAAA;;AAGA,YAAA,MAAMG,uBAAAA,CAAwB,yBAAA,CAAA;AAE9BjC,YAAAA,OAAAA,CAAOoC,SAAS,CAACC,GAAG,CAAC,OAAOtC,OAAAA,EAASuC,IAAAA,GAAAA;AACnC,gBAAA,MAAMC,SAAU,MAAMD,IAAAA,EAAAA;gBAEtB,IAAI,CAACxC,2BAA2BC,OAAAA,CAAAA,EAAU;oBACxC,OAAOwC,MAAAA;AACT,gBAAA;;AAGA,gBAAA,MAAMC,UAAAA,GACJzC,OAAAA,CAAQO,MAAM,KAAK,YAAYP,OAAAA,CAAQO,MAAM,KAAK,OAAA,GAC9CiC,OAAOC,UAAU,GACjBzC,OAAAA,CAAQ0C,MAAM,CAACD,UAAU;;gBAG/B,MAAME,aAAAA,GAAgB,MAAMX,YAAAA,CAAaY,gBAAgB,EAAA;AACzD,gBAAA,MAAMC,OAAAA,GAAUC,SAAAA,CAAU9C,OAAAA,CAAQ0C,MAAM,EAAEK,MAAAA,IAAUJ,aAAAA,CAAAA;gBACpD,IAAI,CAACE,OAAAA,CAAQG,MAAM,EAAE;oBACnB,OAAOR,MAAAA;AACT,gBAAA;;AAGA,gBAAA,MAAM7B,GAAAA,GAAMX,OAAAA,CAAQU,WAAW,CAACC,GAAG;AACnC,gBAAA,MAAMsC,UAAUrC,UAAAA,CAAWD,GAAAA,CAAAA;gBAC3B,MAAMuC,KAAAA,GAAQjD,OAAAA,CAAOa,QAAQ,CAACH,GAAAA,CAAAA;gBAE9B,MAAMwC,sBAAAA,GAAyBnB,YAAAA,CAAamB,sBAAsB,CAACD,KAAAA,CAAAA;;gBAGnE,MAAME,aAAAA,GAAgB,MAAMnD,OAAAA,CAAOoD,EAAE,CAACC,KAAK,CAAC3C,GAAAA,CAAAA,CAAK4C,QAAQ,CAAC;oBACxDC,KAAAA,EAAO;AACLf,wBAAAA,UAAAA;AACA,wBAAA,GAAIU,sBAAAA,GAAyB;4BAAEJ,MAAAA,EAAQ;gCAAEU,GAAAA,EAAKZ;AAAQ;AAAE,yBAAA,GAAI,EAAE;AAC9D,wBAAA,GAAIa,aAAaC,kBAAkB,CAAC1D,QAAOyD,YAAY,CAAC/C,IAAI,CAAA,GACxD;4BAAEiD,WAAAA,EAAa;AAAK,yBAAA,GACpB;AACN,qBAAA;oBACAC,QAAAA,EAAU7B,YAAAA,CAAa8B,eAAe,CAACnD,GAAAA,EAAK,IAAA;AAC9C,iBAAA,CAAA;gBAEA,MAAMV,OAAAA,CAAOoD,EAAE,CAACU,WAAW,CAAC,OAAO,EAAEC,QAAQ,EAAE,GAAA;;;;oBAI7CA,QAAAA,CAAS,UAAA;wBACP,KAAK,MAAMC,SAASb,aAAAA,CAAe;AACjC,4BAAA,MAAMc,MAAAA,GAAS,MAAMlC,YAAAA,CAAamC,gBAAgB,CAACxD,GAAAA,EAAKsD,KAAAA,CAAAA;AAExD,4BAAA,MAAMG,UAAAA,CAAWnE,OAAAA,EAAQ,SAAA,CAAA,CAAWoE,aAAa,CAAC;gCAChD3D,WAAAA,EAAaC,GAAAA;AACb2D,gCAAAA,IAAAA,EAAM3C,KAAKsC,KAAAA,EAAOrC,gBAAAA,CAAAA;gCAClB2C,iBAAAA,EAAmB9B,UAAAA;AACnBM,gCAAAA,MAAAA,EAAQkB,MAAMlB,MAAM;AACpBmB,gCAAAA,MAAAA;AACA,gCAAA,GAAGjB;AACL,6BAAA,CAAA;AACF,wBAAA;AACF,oBAAA,CAAA,CAAA;AACF,gBAAA,CAAA,CAAA;gBAEA,OAAOT,MAAAA;AACT,YAAA,CAAA,CAAA;;YAGAvC,OAAAA,CAAOuE,IAAI,CAACC,GAAG,CAAC;gBACdC,kBAAAA,EAAoB;oBAClB,MAAMC,IAAAA,CAAAA,GAAAA;AACJ,wBAAA,MAAMC,UAAAA,GAAa,IAAA;AAEnB,wBAAA,MAAMC,8BACJ7C,YAAAA,CAAa8C,gBAAgB,EAAA,GAAK,EAAA,GAAK,KAAK,EAAA,GAAK,IAAA;AACnD,wBAAA,MAAMC,cAAAA,GAAiB,IAAIC,IAAAA,CAAKA,IAAAA,CAAKC,GAAG,EAAA,GAAKJ,2BAAAA,CAAAA;;;wBAI7C,IAAIK,OAAAA;wBACJ,GAAG;;4BAED,MAAMC,eAAAA,GAAkB,MAAMlF,OAAAA,CAAOoD,EAAE,CAACC,KAAK,CAAC8B,mBAAAA,CAAAA,CAAqB7B,QAAQ,CAAC;gCAC1E8B,MAAAA,EAAQ;AAAC,oCAAA;AAAK,iCAAA;gCACd7B,KAAAA,EAAO;oCACL8B,UAAAA,EAAY;wCACVC,GAAAA,EAAKR;AACP;AACF,iCAAA;gCACAS,KAAAA,EAAOZ;AACT,6BAAA,CAAA;AAEA,4BAAA,MAAMa,MAAMN,eAAAA,CAAgBO,GAAG,CAAC,CAACC,CAAAA,GAA+BA,EAAEC,EAAE,CAAA;AACpEV,4BAAAA,OAAAA,GAAUO,IAAIzC,MAAM;;AAGpB,4BAAA,IAAIkC,UAAU,CAAA,EAAG;AACf,gCAAA,MAAMjF,QAAOoD,EAAE,CAACC,KAAK,CAAC8B,mBAAAA,CAAAA,CAAqBS,UAAU,CAAC;oCACpDrC,KAAAA,EAAO;wCACLoC,EAAAA,EAAI;4CAAEnC,GAAAA,EAAKgC;AAAI;AACjB;AACF,iCAAA,CAAA;AACF,4BAAA;;;AAIF,wBAAA,CAAA,OAASP,WAAWN,UAAAA;AACtB,oBAAA,CAAA;oBACAkB,OAAAA,EAAS;AACX;AACF,aAAA,CAAA;AAEAhE,YAAAA,KAAAA,CAAMC,aAAa,GAAG,IAAA;AACxB,QAAA,CAAA;QAEA,MAAMgE,OAAAA,CAAAA,GAAAA;YACJ9F,OAAAA,CAAOuE,IAAI,CAACwB,MAAM,CAAC,oBAAA,CAAA;AACrB,QAAA;AACF,KAAA;AACF;;;;"}
|
|
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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"}
|
package/dist/server/register.js
CHANGED
|
@@ -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":"
|
|
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;;;;"}
|
package/dist/server/register.mjs
CHANGED
|
@@ -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":"
|
|
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$
|
|
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":"
|
|
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":"
|
|
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 (
|
|
33
|
+
if (kind === undefined || kind === null) {
|
|
34
34
|
return this.findAllContentTypes();
|
|
35
35
|
}
|
|
36
|
-
// @ts-expect-error
|
|
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) {
|