@strapi/content-releases 0.0.0-next.37dd1e3ff22e1635b69683abadd444912ae0dbff → 0.0.0-next.56199ab7a5f3320e0debcbe4a24fe0b8cd599e21

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../server/src/constants.ts","../../server/src/utils/index.ts","../../server/src/register.ts","../../server/src/bootstrap.ts","../../server/src/content-types/release/schema.ts","../../server/src/content-types/release/index.ts","../../server/src/content-types/release-action/schema.ts","../../server/src/content-types/release-action/index.ts","../../server/src/content-types/index.ts","../../server/src/services/release-action.ts","../../server/src/services/release.ts","../../server/src/services/validation.ts","../../server/src/services/event-manager.ts","../../server/src/services/index.ts","../../shared/validation-schemas.ts","../../server/src/controllers/validation/release.ts","../../server/src/controllers/release.ts","../../server/src/controllers/validation/release-action.ts","../../server/src/controllers/release-action.ts","../../server/src/controllers/index.ts","../../server/src/routes/release.ts","../../server/src/routes/release-action.ts","../../server/src/routes/index.ts","../../server/src/index.ts"],"sourcesContent":["export const RELEASE_MODEL_UID = 'plugin::content-releases.release';\nexport const RELEASE_ACTION_MODEL_UID = 'plugin::content-releases.release-action';\n\nexport const ACTIONS = [\n {\n section: 'plugins',\n displayName: 'Read',\n uid: 'read',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Create',\n uid: 'create',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Edit',\n uid: 'update',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Delete',\n uid: 'delete',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Publish',\n uid: 'publish',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Remove an entry from a release',\n uid: 'delete-action',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Add an entry to a release',\n uid: 'create-action',\n pluginName: 'content-releases',\n },\n];\n","export const getService = (\n name: 'release' | 'release-validation' | 'release-action' | 'event-manager',\n { strapi } = { strapi: global.strapi }\n) => {\n return strapi.plugin('content-releases').service(name);\n};\n","/* eslint-disable @typescript-eslint/no-var-requires */\nimport type { LoadedStrapi } from '@strapi/types';\nimport { ACTIONS } from './constants';\n\nimport { getService } from './utils';\n\nconst { features } = require('@strapi/strapi/dist/utils/ee');\n\nexport const register = async ({ strapi }: { strapi: LoadedStrapi }) => {\n if (\n features.isEnabled('cms-content-releases') &&\n strapi.features.future.isEnabled('contentReleases')\n ) {\n await strapi.admin.services.permission.actionProvider.registerMany(ACTIONS);\n\n const releaseActionService = getService('release-action', { strapi });\n const eventManager = getService('event-manager', { strapi });\n // Clean up release-actions when draft and publish is disabled\n const destroyContentTypeUpdateListener = strapi.eventHub.on(\n 'content-type.update',\n async ({ contentType }) => {\n if (contentType.schema.options.draftAndPublish === false) {\n await releaseActionService.deleteManyForContentType(contentType.uid);\n }\n }\n );\n eventManager.addDestroyListenerCallback(destroyContentTypeUpdateListener);\n // Clean up release-actions when a content-type is deleted\n const destroyContentTypeDeleteListener = strapi.eventHub.on(\n 'content-type.delete',\n async ({ contentType }) => {\n await releaseActionService.deleteManyForContentType(contentType.uid);\n }\n );\n eventManager.addDestroyListenerCallback(destroyContentTypeDeleteListener);\n }\n};\n","/* eslint-disable @typescript-eslint/no-var-requires */\nimport type { LoadedStrapi, Entity as StrapiEntity } from '@strapi/types';\nimport { RELEASE_ACTION_MODEL_UID } from './constants';\n\nconst { features } = require('@strapi/strapi/dist/utils/ee');\n\nexport const bootstrap = async ({ strapi }: { strapi: LoadedStrapi }) => {\n if (\n features.isEnabled('cms-content-releases') &&\n strapi.features.future.isEnabled('contentReleases')\n ) {\n strapi.db.lifecycles.subscribe({\n afterDelete(event) {\n // @ts-expect-error TODO: lifecycles types looks like are not 100% finished\n const { model, result } = event;\n\n // @ts-expect-error TODO: lifecycles types looks like are not 100% finished\n if (model.kind === 'collectionType' && model.options.draftAndPublish) {\n const { id } = result;\n\n strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({\n where: {\n target_type: model.uid,\n target_id: id,\n },\n });\n }\n },\n\n /**\n * deleteMany hook doesn't return the deleted entries ids\n * so we need to fetch them before deleting the entries to save the ids on our state\n */\n async beforeDeleteMany(event) {\n const { model, params } = event;\n\n // @ts-expect-error TODO: lifecycles types looks like are not 100% finished\n if (model.kind === 'collectionType' && model.options.draftAndPublish) {\n const { where } = params;\n\n const entriesToDelete = await strapi.db\n .query(model.uid)\n .findMany({ select: ['id'], where });\n\n event.state.entriesToDelete = entriesToDelete;\n }\n },\n\n /**\n * We delete the release actions related to deleted entries\n * We make this only after deleteMany is succesfully executed to avoid errors\n */\n async afterDeleteMany(event) {\n const { model, state } = event;\n const entriesToDelete = state.entriesToDelete;\n\n if (entriesToDelete) {\n await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({\n where: {\n target_type: model.uid,\n target_id: {\n $in: (entriesToDelete as Array<{ id: StrapiEntity.ID }>).map((entry) => entry.id),\n },\n },\n });\n }\n },\n });\n }\n};\n","import { RELEASE_ACTION_MODEL_UID } from '../../constants';\n\nexport default {\n collectionName: 'strapi_releases',\n info: {\n singularName: 'release',\n pluralName: 'releases',\n displayName: 'Release',\n },\n options: {\n draftAndPublish: false,\n },\n pluginOptions: {\n 'content-manager': {\n visible: false,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n name: {\n type: 'string',\n required: true,\n },\n releasedAt: {\n type: 'datetime',\n },\n actions: {\n type: 'relation',\n relation: 'oneToMany',\n target: RELEASE_ACTION_MODEL_UID,\n mappedBy: 'release',\n },\n },\n};\n","import schema from './schema';\n\nexport const release = {\n schema,\n};\n","import { RELEASE_MODEL_UID } from '../../constants';\n\nexport default {\n collectionName: 'strapi_release_actions',\n info: {\n singularName: 'release-action',\n pluralName: 'release-actions',\n displayName: 'Release Action',\n },\n options: {\n draftAndPublish: false,\n },\n pluginOptions: {\n 'content-manager': {\n visible: false,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n type: {\n type: 'enumeration',\n enum: ['publish', 'unpublish'],\n required: true,\n },\n entry: {\n type: 'relation',\n relation: 'morphToOne',\n configurable: false,\n },\n contentType: {\n type: 'string',\n required: true,\n },\n locale: {\n type: 'string',\n },\n release: {\n type: 'relation',\n relation: 'manyToOne',\n target: RELEASE_MODEL_UID,\n inversedBy: 'actions',\n },\n },\n};\n","import schema from './schema';\n\nexport const releaseAction = {\n schema,\n};\n","import { release } from './release';\nimport { releaseAction } from './release-action';\n\nexport const contentTypes = {\n release,\n 'release-action': releaseAction,\n};\n","import type { LoadedStrapi } from '@strapi/types';\nimport { RELEASE_ACTION_MODEL_UID } from '../constants';\nimport type { ReleaseAction } from '../../../shared/contracts/release-actions';\n\nconst createReleaseActionService = ({ strapi }: { strapi: LoadedStrapi }) => ({\n async deleteManyForContentType(contentTypeUid: ReleaseAction['contentType']) {\n return strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({\n where: {\n target_type: contentTypeUid,\n },\n });\n },\n});\n\nexport default createReleaseActionService;\n","import { setCreatorFields, errors } from '@strapi/utils';\n\nimport type { LoadedStrapi, EntityService, UID } from '@strapi/types';\n\nimport _ from 'lodash/fp';\nimport { RELEASE_ACTION_MODEL_UID, RELEASE_MODEL_UID } from '../constants';\nimport type {\n GetReleases,\n CreateRelease,\n UpdateRelease,\n PublishRelease,\n GetRelease,\n Release,\n DeleteRelease,\n GetContentTypeEntryReleases,\n} from '../../../shared/contracts/releases';\nimport type {\n CreateReleaseAction,\n GetReleaseActions,\n ReleaseAction,\n UpdateReleaseAction,\n DeleteReleaseAction,\n ReleaseActionGroupBy,\n} from '../../../shared/contracts/release-actions';\nimport type { Entity, UserInfo } from '../../../shared/types';\nimport { getService } from '../utils';\n\ninterface Locale extends Entity {\n name: string;\n code: string;\n}\n\ntype LocaleDictionary = {\n [key: Locale['code']]: Pick<Locale, 'name' | 'code'>;\n};\n\nconst getGroupName = (queryValue?: ReleaseActionGroupBy) => {\n switch (queryValue) {\n case 'contentType':\n return 'entry.contentType.displayName';\n case 'action':\n return 'type';\n case 'locale':\n return _.getOr('No locale', 'entry.locale.name');\n default:\n return 'entry.contentType.displayName';\n }\n};\n\nconst createReleaseService = ({ strapi }: { strapi: LoadedStrapi }) => ({\n async create(releaseData: CreateRelease.Request['body'], { user }: { user: UserInfo }) {\n const releaseWithCreatorFields = await setCreatorFields({ user })(releaseData);\n\n return strapi.entityService.create(RELEASE_MODEL_UID, {\n data: releaseWithCreatorFields,\n });\n },\n\n async findOne(id: GetRelease.Request['params']['id'], query = {}) {\n const release = await strapi.entityService.findOne(RELEASE_MODEL_UID, id, {\n ...query,\n });\n\n return release;\n },\n\n findPage(query?: GetReleases.Request['query']) {\n return strapi.entityService.findPage(RELEASE_MODEL_UID, {\n ...query,\n populate: {\n actions: {\n // @ts-expect-error Ignore missing properties\n count: true,\n },\n },\n });\n },\n\n async findManyForContentTypeEntry(\n contentTypeUid: GetContentTypeEntryReleases.Request['query']['contentTypeUid'],\n entryId: GetContentTypeEntryReleases.Request['query']['entryId'],\n {\n hasEntryAttached,\n }: { hasEntryAttached?: GetContentTypeEntryReleases.Request['query']['hasEntryAttached'] } = {\n hasEntryAttached: false,\n }\n ) {\n const whereActions = hasEntryAttached\n ? {\n // Find all Releases where the content type entry is present\n actions: {\n target_type: contentTypeUid,\n target_id: entryId,\n },\n }\n : {\n // Find all Releases where the content type entry is not present\n $or: [\n {\n $not: {\n actions: {\n target_type: contentTypeUid,\n target_id: entryId,\n },\n },\n },\n {\n actions: null,\n },\n ],\n };\n const populateAttachedAction = hasEntryAttached\n ? {\n // Filter the action to get only the content type entry\n actions: {\n where: {\n target_type: contentTypeUid,\n target_id: entryId,\n },\n },\n }\n : {};\n\n const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({\n where: {\n ...whereActions,\n releasedAt: {\n $null: true,\n },\n },\n populate: {\n ...populateAttachedAction,\n },\n });\n\n return releases.map((release) => {\n if (release.actions?.length) {\n const [actionForEntry] = release.actions;\n\n // Remove the actions key to replace it with an action key\n delete release.actions;\n\n return {\n ...release,\n action: actionForEntry,\n };\n }\n\n return release;\n });\n },\n\n async update(\n id: number,\n releaseData: UpdateRelease.Request['body'],\n { user }: { user: UserInfo }\n ) {\n const releaseWithCreatorFields = await setCreatorFields({ user, isEdition: true })(releaseData);\n\n const release = await strapi.entityService.findOne(RELEASE_MODEL_UID, id);\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${id}`);\n }\n\n if (release.releasedAt) {\n throw new errors.ValidationError('Release already published');\n }\n\n const updatedRelease = await strapi.entityService.update(RELEASE_MODEL_UID, id, {\n /*\n * The type returned from the entity service: Partial<Input<\"plugin::content-releases.release\">>\n * is not compatible with the type we are passing here: UpdateRelease.Request['body']\n */\n // @ts-expect-error see above\n data: releaseWithCreatorFields,\n });\n\n return updatedRelease;\n },\n\n async createAction(\n releaseId: CreateReleaseAction.Request['params']['releaseId'],\n action: Pick<CreateReleaseAction.Request['body'], 'type' | 'entry'>\n ) {\n const { validateEntryContentType, validateUniqueEntry } = getService('release-validation', {\n strapi,\n });\n\n await Promise.all([\n validateEntryContentType(action.entry.contentType),\n validateUniqueEntry(releaseId, action),\n ]);\n\n const release = await strapi.entityService.findOne(RELEASE_MODEL_UID, releaseId);\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n if (release.releasedAt) {\n throw new errors.ValidationError('Release already published');\n }\n\n const { entry, type } = action;\n\n return strapi.entityService.create(RELEASE_ACTION_MODEL_UID, {\n data: {\n type,\n contentType: entry.contentType,\n locale: entry.locale,\n entry: {\n id: entry.id,\n __type: entry.contentType,\n __pivot: { field: 'entry' },\n },\n release: releaseId,\n },\n populate: { release: { fields: ['id'] }, entry: { fields: ['id'] } },\n });\n },\n\n async findActions(\n releaseId: GetReleaseActions.Request['params']['releaseId'],\n query?: GetReleaseActions.Request['query']\n ) {\n const release = await strapi.entityService.findOne(RELEASE_MODEL_UID, releaseId, {\n fields: ['id'],\n });\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n return strapi.entityService.findPage(RELEASE_ACTION_MODEL_UID, {\n ...query,\n populate: {\n entry: true,\n },\n filters: {\n release: releaseId,\n },\n });\n },\n\n async countActions(query: EntityService.Params.Pick<typeof RELEASE_ACTION_MODEL_UID, 'filters'>) {\n return strapi.entityService.count(RELEASE_ACTION_MODEL_UID, query);\n },\n\n async groupActions(actions: ReleaseAction[], groupBy: ReleaseActionGroupBy) {\n const contentTypeUids = actions.reduce<ReleaseAction['contentType'][]>((acc, action) => {\n if (!acc.includes(action.contentType)) {\n acc.push(action.contentType);\n }\n\n return acc;\n }, []);\n const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(\n contentTypeUids\n );\n const allLocales: Locale[] = await strapi.plugin('i18n').service('locales').find();\n const allLocalesDictionary = allLocales.reduce<LocaleDictionary>((acc, locale) => {\n acc[locale.code] = { name: locale.name, code: locale.code };\n\n return acc;\n }, {});\n\n const formattedData = actions.map((action: ReleaseAction) => {\n const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];\n\n return {\n ...action,\n entry: {\n id: action.entry.id,\n contentType: {\n displayName,\n mainFieldValue: action.entry[mainField],\n },\n locale: action.locale ? allLocalesDictionary[action.locale] : null,\n status: action.entry.publishedAt ? 'published' : 'draft',\n },\n };\n });\n\n const groupName = getGroupName(groupBy);\n return _.groupBy(groupName)(formattedData);\n },\n\n async getContentTypesDataForActions(contentTypesUids: ReleaseAction['contentType'][]) {\n const contentManagerContentTypeService = strapi\n .plugin('content-manager')\n .service('content-types');\n\n const contentTypesData: Record<UID.ContentType, { mainField: string; displayName: string }> =\n {};\n for (const contentTypeUid of contentTypesUids) {\n const contentTypeConfig = await contentManagerContentTypeService.findConfiguration({\n uid: contentTypeUid,\n });\n\n contentTypesData[contentTypeUid] = {\n mainField: contentTypeConfig.settings.mainField,\n displayName: strapi.getModel(contentTypeUid).info.displayName,\n };\n }\n\n return contentTypesData;\n },\n\n async delete(releaseId: DeleteRelease.Request['params']['id']) {\n const release = (await strapi.entityService.findOne(RELEASE_MODEL_UID, releaseId, {\n populate: {\n actions: {\n fields: ['id'],\n },\n },\n })) as unknown as Release;\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n if (release.releasedAt) {\n throw new errors.ValidationError('Release already published');\n }\n\n // Only delete the release and its actions is you in fact can delete all the actions and the release\n // Otherwise, if the transaction fails it throws an error\n await strapi.db.transaction(async () => {\n await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({\n where: {\n id: {\n $in: release.actions.map((action) => action.id),\n },\n },\n });\n await strapi.entityService.delete(RELEASE_MODEL_UID, releaseId);\n });\n\n return release;\n },\n\n async publish(releaseId: PublishRelease.Request['params']['id']) {\n // We need to pass the type because entityService.findOne is not returning the correct type\n const releaseWithPopulatedActionEntries = (await strapi.entityService.findOne(\n RELEASE_MODEL_UID,\n releaseId,\n {\n populate: {\n actions: {\n populate: {\n entry: true,\n },\n },\n },\n }\n )) as unknown as Release;\n\n if (!releaseWithPopulatedActionEntries) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n if (releaseWithPopulatedActionEntries.releasedAt) {\n throw new errors.ValidationError('Release already published');\n }\n\n if (releaseWithPopulatedActionEntries.actions.length === 0) {\n throw new errors.ValidationError('No entries to publish');\n }\n\n /**\n * We separate publish and unpublish actions group by content type\n */\n const actions: {\n [key: UID.ContentType]: {\n publish: ReleaseAction['entry'][];\n unpublish: ReleaseAction['entry'][];\n };\n } = {};\n for (const action of releaseWithPopulatedActionEntries.actions) {\n const contentTypeUid = action.contentType;\n\n if (!actions[contentTypeUid]) {\n actions[contentTypeUid] = {\n publish: [],\n unpublish: [],\n };\n }\n\n if (action.type === 'publish') {\n actions[contentTypeUid].publish.push(action.entry);\n } else {\n actions[contentTypeUid].unpublish.push(action.entry);\n }\n }\n\n const entityManagerService = strapi.plugin('content-manager').service('entity-manager');\n\n // Only publish the release if all action updates are applied successfully to their entry, otherwise leave everything as is\n await strapi.db.transaction(async () => {\n for (const contentTypeUid of Object.keys(actions)) {\n const { publish, unpublish } = actions[contentTypeUid as UID.ContentType];\n\n if (publish.length > 0) {\n await entityManagerService.publishMany(publish, contentTypeUid);\n }\n\n if (unpublish.length > 0) {\n await entityManagerService.unpublishMany(unpublish, contentTypeUid);\n }\n }\n });\n\n // When the transaction fails it throws an error, when it is successful proceed to updating the release\n const release = await strapi.entityService.update(RELEASE_MODEL_UID, releaseId, {\n data: {\n /*\n * The type returned from the entity service: Partial<Input<\"plugin::content-releases.release\">> looks like it's wrong\n */\n // @ts-expect-error see above\n releasedAt: new Date(),\n },\n });\n\n return release;\n },\n\n async updateAction(\n actionId: UpdateReleaseAction.Request['params']['actionId'],\n releaseId: UpdateReleaseAction.Request['params']['releaseId'],\n update: UpdateReleaseAction.Request['body']\n ) {\n const updatedAction = await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({\n where: {\n id: actionId,\n release: {\n id: releaseId,\n releasedAt: {\n $null: true,\n },\n },\n },\n data: update,\n });\n\n if (!updatedAction) {\n throw new errors.NotFoundError(\n `Action with id ${actionId} not found in release with id ${releaseId} or it is already published`\n );\n }\n\n return updatedAction;\n },\n\n async deleteAction(\n actionId: DeleteReleaseAction.Request['params']['actionId'],\n releaseId: DeleteReleaseAction.Request['params']['releaseId']\n ) {\n const deletedAction = await strapi.db.query(RELEASE_ACTION_MODEL_UID).delete({\n where: {\n id: actionId,\n release: {\n id: releaseId,\n releasedAt: {\n $null: true,\n },\n },\n },\n });\n\n if (!deletedAction) {\n throw new errors.NotFoundError(\n `Action with id ${actionId} not found in release with id ${releaseId} or it is already published`\n );\n }\n\n return deletedAction;\n },\n});\n\nexport default createReleaseService;\n","import { errors } from '@strapi/utils';\nimport { LoadedStrapi } from '@strapi/types';\nimport type { Release } from '../../../shared/contracts/releases';\nimport type { CreateReleaseAction } from '../../../shared/contracts/release-actions';\nimport { RELEASE_MODEL_UID } from '../constants';\n\nconst createReleaseValidationService = ({ strapi }: { strapi: LoadedStrapi }) => ({\n async validateUniqueEntry(\n releaseId: CreateReleaseAction.Request['params']['releaseId'],\n releaseActionArgs: CreateReleaseAction.Request['body']\n ) {\n /**\n * Asserting the type, otherwise TS complains: 'release.actions' is of type 'unknown', even though the types come through for non-populated fields...\n * Possibly related to the comment on GetValues: https://github.com/strapi/strapi/blob/main/packages/core/types/src/modules/entity-service/result.ts\n */\n const release = (await strapi.entityService.findOne(RELEASE_MODEL_UID, releaseId, {\n populate: { actions: { populate: { entry: { fields: ['id'] } } } },\n })) as Release | null;\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n const isEntryInRelease = release.actions.some(\n (action) =>\n Number(action.entry.id) === Number(releaseActionArgs.entry.id) &&\n action.contentType === releaseActionArgs.entry.contentType\n );\n\n if (isEntryInRelease) {\n throw new errors.ValidationError(\n `Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`\n );\n }\n },\n validateEntryContentType(\n contentTypeUid: CreateReleaseAction.Request['body']['entry']['contentType']\n ) {\n const contentType = strapi.contentType(contentTypeUid);\n\n if (!contentType) {\n throw new errors.NotFoundError(`No content type found for uid ${contentTypeUid}`);\n }\n\n // TODO: V5 migration - All contentType will have draftAndPublish enabled\n if (!contentType.options?.draftAndPublish) {\n throw new errors.ValidationError(\n `Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`\n );\n }\n },\n});\n\nexport default createReleaseValidationService;\n","interface ReleaseEventServiceState {\n destroyListenerCallbacks: (() => void)[];\n}\n\nconst createEventManagerService = () => {\n const state: ReleaseEventServiceState = {\n destroyListenerCallbacks: [],\n };\n\n return {\n addDestroyListenerCallback(destroyListenerCallback: () => void) {\n state.destroyListenerCallbacks.push(destroyListenerCallback);\n },\n\n destroyAllListeners() {\n if (!state.destroyListenerCallbacks.length) {\n return;\n }\n\n state.destroyListenerCallbacks.forEach((destroyListenerCallback) => {\n destroyListenerCallback();\n });\n },\n };\n};\n\nexport default createEventManagerService;\n","import releaseAction from './release-action';\nimport release from './release';\nimport releaseValidation from './validation';\nimport eventManager from './event-manager';\n\nexport const services = {\n release,\n 'release-action': releaseAction,\n 'release-validation': releaseValidation,\n 'event-manager': eventManager,\n};\n","import * as yup from 'yup';\n\nexport const RELEASE_SCHEMA = yup\n .object()\n .shape({\n name: yup.string().trim().required(),\n })\n .required()\n .noUnknown();\n","import { validateYupSchema } from '@strapi/utils';\nimport { RELEASE_SCHEMA } from '../../../../shared/validation-schemas';\n\nexport const validateRelease = validateYupSchema(RELEASE_SCHEMA);\n","import type Koa from 'koa';\nimport { errors } from '@strapi/utils';\nimport { RELEASE_MODEL_UID } from '../constants';\nimport { validateRelease } from './validation/release';\nimport type {\n CreateRelease,\n UpdateRelease,\n PublishRelease,\n GetRelease,\n Release,\n DeleteRelease,\n GetContentTypeEntryReleases,\n GetReleases,\n} from '../../../shared/contracts/releases';\nimport type { UserInfo } from '../../../shared/types';\nimport { getService } from '../utils';\n\ntype ReleaseWithPopulatedActions = Release & { actions: { count: number } };\n\nconst releaseController = {\n async findMany(ctx: Koa.Context) {\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n\n const releaseService = getService('release', { strapi });\n\n // Handle requests for releases filtered by content type entry\n const isFindManyForContentTypeEntry = Boolean(ctx.query?.contentTypeUid && ctx.query?.entryId);\n if (isFindManyForContentTypeEntry) {\n const query: GetContentTypeEntryReleases.Request['query'] =\n await permissionsManager.sanitizeQuery(ctx.query);\n\n const contentTypeUid = query.contentTypeUid;\n const entryId = query.entryId;\n // Parse the string value or fallback to a default\n const hasEntryAttached: GetContentTypeEntryReleases.Request['query']['hasEntryAttached'] =\n typeof query.hasEntryAttached === 'string' ? JSON.parse(query.hasEntryAttached) : false;\n\n const data = await releaseService.findManyForContentTypeEntry(contentTypeUid, entryId, {\n hasEntryAttached,\n });\n\n ctx.body = { data };\n } else {\n const query: GetReleases.Request['query'] = await permissionsManager.sanitizeQuery(ctx.query);\n const { results, pagination } = await releaseService.findPage(query);\n\n const data = results.map((release: ReleaseWithPopulatedActions) => {\n const { actions, ...releaseData } = release;\n\n return {\n ...releaseData,\n actions: {\n meta: {\n count: actions.count,\n },\n },\n };\n });\n\n ctx.body = { data, meta: { pagination } };\n }\n },\n\n async findOne(ctx: Koa.Context) {\n const id: GetRelease.Request['params']['id'] = ctx.params.id;\n\n const releaseService = getService('release', { strapi });\n\n const release = await releaseService.findOne(id, { populate: ['createdBy'] });\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_MODEL_UID,\n });\n const sanitizedRelease = await permissionsManager.sanitizeOutput(release);\n\n const count = await releaseService.countActions({\n filters: {\n release: id,\n },\n });\n\n if (!release) {\n throw new errors.NotFoundError(`Release not found for id: ${id}`);\n }\n\n // Format the data object\n const data = {\n ...sanitizedRelease,\n actions: {\n meta: {\n count,\n },\n },\n };\n\n ctx.body = { data };\n },\n\n async create(ctx: Koa.Context) {\n const user: UserInfo = ctx.state.user;\n const releaseArgs: CreateRelease.Request['body'] = ctx.request.body;\n\n await validateRelease(releaseArgs);\n\n const releaseService = getService('release', { strapi });\n const release = await releaseService.create(releaseArgs, { user });\n\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_MODEL_UID,\n });\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(release),\n };\n },\n\n async update(ctx: Koa.Context) {\n const user: UserInfo = ctx.state.user;\n const releaseArgs: UpdateRelease.Request['body'] = ctx.request.body;\n const id: UpdateRelease.Request['params']['id'] = ctx.params.id;\n\n await validateRelease(releaseArgs);\n\n const releaseService = getService('release', { strapi });\n const release = await releaseService.update(id, releaseArgs, { user });\n\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_MODEL_UID,\n });\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(release),\n };\n },\n\n async delete(ctx: Koa.Context) {\n const id: DeleteRelease.Request['params']['id'] = ctx.params.id;\n\n const releaseService = getService('release', { strapi });\n const release = await releaseService.delete(id);\n\n ctx.body = {\n data: release,\n };\n },\n\n async publish(ctx: Koa.Context) {\n const user: PublishRelease.Request['state']['user'] = ctx.state.user;\n const id: PublishRelease.Request['params']['id'] = ctx.params.id;\n\n const releaseService = getService('release', { strapi });\n const release = await releaseService.publish(id, { user });\n\n ctx.body = {\n data: release,\n };\n },\n};\n\nexport default releaseController;\n","import { yup, validateYupSchema } from '@strapi/utils';\n\nconst RELEASE_ACTION_SCHEMA = yup.object().shape({\n entry: yup\n .object()\n .shape({\n id: yup.strapiID().required(),\n contentType: yup.string().required(),\n })\n .required(),\n type: yup.string().oneOf(['publish', 'unpublish']).required(),\n});\n\nconst RELEASE_ACTION_UPDATE_SCHEMA = yup.object().shape({\n type: yup.string().oneOf(['publish', 'unpublish']).required(),\n});\n\nexport const validateReleaseAction = validateYupSchema(RELEASE_ACTION_SCHEMA);\nexport const validateReleaseActionUpdateSchema = validateYupSchema(RELEASE_ACTION_UPDATE_SCHEMA);\n","import type Koa from 'koa';\n\nimport {\n validateReleaseAction,\n validateReleaseActionUpdateSchema,\n} from './validation/release-action';\nimport type {\n CreateReleaseAction,\n GetReleaseActions,\n UpdateReleaseAction,\n DeleteReleaseAction,\n} from '../../../shared/contracts/release-actions';\nimport { getService } from '../utils';\nimport { RELEASE_ACTION_MODEL_UID } from '../constants';\n\nconst releaseActionController = {\n async create(ctx: Koa.Context) {\n const releaseId: CreateReleaseAction.Request['params']['releaseId'] = ctx.params.releaseId;\n const releaseActionArgs: CreateReleaseAction.Request['body'] = ctx.request.body;\n\n await validateReleaseAction(releaseActionArgs);\n\n const releaseService = getService('release', { strapi });\n const releaseAction = await releaseService.createAction(releaseId, releaseActionArgs);\n\n ctx.body = {\n data: releaseAction,\n };\n },\n\n async findMany(ctx: Koa.Context) {\n const releaseId: GetReleaseActions.Request['params']['releaseId'] = ctx.params.releaseId;\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_ACTION_MODEL_UID,\n });\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const releaseService = getService('release', { strapi });\n const { results, pagination } = await releaseService.findActions(releaseId, {\n sort: query.groupBy === 'action' ? 'type' : query.groupBy,\n ...query,\n });\n const groupedData = await releaseService.groupActions(results, query.groupBy);\n\n ctx.body = {\n data: groupedData,\n meta: {\n pagination,\n },\n };\n },\n\n async update(ctx: Koa.Context) {\n const actionId: UpdateReleaseAction.Request['params']['actionId'] = ctx.params.actionId;\n const releaseId: UpdateReleaseAction.Request['params']['releaseId'] = ctx.params.releaseId;\n const releaseActionUpdateArgs: UpdateReleaseAction.Request['body'] = ctx.request.body;\n\n await validateReleaseActionUpdateSchema(releaseActionUpdateArgs);\n\n const releaseService = getService('release', { strapi });\n\n const updatedAction = await releaseService.updateAction(\n actionId,\n releaseId,\n releaseActionUpdateArgs\n );\n\n ctx.body = {\n data: updatedAction,\n };\n },\n\n async delete(ctx: Koa.Context) {\n const actionId: DeleteReleaseAction.Request['params']['actionId'] = ctx.params.actionId;\n const releaseId: DeleteReleaseAction.Request['params']['releaseId'] = ctx.params.releaseId;\n\n const releaseService = getService('release', { strapi });\n\n const deletedReleaseAction = await releaseService.deleteAction(actionId, releaseId);\n\n ctx.body = {\n data: deletedReleaseAction,\n };\n },\n};\n\nexport default releaseActionController;\n","import release from './release';\nimport releaseAction from './release-action';\n\nexport const controllers = { release, 'release-action': releaseAction };\n","export default {\n type: 'admin',\n routes: [\n {\n method: 'POST',\n path: '/',\n handler: 'release.create',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.create'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/',\n handler: 'release.findMany',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.read'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/:id',\n handler: 'release.findOne',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.read'],\n },\n },\n ],\n },\n },\n {\n method: 'PUT',\n path: '/:id',\n handler: 'release.update',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.update'],\n },\n },\n ],\n },\n },\n {\n method: 'DELETE',\n path: '/:id',\n handler: 'release.delete',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.delete'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/:id/publish',\n handler: 'release.publish',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.publish'],\n },\n },\n ],\n },\n },\n ],\n};\n","export default {\n type: 'admin',\n routes: [\n {\n method: 'POST',\n path: '/:releaseId/actions',\n handler: 'release-action.create',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.create-action'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/:releaseId/actions',\n handler: 'release-action.findMany',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.read'],\n },\n },\n ],\n },\n },\n {\n method: 'PUT',\n path: '/:releaseId/actions/:actionId',\n handler: 'release-action.update',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.update'],\n },\n },\n ],\n },\n },\n {\n method: 'DELETE',\n path: '/:releaseId/actions/:actionId',\n handler: 'release-action.delete',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.delete-action'],\n },\n },\n ],\n },\n },\n ],\n};\n","import release from './release';\nimport releaseAction from './release-action';\n\nexport const routes = {\n release,\n 'release-action': releaseAction,\n};\n","/* eslint-disable @typescript-eslint/no-var-requires */\nimport { register } from './register';\nimport { bootstrap } from './bootstrap';\nimport { contentTypes } from './content-types';\nimport { services } from './services';\nimport { controllers } from './controllers';\nimport { routes } from './routes';\nimport { getService } from './utils';\n\nconst { features } = require('@strapi/strapi/dist/utils/ee');\n\nconst getPlugin = () => {\n if (\n features.isEnabled('cms-content-releases') &&\n strapi.features.future.isEnabled('contentReleases')\n ) {\n return {\n register,\n bootstrap,\n contentTypes,\n services,\n controllers,\n routes,\n destroy() {\n if (\n features.isEnabled('cms-content-releases') &&\n strapi.features.future.isEnabled('contentReleases')\n ) {\n getService('event-manager').destroyAllListeners();\n }\n },\n };\n }\n\n // We keep returning contentTypes to avoid lost the data if feature is disabled\n return {\n contentTypes,\n };\n};\n\nexport default getPlugin();\n"],"names":["strapi","features","release","schema","releaseAction","_","setCreatorFields","errors","releaseValidation","eventManager","yup","validateYupSchema"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../server/src/constants.ts","../../server/src/utils/index.ts","../../server/src/register.ts","../../server/src/bootstrap.ts","../../server/src/content-types/release/schema.ts","../../server/src/content-types/release/index.ts","../../server/src/content-types/release-action/schema.ts","../../server/src/content-types/release-action/index.ts","../../server/src/content-types/index.ts","../../server/src/services/release-action.ts","../../server/src/services/release.ts","../../server/src/services/validation.ts","../../server/src/services/event-manager.ts","../../server/src/services/index.ts","../../shared/validation-schemas.ts","../../server/src/controllers/validation/release.ts","../../server/src/controllers/release.ts","../../server/src/controllers/validation/release-action.ts","../../server/src/controllers/release-action.ts","../../server/src/controllers/index.ts","../../server/src/routes/release.ts","../../server/src/routes/release-action.ts","../../server/src/routes/index.ts","../../server/src/index.ts"],"sourcesContent":["export const RELEASE_MODEL_UID = 'plugin::content-releases.release';\nexport const RELEASE_ACTION_MODEL_UID = 'plugin::content-releases.release-action';\n\nexport const ACTIONS = [\n {\n section: 'plugins',\n displayName: 'Read',\n uid: 'read',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Create',\n uid: 'create',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Edit',\n uid: 'update',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Delete',\n uid: 'delete',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Publish',\n uid: 'publish',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Remove an entry from a release',\n uid: 'delete-action',\n pluginName: 'content-releases',\n },\n {\n section: 'plugins',\n displayName: 'Add an entry to a release',\n uid: 'create-action',\n pluginName: 'content-releases',\n },\n];\n","export const getService = (\n name: 'release' | 'release-validation' | 'release-action' | 'event-manager',\n { strapi } = { strapi: global.strapi }\n) => {\n return strapi.plugin('content-releases').service(name);\n};\n","/* eslint-disable @typescript-eslint/no-var-requires */\nimport type { LoadedStrapi } from '@strapi/types';\nimport { ACTIONS } from './constants';\n\nimport { getService } from './utils';\n\nconst { features } = require('@strapi/strapi/dist/utils/ee');\n\nexport const register = async ({ strapi }: { strapi: LoadedStrapi }) => {\n if (\n features.isEnabled('cms-content-releases') &&\n strapi.features.future.isEnabled('contentReleases')\n ) {\n await strapi.admin.services.permission.actionProvider.registerMany(ACTIONS);\n\n const releaseActionService = getService('release-action', { strapi });\n const eventManager = getService('event-manager', { strapi });\n // Clean up release-actions when draft and publish is disabled\n const destroyContentTypeUpdateListener = strapi.eventHub.on(\n 'content-type.update',\n async ({ contentType }) => {\n if (contentType.schema.options.draftAndPublish === false) {\n await releaseActionService.deleteManyForContentType(contentType.uid);\n }\n }\n );\n eventManager.addDestroyListenerCallback(destroyContentTypeUpdateListener);\n // Clean up release-actions when a content-type is deleted\n const destroyContentTypeDeleteListener = strapi.eventHub.on(\n 'content-type.delete',\n async ({ contentType }) => {\n await releaseActionService.deleteManyForContentType(contentType.uid);\n }\n );\n eventManager.addDestroyListenerCallback(destroyContentTypeDeleteListener);\n }\n};\n","/* eslint-disable @typescript-eslint/no-var-requires */\nimport type { LoadedStrapi, Entity as StrapiEntity } from '@strapi/types';\nimport { RELEASE_ACTION_MODEL_UID } from './constants';\n\nconst { features } = require('@strapi/strapi/dist/utils/ee');\n\nexport const bootstrap = async ({ strapi }: { strapi: LoadedStrapi }) => {\n if (\n features.isEnabled('cms-content-releases') &&\n strapi.features.future.isEnabled('contentReleases')\n ) {\n strapi.db.lifecycles.subscribe({\n afterDelete(event) {\n // @ts-expect-error TODO: lifecycles types looks like are not 100% finished\n const { model, result } = event;\n\n // @ts-expect-error TODO: lifecycles types looks like are not 100% finished\n if (model.kind === 'collectionType' && model.options.draftAndPublish) {\n const { id } = result;\n\n strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({\n where: {\n target_type: model.uid,\n target_id: id,\n },\n });\n }\n },\n\n /**\n * deleteMany hook doesn't return the deleted entries ids\n * so we need to fetch them before deleting the entries to save the ids on our state\n */\n async beforeDeleteMany(event) {\n const { model, params } = event;\n\n // @ts-expect-error TODO: lifecycles types looks like are not 100% finished\n if (model.kind === 'collectionType' && model.options.draftAndPublish) {\n const { where } = params;\n\n const entriesToDelete = await strapi.db\n .query(model.uid)\n .findMany({ select: ['id'], where });\n\n event.state.entriesToDelete = entriesToDelete;\n }\n },\n\n /**\n * We delete the release actions related to deleted entries\n * We make this only after deleteMany is succesfully executed to avoid errors\n */\n async afterDeleteMany(event) {\n const { model, state } = event;\n const entriesToDelete = state.entriesToDelete;\n\n if (entriesToDelete) {\n await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({\n where: {\n target_type: model.uid,\n target_id: {\n $in: (entriesToDelete as Array<{ id: StrapiEntity.ID }>).map((entry) => entry.id),\n },\n },\n });\n }\n },\n });\n }\n};\n","import { RELEASE_ACTION_MODEL_UID } from '../../constants';\n\nexport default {\n collectionName: 'strapi_releases',\n info: {\n singularName: 'release',\n pluralName: 'releases',\n displayName: 'Release',\n },\n options: {\n draftAndPublish: false,\n },\n pluginOptions: {\n 'content-manager': {\n visible: false,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n name: {\n type: 'string',\n required: true,\n },\n releasedAt: {\n type: 'datetime',\n },\n actions: {\n type: 'relation',\n relation: 'oneToMany',\n target: RELEASE_ACTION_MODEL_UID,\n mappedBy: 'release',\n },\n },\n};\n","import schema from './schema';\n\nexport const release = {\n schema,\n};\n","import { RELEASE_MODEL_UID } from '../../constants';\n\nexport default {\n collectionName: 'strapi_release_actions',\n info: {\n singularName: 'release-action',\n pluralName: 'release-actions',\n displayName: 'Release Action',\n },\n options: {\n draftAndPublish: false,\n },\n pluginOptions: {\n 'content-manager': {\n visible: false,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n type: {\n type: 'enumeration',\n enum: ['publish', 'unpublish'],\n required: true,\n },\n entry: {\n type: 'relation',\n relation: 'morphToOne',\n configurable: false,\n },\n contentType: {\n type: 'string',\n required: true,\n },\n locale: {\n type: 'string',\n },\n release: {\n type: 'relation',\n relation: 'manyToOne',\n target: RELEASE_MODEL_UID,\n inversedBy: 'actions',\n },\n },\n};\n","import schema from './schema';\n\nexport const releaseAction = {\n schema,\n};\n","import { release } from './release';\nimport { releaseAction } from './release-action';\n\nexport const contentTypes = {\n release,\n 'release-action': releaseAction,\n};\n","import type { LoadedStrapi } from '@strapi/types';\nimport { RELEASE_ACTION_MODEL_UID } from '../constants';\nimport type { ReleaseAction } from '../../../shared/contracts/release-actions';\n\nconst createReleaseActionService = ({ strapi }: { strapi: LoadedStrapi }) => ({\n async deleteManyForContentType(contentTypeUid: ReleaseAction['contentType']) {\n return strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({\n where: {\n target_type: contentTypeUid,\n },\n });\n },\n});\n\nexport default createReleaseActionService;\n","import { setCreatorFields, errors } from '@strapi/utils';\n\nimport type { LoadedStrapi, EntityService, UID, Schema } from '@strapi/types';\n\nimport _ from 'lodash/fp';\n\nimport { RELEASE_ACTION_MODEL_UID, RELEASE_MODEL_UID } from '../constants';\nimport type {\n GetReleases,\n CreateRelease,\n UpdateRelease,\n PublishRelease,\n GetRelease,\n Release,\n DeleteRelease,\n GetContentTypeEntryReleases,\n} from '../../../shared/contracts/releases';\nimport type {\n CreateReleaseAction,\n GetReleaseActions,\n ReleaseAction,\n UpdateReleaseAction,\n DeleteReleaseAction,\n ReleaseActionGroupBy,\n} from '../../../shared/contracts/release-actions';\nimport type { Entity, UserInfo } from '../../../shared/types';\nimport { getService } from '../utils';\n\ninterface Locale extends Entity {\n name: string;\n code: string;\n}\n\ntype LocaleDictionary = {\n [key: Locale['code']]: Pick<Locale, 'name' | 'code'>;\n};\n\nconst getGroupName = (queryValue?: ReleaseActionGroupBy) => {\n switch (queryValue) {\n case 'contentType':\n return 'contentType.displayName';\n case 'action':\n return 'type';\n case 'locale':\n return _.getOr('No locale', 'locale.name');\n default:\n return 'contentType.displayName';\n }\n};\n\nconst createReleaseService = ({ strapi }: { strapi: LoadedStrapi }) => ({\n async create(releaseData: CreateRelease.Request['body'], { user }: { user: UserInfo }) {\n const releaseWithCreatorFields = await setCreatorFields({ user })(releaseData);\n\n await getService('release-validation', { strapi }).validatePendingReleasesLimit();\n\n return strapi.entityService.create(RELEASE_MODEL_UID, {\n data: releaseWithCreatorFields,\n });\n },\n\n async findOne(id: GetRelease.Request['params']['id'], query = {}) {\n const release = await strapi.entityService.findOne(RELEASE_MODEL_UID, id, {\n ...query,\n });\n\n return release;\n },\n\n findPage(query?: GetReleases.Request['query']) {\n return strapi.entityService.findPage(RELEASE_MODEL_UID, {\n ...query,\n populate: {\n actions: {\n // @ts-expect-error Ignore missing properties\n count: true,\n },\n },\n });\n },\n\n async findManyForContentTypeEntry(\n contentTypeUid: GetContentTypeEntryReleases.Request['query']['contentTypeUid'],\n entryId: GetContentTypeEntryReleases.Request['query']['entryId'],\n {\n hasEntryAttached,\n }: { hasEntryAttached?: GetContentTypeEntryReleases.Request['query']['hasEntryAttached'] } = {\n hasEntryAttached: false,\n }\n ) {\n const whereActions = hasEntryAttached\n ? {\n // Find all Releases where the content type entry is present\n actions: {\n target_type: contentTypeUid,\n target_id: entryId,\n },\n }\n : {\n // Find all Releases where the content type entry is not present\n $or: [\n {\n $not: {\n actions: {\n target_type: contentTypeUid,\n target_id: entryId,\n },\n },\n },\n {\n actions: null,\n },\n ],\n };\n const populateAttachedAction = hasEntryAttached\n ? {\n // Filter the action to get only the content type entry\n actions: {\n where: {\n target_type: contentTypeUid,\n target_id: entryId,\n },\n },\n }\n : {};\n\n const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({\n where: {\n ...whereActions,\n releasedAt: {\n $null: true,\n },\n },\n populate: {\n ...populateAttachedAction,\n },\n });\n\n return releases.map((release) => {\n if (release.actions?.length) {\n const [actionForEntry] = release.actions;\n\n // Remove the actions key to replace it with an action key\n delete release.actions;\n\n return {\n ...release,\n action: actionForEntry,\n };\n }\n\n return release;\n });\n },\n\n async update(\n id: number,\n releaseData: UpdateRelease.Request['body'],\n { user }: { user: UserInfo }\n ) {\n const releaseWithCreatorFields = await setCreatorFields({ user, isEdition: true })(releaseData);\n\n const release = await strapi.entityService.findOne(RELEASE_MODEL_UID, id);\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${id}`);\n }\n\n if (release.releasedAt) {\n throw new errors.ValidationError('Release already published');\n }\n\n const updatedRelease = await strapi.entityService.update(RELEASE_MODEL_UID, id, {\n /*\n * The type returned from the entity service: Partial<Input<\"plugin::content-releases.release\">>\n * is not compatible with the type we are passing here: UpdateRelease.Request['body']\n */\n // @ts-expect-error see above\n data: releaseWithCreatorFields,\n });\n\n return updatedRelease;\n },\n\n async createAction(\n releaseId: CreateReleaseAction.Request['params']['releaseId'],\n action: Pick<CreateReleaseAction.Request['body'], 'type' | 'entry'>\n ) {\n const { validateEntryContentType, validateUniqueEntry } = getService('release-validation', {\n strapi,\n });\n\n await Promise.all([\n validateEntryContentType(action.entry.contentType),\n validateUniqueEntry(releaseId, action),\n ]);\n\n const release = await strapi.entityService.findOne(RELEASE_MODEL_UID, releaseId);\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n if (release.releasedAt) {\n throw new errors.ValidationError('Release already published');\n }\n\n const { entry, type } = action;\n\n return strapi.entityService.create(RELEASE_ACTION_MODEL_UID, {\n data: {\n type,\n contentType: entry.contentType,\n locale: entry.locale,\n entry: {\n id: entry.id,\n __type: entry.contentType,\n __pivot: { field: 'entry' },\n },\n release: releaseId,\n },\n populate: { release: { fields: ['id'] }, entry: { fields: ['id'] } },\n });\n },\n\n async findActions(\n releaseId: GetReleaseActions.Request['params']['releaseId'],\n query?: GetReleaseActions.Request['query']\n ) {\n const release = await strapi.entityService.findOne(RELEASE_MODEL_UID, releaseId, {\n fields: ['id'],\n });\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n return strapi.entityService.findPage(RELEASE_ACTION_MODEL_UID, {\n ...query,\n populate: {\n entry: {\n populate: '*',\n },\n },\n filters: {\n release: releaseId,\n },\n });\n },\n\n async countActions(query: EntityService.Params.Pick<typeof RELEASE_ACTION_MODEL_UID, 'filters'>) {\n return strapi.entityService.count(RELEASE_ACTION_MODEL_UID, query);\n },\n\n async groupActions(actions: ReleaseAction[], groupBy: ReleaseActionGroupBy) {\n const contentTypeUids = actions.reduce<ReleaseAction['contentType'][]>((acc, action) => {\n if (!acc.includes(action.contentType)) {\n acc.push(action.contentType);\n }\n\n return acc;\n }, []);\n const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(\n contentTypeUids\n );\n const allLocalesDictionary = await this.getLocalesDataForActions();\n\n const formattedData = actions.map((action: ReleaseAction) => {\n const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];\n\n return {\n ...action,\n locale: action.locale ? allLocalesDictionary[action.locale] : null,\n contentType: {\n displayName,\n mainFieldValue: action.entry[mainField],\n uid: action.contentType,\n },\n };\n });\n\n const groupName = getGroupName(groupBy);\n return _.groupBy(groupName)(formattedData);\n },\n\n async getLocalesDataForActions() {\n if (!strapi.plugin('i18n')) {\n return {};\n }\n\n const allLocales: Locale[] = (await strapi.plugin('i18n').service('locales').find()) || [];\n return allLocales.reduce<LocaleDictionary>((acc, locale) => {\n acc[locale.code] = { name: locale.name, code: locale.code };\n\n return acc;\n }, {});\n },\n\n async getContentTypesDataForActions(contentTypesUids: ReleaseAction['contentType'][]) {\n const contentManagerContentTypeService = strapi\n .plugin('content-manager')\n .service('content-types');\n\n const contentTypesData: Record<UID.ContentType, { mainField: string; displayName: string }> =\n {};\n for (const contentTypeUid of contentTypesUids) {\n const contentTypeConfig = await contentManagerContentTypeService.findConfiguration({\n uid: contentTypeUid,\n });\n\n contentTypesData[contentTypeUid] = {\n mainField: contentTypeConfig.settings.mainField,\n displayName: strapi.getModel(contentTypeUid).info.displayName,\n };\n }\n\n return contentTypesData;\n },\n\n getContentTypeModelsFromActions(actions: ReleaseAction[]) {\n const contentTypeUids = actions.reduce<ReleaseAction['contentType'][]>((acc, action) => {\n if (!acc.includes(action.contentType)) {\n acc.push(action.contentType);\n }\n\n return acc;\n }, []);\n\n const contentTypeModelsMap = contentTypeUids.reduce(\n (\n acc: { [key: ReleaseAction['contentType']]: Schema.ContentType },\n contentTypeUid: ReleaseAction['contentType']\n ) => {\n acc[contentTypeUid] = strapi.getModel(contentTypeUid);\n\n return acc;\n },\n {}\n );\n\n return contentTypeModelsMap;\n },\n\n async getAllComponents() {\n const contentManagerComponentsService = strapi.plugin('content-manager').service('components');\n\n const components = await contentManagerComponentsService.findAllComponents();\n\n const componentsMap = components.reduce(\n (acc: { [key: Schema.Component['uid']]: Schema.Component }, component: Schema.Component) => {\n acc[component.uid] = component;\n\n return acc;\n },\n {}\n );\n\n return componentsMap;\n },\n\n async delete(releaseId: DeleteRelease.Request['params']['id']) {\n const release = (await strapi.entityService.findOne(RELEASE_MODEL_UID, releaseId, {\n populate: {\n actions: {\n fields: ['id'],\n },\n },\n })) as unknown as Release;\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n if (release.releasedAt) {\n throw new errors.ValidationError('Release already published');\n }\n\n // Only delete the release and its actions is you in fact can delete all the actions and the release\n // Otherwise, if the transaction fails it throws an error\n await strapi.db.transaction(async () => {\n await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({\n where: {\n id: {\n $in: release.actions.map((action) => action.id),\n },\n },\n });\n await strapi.entityService.delete(RELEASE_MODEL_UID, releaseId);\n });\n\n return release;\n },\n\n async publish(releaseId: PublishRelease.Request['params']['id']) {\n // We need to pass the type because entityService.findOne is not returning the correct type\n const releaseWithPopulatedActionEntries = (await strapi.entityService.findOne(\n RELEASE_MODEL_UID,\n releaseId,\n {\n populate: {\n actions: {\n populate: {\n entry: true,\n },\n },\n },\n }\n )) as unknown as Release;\n\n if (!releaseWithPopulatedActionEntries) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n if (releaseWithPopulatedActionEntries.releasedAt) {\n throw new errors.ValidationError('Release already published');\n }\n\n if (releaseWithPopulatedActionEntries.actions.length === 0) {\n throw new errors.ValidationError('No entries to publish');\n }\n\n /**\n * We separate publish and unpublish actions group by content type\n */\n const actions: {\n [key: UID.ContentType]: {\n publish: ReleaseAction['entry'][];\n unpublish: ReleaseAction['entry'][];\n };\n } = {};\n for (const action of releaseWithPopulatedActionEntries.actions) {\n const contentTypeUid = action.contentType;\n\n if (!actions[contentTypeUid]) {\n actions[contentTypeUid] = {\n publish: [],\n unpublish: [],\n };\n }\n\n if (action.type === 'publish') {\n actions[contentTypeUid].publish.push(action.entry);\n } else {\n actions[contentTypeUid].unpublish.push(action.entry);\n }\n }\n\n const entityManagerService = strapi.plugin('content-manager').service('entity-manager');\n\n // Only publish the release if all action updates are applied successfully to their entry, otherwise leave everything as is\n await strapi.db.transaction(async () => {\n for (const contentTypeUid of Object.keys(actions)) {\n const { publish, unpublish } = actions[contentTypeUid as UID.ContentType];\n\n if (publish.length > 0) {\n await entityManagerService.publishMany(publish, contentTypeUid);\n }\n\n if (unpublish.length > 0) {\n await entityManagerService.unpublishMany(unpublish, contentTypeUid);\n }\n }\n });\n\n // When the transaction fails it throws an error, when it is successful proceed to updating the release\n const release = await strapi.entityService.update(RELEASE_MODEL_UID, releaseId, {\n data: {\n /*\n * The type returned from the entity service: Partial<Input<\"plugin::content-releases.release\">> looks like it's wrong\n */\n // @ts-expect-error see above\n releasedAt: new Date(),\n },\n });\n\n return release;\n },\n\n async updateAction(\n actionId: UpdateReleaseAction.Request['params']['actionId'],\n releaseId: UpdateReleaseAction.Request['params']['releaseId'],\n update: UpdateReleaseAction.Request['body']\n ) {\n const updatedAction = await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({\n where: {\n id: actionId,\n release: {\n id: releaseId,\n releasedAt: {\n $null: true,\n },\n },\n },\n data: update,\n });\n\n if (!updatedAction) {\n throw new errors.NotFoundError(\n `Action with id ${actionId} not found in release with id ${releaseId} or it is already published`\n );\n }\n\n return updatedAction;\n },\n\n async deleteAction(\n actionId: DeleteReleaseAction.Request['params']['actionId'],\n releaseId: DeleteReleaseAction.Request['params']['releaseId']\n ) {\n const deletedAction = await strapi.db.query(RELEASE_ACTION_MODEL_UID).delete({\n where: {\n id: actionId,\n release: {\n id: releaseId,\n releasedAt: {\n $null: true,\n },\n },\n },\n });\n\n if (!deletedAction) {\n throw new errors.NotFoundError(\n `Action with id ${actionId} not found in release with id ${releaseId} or it is already published`\n );\n }\n\n return deletedAction;\n },\n});\n\nexport default createReleaseService;\n","import { errors } from '@strapi/utils';\nimport { LoadedStrapi } from '@strapi/types';\nimport EE from '@strapi/strapi/dist/utils/ee';\nimport type { Release } from '../../../shared/contracts/releases';\nimport type { CreateReleaseAction } from '../../../shared/contracts/release-actions';\nimport { RELEASE_MODEL_UID } from '../constants';\n\nconst createReleaseValidationService = ({ strapi }: { strapi: LoadedStrapi }) => ({\n async validateUniqueEntry(\n releaseId: CreateReleaseAction.Request['params']['releaseId'],\n releaseActionArgs: CreateReleaseAction.Request['body']\n ) {\n /**\n * Asserting the type, otherwise TS complains: 'release.actions' is of type 'unknown', even though the types come through for non-populated fields...\n * Possibly related to the comment on GetValues: https://github.com/strapi/strapi/blob/main/packages/core/types/src/modules/entity-service/result.ts\n */\n const release = (await strapi.entityService.findOne(RELEASE_MODEL_UID, releaseId, {\n populate: { actions: { populate: { entry: { fields: ['id'] } } } },\n })) as Release | null;\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n const isEntryInRelease = release.actions.some(\n (action) =>\n Number(action.entry.id) === Number(releaseActionArgs.entry.id) &&\n action.contentType === releaseActionArgs.entry.contentType\n );\n\n if (isEntryInRelease) {\n throw new errors.ValidationError(\n `Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`\n );\n }\n },\n validateEntryContentType(\n contentTypeUid: CreateReleaseAction.Request['body']['entry']['contentType']\n ) {\n const contentType = strapi.contentType(contentTypeUid);\n\n if (!contentType) {\n throw new errors.NotFoundError(`No content type found for uid ${contentTypeUid}`);\n }\n\n // TODO: V5 migration - All contentType will have draftAndPublish enabled\n if (!contentType.options?.draftAndPublish) {\n throw new errors.ValidationError(\n `Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`\n );\n }\n },\n async validatePendingReleasesLimit() {\n // Use the maximum releases option if it exists, otherwise default to 3\n const maximumPendingReleases =\n // @ts-expect-error - options is not typed into features\n EE.features.get('cms-content-releases')?.options?.maximumReleases || 3;\n\n const [, pendingReleasesCount] = await strapi.db.query(RELEASE_MODEL_UID).findWithCount({\n filters: {\n releasedAt: {\n $null: true,\n },\n },\n });\n\n // Unlimited is a number that will never be reached like 9999\n if (pendingReleasesCount >= maximumPendingReleases) {\n throw new errors.ValidationError('You have reached the maximum number of pending releases');\n }\n },\n});\n\nexport default createReleaseValidationService;\n","interface ReleaseEventServiceState {\n destroyListenerCallbacks: (() => void)[];\n}\n\nconst createEventManagerService = () => {\n const state: ReleaseEventServiceState = {\n destroyListenerCallbacks: [],\n };\n\n return {\n addDestroyListenerCallback(destroyListenerCallback: () => void) {\n state.destroyListenerCallbacks.push(destroyListenerCallback);\n },\n\n destroyAllListeners() {\n if (!state.destroyListenerCallbacks.length) {\n return;\n }\n\n state.destroyListenerCallbacks.forEach((destroyListenerCallback) => {\n destroyListenerCallback();\n });\n },\n };\n};\n\nexport default createEventManagerService;\n","import releaseAction from './release-action';\nimport release from './release';\nimport releaseValidation from './validation';\nimport eventManager from './event-manager';\n\nexport const services = {\n release,\n 'release-action': releaseAction,\n 'release-validation': releaseValidation,\n 'event-manager': eventManager,\n};\n","import * as yup from 'yup';\n\nexport const RELEASE_SCHEMA = yup\n .object()\n .shape({\n name: yup.string().trim().required(),\n })\n .required()\n .noUnknown();\n","import { validateYupSchema } from '@strapi/utils';\nimport { RELEASE_SCHEMA } from '../../../../shared/validation-schemas';\n\nexport const validateRelease = validateYupSchema(RELEASE_SCHEMA);\n","import type Koa from 'koa';\nimport { errors } from '@strapi/utils';\nimport { RELEASE_MODEL_UID } from '../constants';\nimport { validateRelease } from './validation/release';\nimport type {\n CreateRelease,\n UpdateRelease,\n PublishRelease,\n GetRelease,\n Release,\n DeleteRelease,\n GetContentTypeEntryReleases,\n GetReleases,\n} from '../../../shared/contracts/releases';\nimport type { UserInfo } from '../../../shared/types';\nimport { getService } from '../utils';\n\ntype ReleaseWithPopulatedActions = Release & { actions: { count: number } };\n\nconst releaseController = {\n async findMany(ctx: Koa.Context) {\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n\n const releaseService = getService('release', { strapi });\n\n // Handle requests for releases filtered by content type entry\n const isFindManyForContentTypeEntry = Boolean(ctx.query?.contentTypeUid && ctx.query?.entryId);\n if (isFindManyForContentTypeEntry) {\n const query: GetContentTypeEntryReleases.Request['query'] =\n await permissionsManager.sanitizeQuery(ctx.query);\n\n const contentTypeUid = query.contentTypeUid;\n const entryId = query.entryId;\n // Parse the string value or fallback to a default\n const hasEntryAttached: GetContentTypeEntryReleases.Request['query']['hasEntryAttached'] =\n typeof query.hasEntryAttached === 'string' ? JSON.parse(query.hasEntryAttached) : false;\n\n const data = await releaseService.findManyForContentTypeEntry(contentTypeUid, entryId, {\n hasEntryAttached,\n });\n\n ctx.body = { data };\n } else {\n const query: GetReleases.Request['query'] = await permissionsManager.sanitizeQuery(ctx.query);\n const { results, pagination } = await releaseService.findPage(query);\n\n const data = results.map((release: ReleaseWithPopulatedActions) => {\n const { actions, ...releaseData } = release;\n\n return {\n ...releaseData,\n actions: {\n meta: {\n count: actions.count,\n },\n },\n };\n });\n\n ctx.body = { data, meta: { pagination } };\n }\n },\n\n async findOne(ctx: Koa.Context) {\n const id: GetRelease.Request['params']['id'] = ctx.params.id;\n\n const releaseService = getService('release', { strapi });\n\n const release = await releaseService.findOne(id, { populate: ['createdBy'] });\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_MODEL_UID,\n });\n const sanitizedRelease = await permissionsManager.sanitizeOutput(release);\n\n const count = await releaseService.countActions({\n filters: {\n release: id,\n },\n });\n\n if (!release) {\n throw new errors.NotFoundError(`Release not found for id: ${id}`);\n }\n\n // Format the data object\n const data = {\n ...sanitizedRelease,\n actions: {\n meta: {\n count,\n },\n },\n };\n\n ctx.body = { data };\n },\n\n async create(ctx: Koa.Context) {\n const user: UserInfo = ctx.state.user;\n const releaseArgs: CreateRelease.Request['body'] = ctx.request.body;\n\n await validateRelease(releaseArgs);\n\n const releaseService = getService('release', { strapi });\n const release = await releaseService.create(releaseArgs, { user });\n\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_MODEL_UID,\n });\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(release),\n };\n },\n\n async update(ctx: Koa.Context) {\n const user: UserInfo = ctx.state.user;\n const releaseArgs: UpdateRelease.Request['body'] = ctx.request.body;\n const id: UpdateRelease.Request['params']['id'] = ctx.params.id;\n\n await validateRelease(releaseArgs);\n\n const releaseService = getService('release', { strapi });\n const release = await releaseService.update(id, releaseArgs, { user });\n\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_MODEL_UID,\n });\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(release),\n };\n },\n\n async delete(ctx: Koa.Context) {\n const id: DeleteRelease.Request['params']['id'] = ctx.params.id;\n\n const releaseService = getService('release', { strapi });\n const release = await releaseService.delete(id);\n\n ctx.body = {\n data: release,\n };\n },\n\n async publish(ctx: Koa.Context) {\n const user: PublishRelease.Request['state']['user'] = ctx.state.user;\n const id: PublishRelease.Request['params']['id'] = ctx.params.id;\n\n const releaseService = getService('release', { strapi });\n const release = await releaseService.publish(id, { user });\n\n ctx.body = {\n data: release,\n };\n },\n};\n\nexport default releaseController;\n","import { yup, validateYupSchema } from '@strapi/utils';\n\nconst RELEASE_ACTION_SCHEMA = yup.object().shape({\n entry: yup\n .object()\n .shape({\n id: yup.strapiID().required(),\n contentType: yup.string().required(),\n })\n .required(),\n type: yup.string().oneOf(['publish', 'unpublish']).required(),\n});\n\nconst RELEASE_ACTION_UPDATE_SCHEMA = yup.object().shape({\n type: yup.string().oneOf(['publish', 'unpublish']).required(),\n});\n\nexport const validateReleaseAction = validateYupSchema(RELEASE_ACTION_SCHEMA);\nexport const validateReleaseActionUpdateSchema = validateYupSchema(RELEASE_ACTION_UPDATE_SCHEMA);\n","import type Koa from 'koa';\n\nimport { mapAsync } from '@strapi/utils';\nimport {\n validateReleaseAction,\n validateReleaseActionUpdateSchema,\n} from './validation/release-action';\nimport type {\n CreateReleaseAction,\n GetReleaseActions,\n UpdateReleaseAction,\n DeleteReleaseAction,\n} from '../../../shared/contracts/release-actions';\nimport { getService } from '../utils';\nimport { RELEASE_ACTION_MODEL_UID } from '../constants';\n\nconst releaseActionController = {\n async create(ctx: Koa.Context) {\n const releaseId: CreateReleaseAction.Request['params']['releaseId'] = ctx.params.releaseId;\n const releaseActionArgs: CreateReleaseAction.Request['body'] = ctx.request.body;\n\n await validateReleaseAction(releaseActionArgs);\n\n const releaseService = getService('release', { strapi });\n const releaseAction = await releaseService.createAction(releaseId, releaseActionArgs);\n\n ctx.body = {\n data: releaseAction,\n };\n },\n\n async findMany(ctx: Koa.Context) {\n const releaseId: GetReleaseActions.Request['params']['releaseId'] = ctx.params.releaseId;\n const permissionsManager = strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: RELEASE_ACTION_MODEL_UID,\n });\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const releaseService = getService('release', { strapi });\n const { results, pagination } = await releaseService.findActions(releaseId, {\n sort: query.groupBy === 'action' ? 'type' : query.groupBy,\n ...query,\n });\n\n /**\n * Release actions can be related to entries of different content types.\n * We need to sanitize the entry output according to that content type.\n * So, we group the sanitized output function by content type.\n */\n const contentTypeOutputSanitizers = results.reduce((acc, action) => {\n if (acc[action.contentType]) {\n return acc;\n }\n\n const contentTypePermissionsManager =\n strapi.admin.services.permission.createPermissionsManager({\n ability: ctx.state.userAbility,\n model: action.contentType,\n });\n\n acc[action.contentType] = contentTypePermissionsManager.sanitizeOutput;\n\n return acc;\n }, {});\n\n /**\n * sanitizeOutput doesn't work if you use it directly on the Release Action model, it doesn't sanitize the entries\n * So, we need to sanitize manually each entry inside a Release Action\n */\n const sanitizedResults = await mapAsync(results, async (action) => ({\n ...action,\n entry: await contentTypeOutputSanitizers[action.contentType](action.entry),\n }));\n\n const groupedData = await releaseService.groupActions(sanitizedResults, query.groupBy);\n\n const contentTypes = releaseService.getContentTypeModelsFromActions(results);\n const components = await releaseService.getAllComponents();\n\n ctx.body = {\n data: groupedData,\n meta: {\n pagination,\n contentTypes,\n components,\n },\n };\n },\n\n async update(ctx: Koa.Context) {\n const actionId: UpdateReleaseAction.Request['params']['actionId'] = ctx.params.actionId;\n const releaseId: UpdateReleaseAction.Request['params']['releaseId'] = ctx.params.releaseId;\n const releaseActionUpdateArgs: UpdateReleaseAction.Request['body'] = ctx.request.body;\n\n await validateReleaseActionUpdateSchema(releaseActionUpdateArgs);\n\n const releaseService = getService('release', { strapi });\n\n const updatedAction = await releaseService.updateAction(\n actionId,\n releaseId,\n releaseActionUpdateArgs\n );\n\n ctx.body = {\n data: updatedAction,\n };\n },\n\n async delete(ctx: Koa.Context) {\n const actionId: DeleteReleaseAction.Request['params']['actionId'] = ctx.params.actionId;\n const releaseId: DeleteReleaseAction.Request['params']['releaseId'] = ctx.params.releaseId;\n\n const releaseService = getService('release', { strapi });\n\n const deletedReleaseAction = await releaseService.deleteAction(actionId, releaseId);\n\n ctx.body = {\n data: deletedReleaseAction,\n };\n },\n};\n\nexport default releaseActionController;\n","import release from './release';\nimport releaseAction from './release-action';\n\nexport const controllers = { release, 'release-action': releaseAction };\n","export default {\n type: 'admin',\n routes: [\n {\n method: 'POST',\n path: '/',\n handler: 'release.create',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.create'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/',\n handler: 'release.findMany',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.read'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/:id',\n handler: 'release.findOne',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.read'],\n },\n },\n ],\n },\n },\n {\n method: 'PUT',\n path: '/:id',\n handler: 'release.update',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.update'],\n },\n },\n ],\n },\n },\n {\n method: 'DELETE',\n path: '/:id',\n handler: 'release.delete',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.delete'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/:id/publish',\n handler: 'release.publish',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.publish'],\n },\n },\n ],\n },\n },\n ],\n};\n","export default {\n type: 'admin',\n routes: [\n {\n method: 'POST',\n path: '/:releaseId/actions',\n handler: 'release-action.create',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.create-action'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/:releaseId/actions',\n handler: 'release-action.findMany',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.read'],\n },\n },\n ],\n },\n },\n {\n method: 'PUT',\n path: '/:releaseId/actions/:actionId',\n handler: 'release-action.update',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.update'],\n },\n },\n ],\n },\n },\n {\n method: 'DELETE',\n path: '/:releaseId/actions/:actionId',\n handler: 'release-action.delete',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::content-releases.delete-action'],\n },\n },\n ],\n },\n },\n ],\n};\n","import release from './release';\nimport releaseAction from './release-action';\n\nexport const routes = {\n release,\n 'release-action': releaseAction,\n};\n","/* eslint-disable @typescript-eslint/no-var-requires */\nimport { register } from './register';\nimport { bootstrap } from './bootstrap';\nimport { contentTypes } from './content-types';\nimport { services } from './services';\nimport { controllers } from './controllers';\nimport { routes } from './routes';\nimport { getService } from './utils';\n\nconst { features } = require('@strapi/strapi/dist/utils/ee');\n\nconst getPlugin = () => {\n if (\n features.isEnabled('cms-content-releases') &&\n strapi.features.future.isEnabled('contentReleases')\n ) {\n return {\n register,\n bootstrap,\n contentTypes,\n services,\n controllers,\n routes,\n destroy() {\n if (\n features.isEnabled('cms-content-releases') &&\n strapi.features.future.isEnabled('contentReleases')\n ) {\n getService('event-manager').destroyAllListeners();\n }\n },\n };\n }\n\n // We keep returning contentTypes to avoid lost the data if feature is disabled\n return {\n contentTypes,\n };\n};\n\nexport default getPlugin();\n"],"names":["strapi","features","release","schema","releaseAction","_","setCreatorFields","errors","EE","releaseValidation","eventManager","yup","validateYupSchema","mapAsync","contentTypes"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import { setCreatorFields, errors, validateYupSchema, yup as yup$1 } from "@strapi/utils";
1
+ import { setCreatorFields, errors, validateYupSchema, yup as yup$1, mapAsync } from "@strapi/utils";
2
2
  import _ from "lodash/fp";
3
+ import EE from "@strapi/strapi/dist/utils/ee";
3
4
  import * as yup from "yup";
4
5
  const RELEASE_MODEL_UID = "plugin::content-releases.release";
5
6
  const RELEASE_ACTION_MODEL_UID = "plugin::content-releases.release-action";
@@ -223,18 +224,19 @@ const createReleaseActionService = ({ strapi: strapi2 }) => ({
223
224
  const getGroupName = (queryValue) => {
224
225
  switch (queryValue) {
225
226
  case "contentType":
226
- return "entry.contentType.displayName";
227
+ return "contentType.displayName";
227
228
  case "action":
228
229
  return "type";
229
230
  case "locale":
230
- return _.getOr("No locale", "entry.locale.name");
231
+ return _.getOr("No locale", "locale.name");
231
232
  default:
232
- return "entry.contentType.displayName";
233
+ return "contentType.displayName";
233
234
  }
234
235
  };
235
236
  const createReleaseService = ({ strapi: strapi2 }) => ({
236
237
  async create(releaseData, { user }) {
237
238
  const releaseWithCreatorFields = await setCreatorFields({ user })(releaseData);
239
+ await getService("release-validation", { strapi: strapi2 }).validatePendingReleasesLimit();
238
240
  return strapi2.entityService.create(RELEASE_MODEL_UID, {
239
241
  data: releaseWithCreatorFields
240
242
  });
@@ -375,7 +377,9 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
375
377
  return strapi2.entityService.findPage(RELEASE_ACTION_MODEL_UID, {
376
378
  ...query,
377
379
  populate: {
378
- entry: true
380
+ entry: {
381
+ populate: "*"
382
+ }
379
383
  },
380
384
  filters: {
381
385
  release: releaseId
@@ -395,29 +399,32 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
395
399
  const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(
396
400
  contentTypeUids
397
401
  );
398
- const allLocales = await strapi2.plugin("i18n").service("locales").find();
399
- const allLocalesDictionary = allLocales.reduce((acc, locale) => {
400
- acc[locale.code] = { name: locale.name, code: locale.code };
401
- return acc;
402
- }, {});
402
+ const allLocalesDictionary = await this.getLocalesDataForActions();
403
403
  const formattedData = actions.map((action) => {
404
404
  const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
405
405
  return {
406
406
  ...action,
407
- entry: {
408
- id: action.entry.id,
409
- contentType: {
410
- displayName,
411
- mainFieldValue: action.entry[mainField]
412
- },
413
- locale: action.locale ? allLocalesDictionary[action.locale] : null,
414
- status: action.entry.publishedAt ? "published" : "draft"
407
+ locale: action.locale ? allLocalesDictionary[action.locale] : null,
408
+ contentType: {
409
+ displayName,
410
+ mainFieldValue: action.entry[mainField],
411
+ uid: action.contentType
415
412
  }
416
413
  };
417
414
  });
418
415
  const groupName = getGroupName(groupBy);
419
416
  return _.groupBy(groupName)(formattedData);
420
417
  },
418
+ async getLocalesDataForActions() {
419
+ if (!strapi2.plugin("i18n")) {
420
+ return {};
421
+ }
422
+ const allLocales = await strapi2.plugin("i18n").service("locales").find() || [];
423
+ return allLocales.reduce((acc, locale) => {
424
+ acc[locale.code] = { name: locale.name, code: locale.code };
425
+ return acc;
426
+ }, {});
427
+ },
421
428
  async getContentTypesDataForActions(contentTypesUids) {
422
429
  const contentManagerContentTypeService = strapi2.plugin("content-manager").service("content-types");
423
430
  const contentTypesData = {};
@@ -432,6 +439,34 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
432
439
  }
433
440
  return contentTypesData;
434
441
  },
442
+ getContentTypeModelsFromActions(actions) {
443
+ const contentTypeUids = actions.reduce((acc, action) => {
444
+ if (!acc.includes(action.contentType)) {
445
+ acc.push(action.contentType);
446
+ }
447
+ return acc;
448
+ }, []);
449
+ const contentTypeModelsMap = contentTypeUids.reduce(
450
+ (acc, contentTypeUid) => {
451
+ acc[contentTypeUid] = strapi2.getModel(contentTypeUid);
452
+ return acc;
453
+ },
454
+ {}
455
+ );
456
+ return contentTypeModelsMap;
457
+ },
458
+ async getAllComponents() {
459
+ const contentManagerComponentsService = strapi2.plugin("content-manager").service("components");
460
+ const components = await contentManagerComponentsService.findAllComponents();
461
+ const componentsMap = components.reduce(
462
+ (acc, component) => {
463
+ acc[component.uid] = component;
464
+ return acc;
465
+ },
466
+ {}
467
+ );
468
+ return componentsMap;
469
+ },
435
470
  async delete(releaseId) {
436
471
  const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
437
472
  populate: {
@@ -586,6 +621,22 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
586
621
  `Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`
587
622
  );
588
623
  }
624
+ },
625
+ async validatePendingReleasesLimit() {
626
+ const maximumPendingReleases = (
627
+ // @ts-expect-error - options is not typed into features
628
+ EE.features.get("cms-content-releases")?.options?.maximumReleases || 3
629
+ );
630
+ const [, pendingReleasesCount] = await strapi2.db.query(RELEASE_MODEL_UID).findWithCount({
631
+ filters: {
632
+ releasedAt: {
633
+ $null: true
634
+ }
635
+ }
636
+ });
637
+ if (pendingReleasesCount >= maximumPendingReleases) {
638
+ throw new errors.ValidationError("You have reached the maximum number of pending releases");
639
+ }
589
640
  }
590
641
  });
591
642
  const createEventManagerService = () => {
@@ -760,11 +811,30 @@ const releaseActionController = {
760
811
  sort: query.groupBy === "action" ? "type" : query.groupBy,
761
812
  ...query
762
813
  });
763
- const groupedData = await releaseService.groupActions(results, query.groupBy);
814
+ const contentTypeOutputSanitizers = results.reduce((acc, action) => {
815
+ if (acc[action.contentType]) {
816
+ return acc;
817
+ }
818
+ const contentTypePermissionsManager = strapi.admin.services.permission.createPermissionsManager({
819
+ ability: ctx.state.userAbility,
820
+ model: action.contentType
821
+ });
822
+ acc[action.contentType] = contentTypePermissionsManager.sanitizeOutput;
823
+ return acc;
824
+ }, {});
825
+ const sanitizedResults = await mapAsync(results, async (action) => ({
826
+ ...action,
827
+ entry: await contentTypeOutputSanitizers[action.contentType](action.entry)
828
+ }));
829
+ const groupedData = await releaseService.groupActions(sanitizedResults, query.groupBy);
830
+ const contentTypes2 = releaseService.getContentTypeModelsFromActions(results);
831
+ const components = await releaseService.getAllComponents();
764
832
  ctx.body = {
765
833
  data: groupedData,
766
834
  meta: {
767
- pagination
835
+ pagination,
836
+ contentTypes: contentTypes2,
837
+ components
768
838
  }
769
839
  };
770
840
  },