chore(content-releases): remove future flags (#19245)

This commit is contained in:
markkaylor 2024-01-19 15:54:10 +01:00 committed by GitHub
parent 0d0b078513
commit d172fb07e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 663 additions and 682 deletions

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,7 @@ import type { Plugin } from '@strapi/types';
const admin: Plugin.Config.AdminInput = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
register(app: any) {
if (
window.strapi.features.isEnabled('cms-content-releases') &&
window.strapi.future.isEnabled('contentReleases')
) {
if (window.strapi.features.isEnabled('cms-content-releases')) {
app.addMenuLink({
to: `/plugins/${pluginId}`,
icon: PaperPlane,

View File

@ -23,9 +23,9 @@ describe('register', () => {
addDestroyListenerCallback: jest.fn(),
})),
})),
eventHub: {
on: jest.fn(),
},
hook: jest.fn(() => ({
register: jest.fn(),
})),
admin: {
services: {
permission: {

View File

@ -1,23 +1,20 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import type { LoadedStrapi, Entity as StrapiEntity } from '@strapi/types';
import { RELEASE_ACTION_MODEL_UID } from './constants';
const { features } = require('@strapi/strapi/dist/utils/ee');
export const bootstrap = async ({ strapi }: { strapi: LoadedStrapi }) => {
if (
features.isEnabled('cms-content-releases') &&
strapi.features.future.isEnabled('contentReleases')
) {
if (features.isEnabled('cms-content-releases')) {
// Clean up release-actions when an entry is deleted
strapi.db.lifecycles.subscribe({
afterDelete(event) {
// @ts-expect-error TODO: lifecycles types looks like are not 100% finished
const { model, result } = event;
// @ts-expect-error TODO: lifecycles types looks like are not 100% finished
if (model.kind === 'collectionType' && model.options.draftAndPublish) {
if (model.kind === 'collectionType' && model.options?.draftAndPublish) {
const { id } = result;
strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
where: {
target_type: model.uid,
@ -26,26 +23,21 @@ export const bootstrap = async ({ strapi }: { strapi: LoadedStrapi }) => {
});
}
},
/**
* deleteMany hook doesn't return the deleted entries ids
* so we need to fetch them before deleting the entries to save the ids on our state
*/
async beforeDeleteMany(event) {
const { model, params } = event;
// @ts-expect-error TODO: lifecycles types looks like are not 100% finished
if (model.kind === 'collectionType' && model.options.draftAndPublish) {
if (model.kind === 'collectionType' && model.options?.draftAndPublish) {
const { where } = params;
const entriesToDelete = await strapi.db
.query(model.uid)
.findMany({ select: ['id'], where });
event.state.entriesToDelete = entriesToDelete;
}
},
/**
* We delete the release actions related to deleted entries
* We make this only after deleteMany is succesfully executed to avoid errors
@ -53,7 +45,6 @@ export const bootstrap = async ({ strapi }: { strapi: LoadedStrapi }) => {
async afterDeleteMany(event) {
const { model, state } = event;
const entriesToDelete = state.entriesToDelete;
if (entriesToDelete) {
await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
where: {

View File

@ -5,15 +5,11 @@ import { contentTypes } from './content-types';
import { services } from './services';
import { controllers } from './controllers';
import { routes } from './routes';
import { getService } from './utils';
const { features } = require('@strapi/strapi/dist/utils/ee');
const getPlugin = () => {
if (
features.isEnabled('cms-content-releases') &&
strapi.features.future.isEnabled('contentReleases')
) {
if (features.isEnabled('cms-content-releases')) {
return {
register,
bootstrap,
@ -21,14 +17,6 @@ const getPlugin = () => {
services,
controllers,
routes,
destroy() {
if (
features.isEnabled('cms-content-releases') &&
strapi.features.future.isEnabled('contentReleases')
) {
getService('event-manager').destroyAllListeners();
}
},
};
}

View File

@ -0,0 +1,53 @@
import type { Schema } from '@strapi/types';
import { contentTypes as contentTypesUtils, mapAsync } from '@strapi/utils';
import { difference, keys } from 'lodash';
import { RELEASE_ACTION_MODEL_UID } from '../constants';
interface Input {
oldContentTypes: Record<string, Schema.ContentType>;
contentTypes: Record<string, Schema.ContentType>;
}
export async function deleteActionsOnDisableDraftAndPublish({
oldContentTypes,
contentTypes,
}: Input) {
if (!oldContentTypes) {
return;
}
for (const uid in contentTypes) {
if (!oldContentTypes[uid]) {
continue;
}
const oldContentType = oldContentTypes[uid];
const contentType = contentTypes[uid];
if (
contentTypesUtils.hasDraftAndPublish(oldContentType) &&
!contentTypesUtils.hasDraftAndPublish(contentType)
) {
await strapi.db
?.queryBuilder(RELEASE_ACTION_MODEL_UID)
.delete()
.where({ contentType: uid })
.execute();
}
}
}
export async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes }: Input) {
const deletedContentTypes = difference(keys(oldContentTypes), keys(contentTypes)) ?? [];
if (deletedContentTypes.length) {
await mapAsync(deletedContentTypes, async (deletedContentTypeUID: unknown) => {
return strapi.db
?.queryBuilder(RELEASE_ACTION_MODEL_UID)
.delete()
.where({ contentType: deletedContentTypeUID })
.execute();
});
}
}

View File

@ -1,37 +1,16 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import type { LoadedStrapi } from '@strapi/types';
import { ACTIONS } from './constants';
import { getService } from './utils';
import { ACTIONS } from './constants';
import { deleteActionsOnDeleteContentType, deleteActionsOnDisableDraftAndPublish } from './migrations';
const { features } = require('@strapi/strapi/dist/utils/ee');
export const register = async ({ strapi }: { strapi: LoadedStrapi }) => {
if (
features.isEnabled('cms-content-releases') &&
strapi.features.future.isEnabled('contentReleases')
) {
if (features.isEnabled('cms-content-releases')) {
await strapi.admin.services.permission.actionProvider.registerMany(ACTIONS);
const releaseActionService = getService('release-action', { strapi });
const eventManager = getService('event-manager', { strapi });
// Clean up release-actions when draft and publish is disabled
const destroyContentTypeUpdateListener = strapi.eventHub.on(
'content-type.update',
async ({ contentType }) => {
if (contentType.schema.options.draftAndPublish === false) {
await releaseActionService.deleteManyForContentType(contentType.uid);
}
}
);
eventManager.addDestroyListenerCallback(destroyContentTypeUpdateListener);
// Clean up release-actions when a content-type is deleted
const destroyContentTypeDeleteListener = strapi.eventHub.on(
'content-type.delete',
async ({ contentType }) => {
await releaseActionService.deleteManyForContentType(contentType.uid);
}
);
eventManager.addDestroyListenerCallback(destroyContentTypeDeleteListener);
strapi.hook('strapi::content-types.beforeSync').register(deleteActionsOnDisableDraftAndPublish);
strapi.hook('strapi::content-types.afterSync').register(deleteActionsOnDeleteContentType);
}
};

View File

@ -1,23 +0,0 @@
import createReleaseActionService from '../release-action';
describe('Release Action service', () => {
it('deletes all release actions given a content type uid', async () => {
const strapiMock = {
db: {
query: jest.fn().mockReturnValue({
deleteMany: jest.fn(),
}),
},
};
// @ts-expect-error Ignore missing properties
const releaseActionService = createReleaseActionService({ strapi: strapiMock });
await releaseActionService.deleteManyForContentType('api::test.test');
expect(strapiMock.db.query().deleteMany).toHaveBeenCalledWith({
where: {
target_type: 'api::test.test',
},
});
});
});

View File

@ -1,27 +0,0 @@
interface ReleaseEventServiceState {
destroyListenerCallbacks: (() => void)[];
}
const createEventManagerService = () => {
const state: ReleaseEventServiceState = {
destroyListenerCallbacks: [],
};
return {
addDestroyListenerCallback(destroyListenerCallback: () => void) {
state.destroyListenerCallbacks.push(destroyListenerCallback);
},
destroyAllListeners() {
if (!state.destroyListenerCallbacks.length) {
return;
}
state.destroyListenerCallbacks.forEach((destroyListenerCallback) => {
destroyListenerCallback();
});
},
};
};
export default createEventManagerService;

View File

@ -1,11 +1,7 @@
import releaseAction from './release-action';
import release from './release';
import releaseValidation from './validation';
import eventManager from './event-manager';
export const services = {
release,
'release-action': releaseAction,
'release-validation': releaseValidation,
'event-manager': eventManager,
};

View File

@ -1,15 +0,0 @@
import type { LoadedStrapi } from '@strapi/types';
import { RELEASE_ACTION_MODEL_UID } from '../constants';
import type { ReleaseAction } from '../../../shared/contracts/release-actions';
const createReleaseActionService = ({ strapi }: { strapi: LoadedStrapi }) => ({
async deleteManyForContentType(contentTypeUid: ReleaseAction['contentType']) {
return strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
where: {
target_type: contentTypeUid,
},
});
},
});
export default createReleaseActionService;

View File

@ -26,7 +26,7 @@ import type {
import type { Entity, UserInfo } from '../../../shared/types';
import { getService } from '../utils';
interface Locale extends Entity {
export interface Locale extends Entity {
name: string;
code: string;
}