@strapi/content-releases 0.0.0-experimental.fc1ac2acd58c8a5a858679956b6d102ac5ee4011 → 0.0.0-experimental.fea7af0bd6b406e4648e4c6669829249f73eb60f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{App-C768ulk4.js → App-HjWtUYmc.js} +233 -261
- package/dist/_chunks/App-HjWtUYmc.js.map +1 -0
- package/dist/_chunks/{App-0Er6xxcq.mjs → App-gu1aiP6i.mjs} +237 -265
- package/dist/_chunks/App-gu1aiP6i.mjs.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-3tRbmbY3.mjs} +2 -2
- package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-bpIYXOfu.js} +2 -2
- package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
- package/dist/_chunks/{en-gcJJ5htG.js → en-HrREghh3.js} +11 -3
- package/dist/_chunks/en-HrREghh3.js.map +1 -0
- package/dist/_chunks/{en-WuuhP6Bn.mjs → en-ltT1TlKQ.mjs} +11 -3
- package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
- package/dist/_chunks/{index-BLSMpbpZ.js → index-ZNwxYN8H.js} +338 -31
- package/dist/_chunks/index-ZNwxYN8H.js.map +1 -0
- package/dist/_chunks/{index-fJx1up7m.mjs → index-mvj9PSKd.mjs} +345 -38
- package/dist/_chunks/index-mvj9PSKd.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +380 -172
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +380 -173
- package/dist/server/index.mjs.map +1 -1
- package/package.json +22 -15
- package/dist/_chunks/App-0Er6xxcq.mjs.map +0 -1
- package/dist/_chunks/App-C768ulk4.js.map +0 -1
- package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +0 -1
- package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +0 -1
- package/dist/_chunks/en-WuuhP6Bn.mjs.map +0 -1
- package/dist/_chunks/en-gcJJ5htG.js.map +0 -1
- package/dist/_chunks/index-BLSMpbpZ.js.map +0 -1
- package/dist/_chunks/index-fJx1up7m.mjs.map +0 -1
- package/dist/admin/src/components/CMReleasesContainer.d.ts +0 -1
- package/dist/admin/src/components/RelativeTime.d.ts +0 -28
- package/dist/admin/src/components/ReleaseActionMenu.d.ts +0 -26
- package/dist/admin/src/components/ReleaseActionOptions.d.ts +0 -9
- package/dist/admin/src/components/ReleaseModal.d.ts +0 -16
- package/dist/admin/src/constants.d.ts +0 -58
- package/dist/admin/src/index.d.ts +0 -3
- package/dist/admin/src/pages/App.d.ts +0 -1
- package/dist/admin/src/pages/PurchaseContentReleases.d.ts +0 -2
- package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +0 -2
- package/dist/admin/src/pages/ReleasesPage.d.ts +0 -8
- package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +0 -181
- package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +0 -39
- package/dist/admin/src/pluginId.d.ts +0 -1
- package/dist/admin/src/services/axios.d.ts +0 -29
- package/dist/admin/src/services/release.d.ts +0 -369
- package/dist/admin/src/store/hooks.d.ts +0 -7
- package/dist/admin/src/utils/time.d.ts +0 -1
- package/dist/server/src/bootstrap.d.ts +0 -5
- package/dist/server/src/bootstrap.d.ts.map +0 -1
- package/dist/server/src/constants.d.ts +0 -12
- package/dist/server/src/constants.d.ts.map +0 -1
- package/dist/server/src/content-types/index.d.ts +0 -99
- package/dist/server/src/content-types/index.d.ts.map +0 -1
- package/dist/server/src/content-types/release/index.d.ts +0 -48
- package/dist/server/src/content-types/release/index.d.ts.map +0 -1
- package/dist/server/src/content-types/release/schema.d.ts +0 -47
- package/dist/server/src/content-types/release/schema.d.ts.map +0 -1
- package/dist/server/src/content-types/release-action/index.d.ts +0 -50
- package/dist/server/src/content-types/release-action/index.d.ts.map +0 -1
- package/dist/server/src/content-types/release-action/schema.d.ts +0 -49
- package/dist/server/src/content-types/release-action/schema.d.ts.map +0 -1
- package/dist/server/src/controllers/index.d.ts +0 -18
- package/dist/server/src/controllers/index.d.ts.map +0 -1
- package/dist/server/src/controllers/release-action.d.ts +0 -9
- package/dist/server/src/controllers/release-action.d.ts.map +0 -1
- package/dist/server/src/controllers/release.d.ts +0 -11
- package/dist/server/src/controllers/release.d.ts.map +0 -1
- package/dist/server/src/controllers/validation/release-action.d.ts +0 -3
- package/dist/server/src/controllers/validation/release-action.d.ts.map +0 -1
- package/dist/server/src/controllers/validation/release.d.ts +0 -2
- package/dist/server/src/controllers/validation/release.d.ts.map +0 -1
- package/dist/server/src/destroy.d.ts +0 -5
- package/dist/server/src/destroy.d.ts.map +0 -1
- package/dist/server/src/index.d.ts +0 -3838
- package/dist/server/src/index.d.ts.map +0 -1
- package/dist/server/src/migrations/index.d.ts +0 -10
- package/dist/server/src/migrations/index.d.ts.map +0 -1
- package/dist/server/src/register.d.ts +0 -5
- package/dist/server/src/register.d.ts.map +0 -1
- package/dist/server/src/routes/index.d.ts +0 -35
- package/dist/server/src/routes/index.d.ts.map +0 -1
- package/dist/server/src/routes/release-action.d.ts +0 -18
- package/dist/server/src/routes/release-action.d.ts.map +0 -1
- package/dist/server/src/routes/release.d.ts +0 -18
- package/dist/server/src/routes/release.d.ts.map +0 -1
- package/dist/server/src/services/index.d.ts +0 -3572
- package/dist/server/src/services/index.d.ts.map +0 -1
- package/dist/server/src/services/release.d.ts +0 -1812
- package/dist/server/src/services/release.d.ts.map +0 -1
- package/dist/server/src/services/scheduling.d.ts +0 -18
- package/dist/server/src/services/scheduling.d.ts.map +0 -1
- package/dist/server/src/services/validation.d.ts +0 -14
- package/dist/server/src/services/validation.d.ts.map +0 -1
- package/dist/server/src/utils/index.d.ts +0 -18
- package/dist/server/src/utils/index.d.ts.map +0 -1
- package/dist/shared/contracts/release-actions.d.ts +0 -105
- package/dist/shared/contracts/release-actions.d.ts.map +0 -1
- package/dist/shared/contracts/releases.d.ts +0 -166
- package/dist/shared/contracts/releases.d.ts.map +0 -1
- package/dist/shared/types.d.ts +0 -24
- package/dist/shared/types.d.ts.map +0 -1
- package/dist/shared/validation-schemas.d.ts +0 -2
- package/dist/shared/validation-schemas.d.ts.map +0 -1
package/dist/server/index.js
CHANGED
|
@@ -3,6 +3,7 @@ const utils = require("@strapi/utils");
|
|
|
3
3
|
const isEqual = require("lodash/isEqual");
|
|
4
4
|
const lodash = require("lodash");
|
|
5
5
|
const _ = require("lodash/fp");
|
|
6
|
+
const EE = require("@strapi/strapi/dist/utils/ee");
|
|
6
7
|
const nodeSchedule = require("node-schedule");
|
|
7
8
|
const yup = require("yup");
|
|
8
9
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
@@ -26,6 +27,7 @@ function _interopNamespace(e) {
|
|
|
26
27
|
}
|
|
27
28
|
const isEqual__default = /* @__PURE__ */ _interopDefault(isEqual);
|
|
28
29
|
const ___default = /* @__PURE__ */ _interopDefault(_);
|
|
30
|
+
const EE__default = /* @__PURE__ */ _interopDefault(EE);
|
|
29
31
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
|
30
32
|
const RELEASE_MODEL_UID = "plugin::content-releases.release";
|
|
31
33
|
const RELEASE_ACTION_MODEL_UID = "plugin::content-releases.release-action";
|
|
@@ -99,10 +101,28 @@ const getEntryValidStatus = async (contentTypeUid, entry, { strapi: strapi2 } =
|
|
|
99
101
|
return false;
|
|
100
102
|
}
|
|
101
103
|
};
|
|
104
|
+
async function deleteActionsOnDisableDraftAndPublish({
|
|
105
|
+
oldContentTypes,
|
|
106
|
+
contentTypes: contentTypes2
|
|
107
|
+
}) {
|
|
108
|
+
if (!oldContentTypes) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
for (const uid in contentTypes2) {
|
|
112
|
+
if (!oldContentTypes[uid]) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const oldContentType = oldContentTypes[uid];
|
|
116
|
+
const contentType = contentTypes2[uid];
|
|
117
|
+
if (utils.contentTypes.hasDraftAndPublish(oldContentType) && !utils.contentTypes.hasDraftAndPublish(contentType)) {
|
|
118
|
+
await strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: uid }).execute();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
102
122
|
async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
103
123
|
const deletedContentTypes = lodash.difference(lodash.keys(oldContentTypes), lodash.keys(contentTypes2)) ?? [];
|
|
104
124
|
if (deletedContentTypes.length) {
|
|
105
|
-
await utils.
|
|
125
|
+
await utils.mapAsync(deletedContentTypes, async (deletedContentTypeUID) => {
|
|
106
126
|
return strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: deletedContentTypeUID }).execute();
|
|
107
127
|
});
|
|
108
128
|
}
|
|
@@ -121,7 +141,7 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
121
141
|
}
|
|
122
142
|
}
|
|
123
143
|
});
|
|
124
|
-
utils.
|
|
144
|
+
utils.mapAsync(releasesWithoutStatus, async (release2) => {
|
|
125
145
|
const actions = release2.actions;
|
|
126
146
|
const notValidatedActions = actions.filter((action) => action.isEntryValid === null);
|
|
127
147
|
for (const action of notValidatedActions) {
|
|
@@ -152,7 +172,7 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
152
172
|
}
|
|
153
173
|
}
|
|
154
174
|
});
|
|
155
|
-
utils.
|
|
175
|
+
utils.mapAsync(publishedReleases, async (release2) => {
|
|
156
176
|
return strapi.db.query(RELEASE_MODEL_UID).update({
|
|
157
177
|
where: {
|
|
158
178
|
id: release2.id
|
|
@@ -165,9 +185,11 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
165
185
|
}
|
|
166
186
|
async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
167
187
|
if (oldContentTypes !== void 0 && contentTypes2 !== void 0) {
|
|
168
|
-
const contentTypesWithDraftAndPublish = Object.keys(oldContentTypes)
|
|
188
|
+
const contentTypesWithDraftAndPublish = Object.keys(oldContentTypes).filter(
|
|
189
|
+
(uid) => oldContentTypes[uid]?.options?.draftAndPublish
|
|
190
|
+
);
|
|
169
191
|
const releasesAffected = /* @__PURE__ */ new Set();
|
|
170
|
-
utils.
|
|
192
|
+
utils.mapAsync(contentTypesWithDraftAndPublish, async (contentTypeUID) => {
|
|
171
193
|
const oldContentType = oldContentTypes[contentTypeUID];
|
|
172
194
|
const contentType = contentTypes2[contentTypeUID];
|
|
173
195
|
if (!isEqual__default.default(oldContentType?.attributes, contentType?.attributes)) {
|
|
@@ -180,8 +202,8 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
180
202
|
release: true
|
|
181
203
|
}
|
|
182
204
|
});
|
|
183
|
-
await utils.
|
|
184
|
-
if (action.entry) {
|
|
205
|
+
await utils.mapAsync(actions, async (action) => {
|
|
206
|
+
if (action.entry && action.release) {
|
|
185
207
|
const populatedEntry = await getPopulatedEntry(contentTypeUID, action.entry.id, {
|
|
186
208
|
strapi
|
|
187
209
|
});
|
|
@@ -203,21 +225,77 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
203
225
|
});
|
|
204
226
|
}
|
|
205
227
|
}).then(() => {
|
|
206
|
-
utils.
|
|
228
|
+
utils.mapAsync(releasesAffected, async (releaseId) => {
|
|
207
229
|
return getService("release", { strapi }).updateReleaseStatus(releaseId);
|
|
208
230
|
});
|
|
209
231
|
});
|
|
210
232
|
}
|
|
211
233
|
}
|
|
234
|
+
async function disableContentTypeLocalized({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
235
|
+
if (!oldContentTypes) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
239
|
+
if (!i18nPlugin) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
for (const uid in contentTypes2) {
|
|
243
|
+
if (!oldContentTypes[uid]) {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
const oldContentType = oldContentTypes[uid];
|
|
247
|
+
const contentType = contentTypes2[uid];
|
|
248
|
+
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
249
|
+
if (isLocalizedContentType(oldContentType) && !isLocalizedContentType(contentType)) {
|
|
250
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
251
|
+
locale: null
|
|
252
|
+
}).where({ contentType: uid }).execute();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async function enableContentTypeLocalized({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
257
|
+
if (!oldContentTypes) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
261
|
+
if (!i18nPlugin) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
for (const uid in contentTypes2) {
|
|
265
|
+
if (!oldContentTypes[uid]) {
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
const oldContentType = oldContentTypes[uid];
|
|
269
|
+
const contentType = contentTypes2[uid];
|
|
270
|
+
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
271
|
+
const { getDefaultLocale } = i18nPlugin.service("locales");
|
|
272
|
+
if (!isLocalizedContentType(oldContentType) && isLocalizedContentType(contentType)) {
|
|
273
|
+
const defaultLocale = await getDefaultLocale();
|
|
274
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
275
|
+
locale: defaultLocale
|
|
276
|
+
}).where({ contentType: uid }).execute();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
|
|
212
281
|
const register = async ({ strapi: strapi2 }) => {
|
|
213
|
-
if (
|
|
282
|
+
if (features$2.isEnabled("cms-content-releases")) {
|
|
214
283
|
await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
|
|
215
|
-
strapi2.hook("strapi::content-types.
|
|
284
|
+
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish).register(disableContentTypeLocalized);
|
|
285
|
+
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(enableContentTypeLocalized).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
286
|
+
}
|
|
287
|
+
if (strapi2.plugin("graphql")) {
|
|
288
|
+
const graphqlExtensionService = strapi2.plugin("graphql").service("extension");
|
|
289
|
+
graphqlExtensionService.shadowCRUD(RELEASE_MODEL_UID).disable();
|
|
290
|
+
graphqlExtensionService.shadowCRUD(RELEASE_ACTION_MODEL_UID).disable();
|
|
216
291
|
}
|
|
217
292
|
};
|
|
293
|
+
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
218
294
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
219
|
-
if (
|
|
220
|
-
const contentTypesWithDraftAndPublish = Object.keys(strapi2.contentTypes)
|
|
295
|
+
if (features$1.isEnabled("cms-content-releases")) {
|
|
296
|
+
const contentTypesWithDraftAndPublish = Object.keys(strapi2.contentTypes).filter(
|
|
297
|
+
(uid) => strapi2.contentTypes[uid]?.options?.draftAndPublish
|
|
298
|
+
);
|
|
221
299
|
strapi2.db.lifecycles.subscribe({
|
|
222
300
|
models: contentTypesWithDraftAndPublish,
|
|
223
301
|
async afterDelete(event) {
|
|
@@ -253,7 +331,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
253
331
|
*/
|
|
254
332
|
async beforeDeleteMany(event) {
|
|
255
333
|
const { model, params } = event;
|
|
256
|
-
if (model.kind === "collectionType") {
|
|
334
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
257
335
|
const { where } = params;
|
|
258
336
|
const entriesToDelete = await strapi2.db.query(model.uid).findMany({ select: ["id"], where });
|
|
259
337
|
event.state.entriesToDelete = entriesToDelete;
|
|
@@ -335,27 +413,23 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
335
413
|
}
|
|
336
414
|
}
|
|
337
415
|
});
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
});
|
|
348
|
-
}
|
|
416
|
+
getService("scheduling", { strapi: strapi2 }).syncFromDatabase().catch((err) => {
|
|
417
|
+
strapi2.log.error(
|
|
418
|
+
"Error while syncing scheduled jobs from the database in the content-releases plugin. This could lead to errors in the releases scheduling."
|
|
419
|
+
);
|
|
420
|
+
throw err;
|
|
421
|
+
});
|
|
422
|
+
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
|
423
|
+
strapi2.webhookStore.addAllowedEvent(key, value);
|
|
424
|
+
});
|
|
349
425
|
}
|
|
350
426
|
};
|
|
351
427
|
const destroy = async ({ strapi: strapi2 }) => {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
job.cancel();
|
|
358
|
-
}
|
|
428
|
+
const scheduledJobs = getService("scheduling", {
|
|
429
|
+
strapi: strapi2
|
|
430
|
+
}).getAll();
|
|
431
|
+
for (const [, job] of scheduledJobs) {
|
|
432
|
+
job.cancel();
|
|
359
433
|
}
|
|
360
434
|
};
|
|
361
435
|
const schema$1 = {
|
|
@@ -480,6 +554,94 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
480
554
|
release: release2
|
|
481
555
|
});
|
|
482
556
|
};
|
|
557
|
+
const publishSingleTypeAction = async (uid, actionType, entryId) => {
|
|
558
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
559
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
560
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
561
|
+
const entry = await strapi2.entityService.findOne(uid, entryId, { populate });
|
|
562
|
+
try {
|
|
563
|
+
if (actionType === "publish") {
|
|
564
|
+
await entityManagerService.publish(entry, uid);
|
|
565
|
+
} else {
|
|
566
|
+
await entityManagerService.unpublish(entry, uid);
|
|
567
|
+
}
|
|
568
|
+
} catch (error) {
|
|
569
|
+
if (error instanceof utils.errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
570
|
+
;
|
|
571
|
+
else {
|
|
572
|
+
throw error;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
const publishCollectionTypeAction = async (uid, entriesToPublishIds, entriestoUnpublishIds) => {
|
|
577
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
578
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
579
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
580
|
+
const entriesToPublish = await strapi2.entityService.findMany(uid, {
|
|
581
|
+
filters: {
|
|
582
|
+
id: {
|
|
583
|
+
$in: entriesToPublishIds
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
populate
|
|
587
|
+
});
|
|
588
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(uid, {
|
|
589
|
+
filters: {
|
|
590
|
+
id: {
|
|
591
|
+
$in: entriestoUnpublishIds
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
populate
|
|
595
|
+
});
|
|
596
|
+
if (entriesToPublish.length > 0) {
|
|
597
|
+
await entityManagerService.publishMany(entriesToPublish, uid);
|
|
598
|
+
}
|
|
599
|
+
if (entriesToUnpublish.length > 0) {
|
|
600
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, uid);
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
const getFormattedActions = async (releaseId) => {
|
|
604
|
+
const actions = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findMany({
|
|
605
|
+
where: {
|
|
606
|
+
release: {
|
|
607
|
+
id: releaseId
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
populate: {
|
|
611
|
+
entry: {
|
|
612
|
+
fields: ["id"]
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
if (actions.length === 0) {
|
|
617
|
+
throw new utils.errors.ValidationError("No entries to publish");
|
|
618
|
+
}
|
|
619
|
+
const collectionTypeActions = {};
|
|
620
|
+
const singleTypeActions = [];
|
|
621
|
+
for (const action of actions) {
|
|
622
|
+
const contentTypeUid = action.contentType;
|
|
623
|
+
if (strapi2.contentTypes[contentTypeUid].kind === "collectionType") {
|
|
624
|
+
if (!collectionTypeActions[contentTypeUid]) {
|
|
625
|
+
collectionTypeActions[contentTypeUid] = {
|
|
626
|
+
entriesToPublishIds: [],
|
|
627
|
+
entriesToUnpublishIds: []
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
if (action.type === "publish") {
|
|
631
|
+
collectionTypeActions[contentTypeUid].entriesToPublishIds.push(action.entry.id);
|
|
632
|
+
} else {
|
|
633
|
+
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
634
|
+
}
|
|
635
|
+
} else {
|
|
636
|
+
singleTypeActions.push({
|
|
637
|
+
uid: contentTypeUid,
|
|
638
|
+
action: action.type,
|
|
639
|
+
id: action.entry.id
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return { collectionTypeActions, singleTypeActions };
|
|
644
|
+
};
|
|
483
645
|
return {
|
|
484
646
|
async create(releaseData, { user }) {
|
|
485
647
|
const releaseWithCreatorFields = await utils.setCreatorFields({ user })(releaseData);
|
|
@@ -499,7 +661,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
499
661
|
status: "empty"
|
|
500
662
|
}
|
|
501
663
|
});
|
|
502
|
-
if (
|
|
664
|
+
if (releaseWithCreatorFields.scheduledAt) {
|
|
503
665
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
504
666
|
await schedulingService.set(release2.id, release2.scheduledAt);
|
|
505
667
|
}
|
|
@@ -523,12 +685,18 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
523
685
|
}
|
|
524
686
|
});
|
|
525
687
|
},
|
|
526
|
-
async findManyWithContentTypeEntryAttached(contentTypeUid,
|
|
688
|
+
async findManyWithContentTypeEntryAttached(contentTypeUid, entriesIds) {
|
|
689
|
+
let entries = entriesIds;
|
|
690
|
+
if (!Array.isArray(entriesIds)) {
|
|
691
|
+
entries = [entriesIds];
|
|
692
|
+
}
|
|
527
693
|
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
528
694
|
where: {
|
|
529
695
|
actions: {
|
|
530
696
|
target_type: contentTypeUid,
|
|
531
|
-
target_id:
|
|
697
|
+
target_id: {
|
|
698
|
+
$in: entries
|
|
699
|
+
}
|
|
532
700
|
},
|
|
533
701
|
releasedAt: {
|
|
534
702
|
$null: true
|
|
@@ -539,18 +707,25 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
539
707
|
actions: {
|
|
540
708
|
where: {
|
|
541
709
|
target_type: contentTypeUid,
|
|
542
|
-
target_id:
|
|
710
|
+
target_id: {
|
|
711
|
+
$in: entries
|
|
712
|
+
}
|
|
713
|
+
},
|
|
714
|
+
populate: {
|
|
715
|
+
entry: {
|
|
716
|
+
select: ["id"]
|
|
717
|
+
}
|
|
543
718
|
}
|
|
544
719
|
}
|
|
545
720
|
}
|
|
546
721
|
});
|
|
547
722
|
return releases.map((release2) => {
|
|
548
723
|
if (release2.actions?.length) {
|
|
549
|
-
const
|
|
724
|
+
const actionsForEntry = release2.actions;
|
|
550
725
|
delete release2.actions;
|
|
551
726
|
return {
|
|
552
727
|
...release2,
|
|
553
|
-
|
|
728
|
+
actions: actionsForEntry
|
|
554
729
|
};
|
|
555
730
|
}
|
|
556
731
|
return release2;
|
|
@@ -624,13 +799,11 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
624
799
|
// @ts-expect-error see above
|
|
625
800
|
data: releaseWithCreatorFields
|
|
626
801
|
});
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
schedulingService.cancel(id);
|
|
633
|
-
}
|
|
802
|
+
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
803
|
+
if (releaseData.scheduledAt) {
|
|
804
|
+
await schedulingService.set(id, releaseData.scheduledAt);
|
|
805
|
+
} else if (release2.scheduledAt) {
|
|
806
|
+
schedulingService.cancel(id);
|
|
634
807
|
}
|
|
635
808
|
this.updateReleaseStatus(id);
|
|
636
809
|
strapi2.telemetry.send("didUpdateContentRelease");
|
|
@@ -796,7 +969,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
796
969
|
});
|
|
797
970
|
await strapi2.entityService.delete(RELEASE_MODEL_UID, releaseId);
|
|
798
971
|
});
|
|
799
|
-
if (
|
|
972
|
+
if (release2.scheduledAt) {
|
|
800
973
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
801
974
|
await schedulingService.cancel(release2.id);
|
|
802
975
|
}
|
|
@@ -804,145 +977,71 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
804
977
|
return release2;
|
|
805
978
|
},
|
|
806
979
|
async publish(releaseId) {
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
actions: {
|
|
814
|
-
populate: {
|
|
815
|
-
entry: {
|
|
816
|
-
fields: ["id"]
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
);
|
|
823
|
-
if (!releaseWithPopulatedActionEntries) {
|
|
980
|
+
const {
|
|
981
|
+
release: release2,
|
|
982
|
+
error
|
|
983
|
+
} = await strapi2.db.transaction(async ({ trx }) => {
|
|
984
|
+
const lockedRelease = await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).select(["id", "name", "releasedAt", "status"]).first().transacting(trx).forUpdate().execute();
|
|
985
|
+
if (!lockedRelease) {
|
|
824
986
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
825
987
|
}
|
|
826
|
-
if (
|
|
988
|
+
if (lockedRelease.releasedAt) {
|
|
827
989
|
throw new utils.errors.ValidationError("Release already published");
|
|
828
990
|
}
|
|
829
|
-
if (
|
|
830
|
-
throw new utils.errors.ValidationError("
|
|
991
|
+
if (lockedRelease.status === "failed") {
|
|
992
|
+
throw new utils.errors.ValidationError("Release failed to publish");
|
|
831
993
|
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
entriesToUnpublishIds: []
|
|
841
|
-
};
|
|
842
|
-
}
|
|
843
|
-
if (action.type === "publish") {
|
|
844
|
-
collectionTypeActions[contentTypeUid].entriestoPublishIds.push(action.entry.id);
|
|
845
|
-
} else {
|
|
846
|
-
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
847
|
-
}
|
|
848
|
-
} else {
|
|
849
|
-
singleTypeActions.push({
|
|
850
|
-
uid: contentTypeUid,
|
|
851
|
-
action: action.type,
|
|
852
|
-
id: action.entry.id
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
857
|
-
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
858
|
-
await strapi2.db.transaction(async () => {
|
|
859
|
-
for (const { uid, action, id } of singleTypeActions) {
|
|
860
|
-
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
861
|
-
const entry = await strapi2.entityService.findOne(uid, id, { populate });
|
|
862
|
-
try {
|
|
863
|
-
if (action === "publish") {
|
|
864
|
-
await entityManagerService.publish(entry, uid);
|
|
865
|
-
} else {
|
|
866
|
-
await entityManagerService.unpublish(entry, uid);
|
|
867
|
-
}
|
|
868
|
-
} catch (error) {
|
|
869
|
-
if (error instanceof utils.errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft")) {
|
|
870
|
-
} else {
|
|
871
|
-
throw error;
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
876
|
-
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
877
|
-
const { entriestoPublishIds, entriesToUnpublishIds } = collectionTypeActions[contentTypeUid];
|
|
878
|
-
const entriesToPublish = await strapi2.entityService.findMany(
|
|
879
|
-
contentTypeUid,
|
|
880
|
-
{
|
|
881
|
-
filters: {
|
|
882
|
-
id: {
|
|
883
|
-
$in: entriestoPublishIds
|
|
884
|
-
}
|
|
885
|
-
},
|
|
886
|
-
populate
|
|
887
|
-
}
|
|
888
|
-
);
|
|
889
|
-
const entriesToUnpublish = await strapi2.entityService.findMany(
|
|
890
|
-
contentTypeUid,
|
|
891
|
-
{
|
|
892
|
-
filters: {
|
|
893
|
-
id: {
|
|
894
|
-
$in: entriesToUnpublishIds
|
|
895
|
-
}
|
|
896
|
-
},
|
|
897
|
-
populate
|
|
898
|
-
}
|
|
899
|
-
);
|
|
900
|
-
if (entriesToPublish.length > 0) {
|
|
901
|
-
await entityManagerService.publishMany(entriesToPublish, contentTypeUid);
|
|
994
|
+
try {
|
|
995
|
+
strapi2.log.info(`[Content Releases] Starting to publish release ${lockedRelease.name}`);
|
|
996
|
+
const { collectionTypeActions, singleTypeActions } = await getFormattedActions(
|
|
997
|
+
releaseId
|
|
998
|
+
);
|
|
999
|
+
await strapi2.db.transaction(async () => {
|
|
1000
|
+
for (const { uid, action, id } of singleTypeActions) {
|
|
1001
|
+
await publishSingleTypeAction(uid, action, id);
|
|
902
1002
|
}
|
|
903
|
-
|
|
904
|
-
|
|
1003
|
+
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
1004
|
+
const uid = contentTypeUid;
|
|
1005
|
+
await publishCollectionTypeAction(
|
|
1006
|
+
uid,
|
|
1007
|
+
collectionTypeActions[uid].entriesToPublishIds,
|
|
1008
|
+
collectionTypeActions[uid].entriesToUnpublishIds
|
|
1009
|
+
);
|
|
905
1010
|
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
releasedAt: /* @__PURE__ */ new Date()
|
|
915
|
-
},
|
|
916
|
-
populate: {
|
|
917
|
-
actions: {
|
|
918
|
-
// @ts-expect-error is not expecting count but it is working
|
|
919
|
-
count: true
|
|
1011
|
+
});
|
|
1012
|
+
const release22 = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1013
|
+
where: {
|
|
1014
|
+
id: releaseId
|
|
1015
|
+
},
|
|
1016
|
+
data: {
|
|
1017
|
+
status: "done",
|
|
1018
|
+
releasedAt: /* @__PURE__ */ new Date()
|
|
920
1019
|
}
|
|
921
|
-
}
|
|
922
|
-
});
|
|
923
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
1020
|
+
});
|
|
924
1021
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
925
1022
|
isPublished: true,
|
|
926
|
-
release:
|
|
1023
|
+
release: release22
|
|
927
1024
|
});
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
} catch (error) {
|
|
932
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
1025
|
+
strapi2.telemetry.send("didPublishContentRelease");
|
|
1026
|
+
return { release: release22, error: null };
|
|
1027
|
+
} catch (error2) {
|
|
933
1028
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
934
1029
|
isPublished: false,
|
|
935
|
-
error
|
|
1030
|
+
error: error2
|
|
936
1031
|
});
|
|
937
|
-
|
|
938
|
-
strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
939
|
-
where: { id: releaseId },
|
|
940
|
-
data: {
|
|
1032
|
+
await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).update({
|
|
941
1033
|
status: "failed"
|
|
942
|
-
}
|
|
943
|
-
|
|
1034
|
+
}).transacting(trx).execute();
|
|
1035
|
+
return {
|
|
1036
|
+
release: null,
|
|
1037
|
+
error: error2
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
if (error) {
|
|
944
1042
|
throw error;
|
|
945
1043
|
}
|
|
1044
|
+
return release2;
|
|
946
1045
|
},
|
|
947
1046
|
async updateAction(actionId, releaseId, update) {
|
|
948
1047
|
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
@@ -1029,6 +1128,12 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
1029
1128
|
}
|
|
1030
1129
|
};
|
|
1031
1130
|
};
|
|
1131
|
+
class AlreadyOnReleaseError extends utils.errors.ApplicationError {
|
|
1132
|
+
constructor(message) {
|
|
1133
|
+
super(message);
|
|
1134
|
+
this.name = "AlreadyOnReleaseError";
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1032
1137
|
const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
1033
1138
|
async validateUniqueEntry(releaseId, releaseActionArgs) {
|
|
1034
1139
|
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
@@ -1041,7 +1146,7 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1041
1146
|
(action) => Number(action.entry.id) === Number(releaseActionArgs.entry.id) && action.contentType === releaseActionArgs.entry.contentType
|
|
1042
1147
|
);
|
|
1043
1148
|
if (isEntryInRelease) {
|
|
1044
|
-
throw new
|
|
1149
|
+
throw new AlreadyOnReleaseError(
|
|
1045
1150
|
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
|
|
1046
1151
|
);
|
|
1047
1152
|
}
|
|
@@ -1051,9 +1156,17 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1051
1156
|
if (!contentType) {
|
|
1052
1157
|
throw new utils.errors.NotFoundError(`No content type found for uid ${contentTypeUid}`);
|
|
1053
1158
|
}
|
|
1159
|
+
if (!contentType.options?.draftAndPublish) {
|
|
1160
|
+
throw new utils.errors.ValidationError(
|
|
1161
|
+
`Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`
|
|
1162
|
+
);
|
|
1163
|
+
}
|
|
1054
1164
|
},
|
|
1055
1165
|
async validatePendingReleasesLimit() {
|
|
1056
|
-
const maximumPendingReleases =
|
|
1166
|
+
const maximumPendingReleases = (
|
|
1167
|
+
// @ts-expect-error - options is not typed into features
|
|
1168
|
+
EE__default.default.features.get("cms-content-releases")?.options?.maximumReleases || 3
|
|
1169
|
+
);
|
|
1057
1170
|
const [, pendingReleasesCount] = await strapi2.db.query(RELEASE_MODEL_UID).findWithCount({
|
|
1058
1171
|
filters: {
|
|
1059
1172
|
releasedAt: {
|
|
@@ -1141,7 +1254,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1141
1254
|
const services = {
|
|
1142
1255
|
release: createReleaseService,
|
|
1143
1256
|
"release-validation": createReleaseValidationService,
|
|
1144
|
-
|
|
1257
|
+
scheduling: createSchedulingService
|
|
1145
1258
|
};
|
|
1146
1259
|
const RELEASE_SCHEMA = yup__namespace.object().shape({
|
|
1147
1260
|
name: yup__namespace.string().trim().required(),
|
|
@@ -1228,6 +1341,33 @@ const releaseController = {
|
|
|
1228
1341
|
};
|
|
1229
1342
|
ctx.body = { data };
|
|
1230
1343
|
},
|
|
1344
|
+
async mapEntriesToReleases(ctx) {
|
|
1345
|
+
const { contentTypeUid, entriesIds } = ctx.query;
|
|
1346
|
+
if (!contentTypeUid || !entriesIds) {
|
|
1347
|
+
throw new utils.errors.ValidationError("Missing required query parameters");
|
|
1348
|
+
}
|
|
1349
|
+
const releaseService = getService("release", { strapi });
|
|
1350
|
+
const releasesWithActions = await releaseService.findManyWithContentTypeEntryAttached(
|
|
1351
|
+
contentTypeUid,
|
|
1352
|
+
entriesIds
|
|
1353
|
+
);
|
|
1354
|
+
const mappedEntriesInReleases = releasesWithActions.reduce(
|
|
1355
|
+
(acc, release2) => {
|
|
1356
|
+
release2.actions.forEach((action) => {
|
|
1357
|
+
if (!acc[action.entry.id]) {
|
|
1358
|
+
acc[action.entry.id] = [{ id: release2.id, name: release2.name }];
|
|
1359
|
+
} else {
|
|
1360
|
+
acc[action.entry.id].push({ id: release2.id, name: release2.name });
|
|
1361
|
+
}
|
|
1362
|
+
});
|
|
1363
|
+
return acc;
|
|
1364
|
+
},
|
|
1365
|
+
{}
|
|
1366
|
+
);
|
|
1367
|
+
ctx.body = {
|
|
1368
|
+
data: mappedEntriesInReleases
|
|
1369
|
+
};
|
|
1370
|
+
},
|
|
1231
1371
|
async create(ctx) {
|
|
1232
1372
|
const user = ctx.state.user;
|
|
1233
1373
|
const releaseArgs = ctx.request.body;
|
|
@@ -1317,6 +1457,38 @@ const releaseActionController = {
|
|
|
1317
1457
|
data: releaseAction2
|
|
1318
1458
|
};
|
|
1319
1459
|
},
|
|
1460
|
+
async createMany(ctx) {
|
|
1461
|
+
const releaseId = ctx.params.releaseId;
|
|
1462
|
+
const releaseActionsArgs = ctx.request.body;
|
|
1463
|
+
await Promise.all(
|
|
1464
|
+
releaseActionsArgs.map((releaseActionArgs) => validateReleaseAction(releaseActionArgs))
|
|
1465
|
+
);
|
|
1466
|
+
const releaseService = getService("release", { strapi });
|
|
1467
|
+
const releaseActions = await strapi.db.transaction(async () => {
|
|
1468
|
+
const releaseActions2 = await Promise.all(
|
|
1469
|
+
releaseActionsArgs.map(async (releaseActionArgs) => {
|
|
1470
|
+
try {
|
|
1471
|
+
const action = await releaseService.createAction(releaseId, releaseActionArgs);
|
|
1472
|
+
return action;
|
|
1473
|
+
} catch (error) {
|
|
1474
|
+
if (error instanceof AlreadyOnReleaseError) {
|
|
1475
|
+
return null;
|
|
1476
|
+
}
|
|
1477
|
+
throw error;
|
|
1478
|
+
}
|
|
1479
|
+
})
|
|
1480
|
+
);
|
|
1481
|
+
return releaseActions2;
|
|
1482
|
+
});
|
|
1483
|
+
const newReleaseActions = releaseActions.filter((action) => action !== null);
|
|
1484
|
+
ctx.body = {
|
|
1485
|
+
data: newReleaseActions,
|
|
1486
|
+
meta: {
|
|
1487
|
+
entriesAlreadyInRelease: releaseActions.length - newReleaseActions.length,
|
|
1488
|
+
totalEntries: releaseActions.length
|
|
1489
|
+
}
|
|
1490
|
+
};
|
|
1491
|
+
},
|
|
1320
1492
|
async findMany(ctx) {
|
|
1321
1493
|
const releaseId = ctx.params.releaseId;
|
|
1322
1494
|
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
@@ -1340,7 +1512,7 @@ const releaseActionController = {
|
|
|
1340
1512
|
acc[action.contentType] = contentTypePermissionsManager.sanitizeOutput;
|
|
1341
1513
|
return acc;
|
|
1342
1514
|
}, {});
|
|
1343
|
-
const sanitizedResults = await utils.
|
|
1515
|
+
const sanitizedResults = await utils.mapAsync(results, async (action) => ({
|
|
1344
1516
|
...action,
|
|
1345
1517
|
entry: await contentTypeOutputSanitizers[action.contentType](action.entry)
|
|
1346
1518
|
}));
|
|
@@ -1385,6 +1557,22 @@ const controllers = { release: releaseController, "release-action": releaseActio
|
|
|
1385
1557
|
const release = {
|
|
1386
1558
|
type: "admin",
|
|
1387
1559
|
routes: [
|
|
1560
|
+
{
|
|
1561
|
+
method: "GET",
|
|
1562
|
+
path: "/mapEntriesToReleases",
|
|
1563
|
+
handler: "release.mapEntriesToReleases",
|
|
1564
|
+
config: {
|
|
1565
|
+
policies: [
|
|
1566
|
+
"admin::isAuthenticatedAdmin",
|
|
1567
|
+
{
|
|
1568
|
+
name: "admin::hasPermissions",
|
|
1569
|
+
config: {
|
|
1570
|
+
actions: ["plugin::content-releases.read"]
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
]
|
|
1574
|
+
}
|
|
1575
|
+
},
|
|
1388
1576
|
{
|
|
1389
1577
|
method: "POST",
|
|
1390
1578
|
path: "/",
|
|
@@ -1502,6 +1690,22 @@ const releaseAction = {
|
|
|
1502
1690
|
]
|
|
1503
1691
|
}
|
|
1504
1692
|
},
|
|
1693
|
+
{
|
|
1694
|
+
method: "POST",
|
|
1695
|
+
path: "/:releaseId/actions/bulk",
|
|
1696
|
+
handler: "release-action.createMany",
|
|
1697
|
+
config: {
|
|
1698
|
+
policies: [
|
|
1699
|
+
"admin::isAuthenticatedAdmin",
|
|
1700
|
+
{
|
|
1701
|
+
name: "admin::hasPermissions",
|
|
1702
|
+
config: {
|
|
1703
|
+
actions: ["plugin::content-releases.create-action"]
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
]
|
|
1707
|
+
}
|
|
1708
|
+
},
|
|
1505
1709
|
{
|
|
1506
1710
|
method: "GET",
|
|
1507
1711
|
path: "/:releaseId/actions",
|
|
@@ -1556,8 +1760,9 @@ const routes = {
|
|
|
1556
1760
|
release,
|
|
1557
1761
|
"release-action": releaseAction
|
|
1558
1762
|
};
|
|
1763
|
+
const { features } = require("@strapi/strapi/dist/utils/ee");
|
|
1559
1764
|
const getPlugin = () => {
|
|
1560
|
-
if (
|
|
1765
|
+
if (features.isEnabled("cms-content-releases")) {
|
|
1561
1766
|
return {
|
|
1562
1767
|
register,
|
|
1563
1768
|
bootstrap,
|
|
@@ -1569,6 +1774,9 @@ const getPlugin = () => {
|
|
|
1569
1774
|
};
|
|
1570
1775
|
}
|
|
1571
1776
|
return {
|
|
1777
|
+
// Always return register, it handles its own feature check
|
|
1778
|
+
register,
|
|
1779
|
+
// Always return contentTypes to avoid losing data when the feature is disabled
|
|
1572
1780
|
contentTypes
|
|
1573
1781
|
};
|
|
1574
1782
|
};
|