@strapi/content-releases 4.20.4 → 5.0.0-alpha.0
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-6ugQxqYE.mjs → App-dbdAcsz_.mjs} +296 -296
- package/dist/_chunks/App-dbdAcsz_.mjs.map +1 -0
- package/dist/_chunks/{App-P1kyM3gT.js → App-zwe_jKPv.js} +301 -301
- package/dist/_chunks/App-zwe_jKPv.js.map +1 -0
- package/dist/_chunks/{en-WuuhP6Bn.mjs → en-RdapH-9X.mjs} +1 -2
- package/dist/_chunks/en-RdapH-9X.mjs.map +1 -0
- package/dist/_chunks/{en-gcJJ5htG.js → en-faJDuv3q.js} +1 -2
- package/dist/_chunks/en-faJDuv3q.js.map +1 -0
- package/dist/_chunks/{index-_eBuegHN.mjs → index-RBaVMtyr.mjs} +79 -70
- package/dist/_chunks/index-RBaVMtyr.mjs.map +1 -0
- package/dist/_chunks/{index-2xzbhaQP.js → index-TBrVNrv9.js} +77 -68
- package/dist/_chunks/index-TBrVNrv9.js.map +1 -0
- package/dist/admin/index.js +1 -14
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +1 -14
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/src/components/CMReleasesContainer.d.ts +1 -0
- package/dist/admin/src/components/RelativeTime.d.ts +28 -0
- package/dist/admin/src/components/ReleaseActionMenu.d.ts +26 -0
- package/dist/admin/src/components/ReleaseActionOptions.d.ts +9 -0
- package/dist/admin/src/components/ReleaseModal.d.ts +16 -0
- package/dist/admin/src/constants.d.ts +58 -0
- package/dist/admin/src/index.d.ts +3 -0
- package/dist/admin/src/pages/App.d.ts +1 -0
- package/dist/admin/src/pages/PurchaseContentReleases.d.ts +2 -0
- package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +2 -0
- package/dist/admin/src/pages/ReleasesPage.d.ts +8 -0
- package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +181 -0
- package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +39 -0
- package/dist/admin/src/pluginId.d.ts +1 -0
- package/dist/admin/src/services/axios.d.ts +29 -0
- package/dist/admin/src/services/release.d.ts +369 -0
- package/dist/admin/src/store/hooks.d.ts +7 -0
- package/dist/admin/src/utils/time.d.ts +1 -0
- package/dist/server/index.js +327 -234
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +328 -234
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts +5 -0
- package/dist/server/src/bootstrap.d.ts.map +1 -0
- package/dist/server/src/constants.d.ts +12 -0
- package/dist/server/src/constants.d.ts.map +1 -0
- package/dist/server/src/content-types/index.d.ts +99 -0
- package/dist/server/src/content-types/index.d.ts.map +1 -0
- package/dist/server/src/content-types/release/index.d.ts +48 -0
- package/dist/server/src/content-types/release/index.d.ts.map +1 -0
- package/dist/server/src/content-types/release/schema.d.ts +47 -0
- package/dist/server/src/content-types/release/schema.d.ts.map +1 -0
- package/dist/server/src/content-types/release-action/index.d.ts +50 -0
- package/dist/server/src/content-types/release-action/index.d.ts.map +1 -0
- package/dist/server/src/content-types/release-action/schema.d.ts +49 -0
- package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -0
- package/dist/server/src/controllers/index.d.ts +19 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -0
- package/dist/server/src/controllers/release-action.d.ts +10 -0
- package/dist/server/src/controllers/release-action.d.ts.map +1 -0
- package/dist/server/src/controllers/release.d.ts +11 -0
- package/dist/server/src/controllers/release.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/release-action.d.ts +3 -0
- package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/release.d.ts +2 -0
- package/dist/server/src/controllers/validation/release.d.ts.map +1 -0
- package/dist/server/src/destroy.d.ts +5 -0
- package/dist/server/src/destroy.d.ts.map +1 -0
- package/dist/server/src/index.d.ts +2095 -0
- package/dist/server/src/index.d.ts.map +1 -0
- package/dist/server/src/migrations/index.d.ts +12 -0
- package/dist/server/src/migrations/index.d.ts.map +1 -0
- package/dist/server/src/register.d.ts +5 -0
- package/dist/server/src/register.d.ts.map +1 -0
- package/dist/server/src/routes/index.d.ts +35 -0
- package/dist/server/src/routes/index.d.ts.map +1 -0
- package/dist/server/src/routes/release-action.d.ts +18 -0
- package/dist/server/src/routes/release-action.d.ts.map +1 -0
- package/dist/server/src/routes/release.d.ts +18 -0
- package/dist/server/src/routes/release.d.ts.map +1 -0
- package/dist/server/src/services/index.d.ts +1826 -0
- package/dist/server/src/services/index.d.ts.map +1 -0
- package/dist/server/src/services/release.d.ts +66 -0
- package/dist/server/src/services/release.d.ts.map +1 -0
- package/dist/server/src/services/scheduling.d.ts +18 -0
- package/dist/server/src/services/scheduling.d.ts.map +1 -0
- package/dist/server/src/services/validation.d.ts +18 -0
- package/dist/server/src/services/validation.d.ts.map +1 -0
- package/dist/server/src/utils/index.d.ts +14 -0
- package/dist/server/src/utils/index.d.ts.map +1 -0
- package/dist/shared/contracts/release-actions.d.ts +131 -0
- package/dist/shared/contracts/release-actions.d.ts.map +1 -0
- package/dist/shared/contracts/releases.d.ts +166 -0
- package/dist/shared/contracts/releases.d.ts.map +1 -0
- package/dist/shared/types.d.ts +24 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/validation-schemas.d.ts +2 -0
- package/dist/shared/validation-schemas.d.ts.map +1 -0
- package/package.json +24 -30
- package/dist/_chunks/App-6ugQxqYE.mjs.map +0 -1
- package/dist/_chunks/App-P1kyM3gT.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-2xzbhaQP.js.map +0 -1
- package/dist/_chunks/index-_eBuegHN.mjs.map +0 -1
package/dist/server/index.js
CHANGED
|
@@ -3,7 +3,6 @@ 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");
|
|
7
6
|
const nodeSchedule = require("node-schedule");
|
|
8
7
|
const yup = require("yup");
|
|
9
8
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
@@ -27,7 +26,6 @@ function _interopNamespace(e) {
|
|
|
27
26
|
}
|
|
28
27
|
const isEqual__default = /* @__PURE__ */ _interopDefault(isEqual);
|
|
29
28
|
const ___default = /* @__PURE__ */ _interopDefault(_);
|
|
30
|
-
const EE__default = /* @__PURE__ */ _interopDefault(EE);
|
|
31
29
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
|
32
30
|
const RELEASE_MODEL_UID = "plugin::content-releases.release";
|
|
33
31
|
const RELEASE_ACTION_MODEL_UID = "plugin::content-releases.release-action";
|
|
@@ -84,7 +82,10 @@ const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
|
84
82
|
const getPopulatedEntry = async (contentTypeUid, entryId, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
85
83
|
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
86
84
|
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
87
|
-
const entry = await strapi2.
|
|
85
|
+
const entry = await strapi2.db.query(contentTypeUid).findOne({
|
|
86
|
+
where: { id: entryId },
|
|
87
|
+
populate
|
|
88
|
+
});
|
|
88
89
|
return entry;
|
|
89
90
|
};
|
|
90
91
|
const getEntryValidStatus = async (contentTypeUid, entry, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
@@ -101,28 +102,10 @@ const getEntryValidStatus = async (contentTypeUid, entry, { strapi: strapi2 } =
|
|
|
101
102
|
return false;
|
|
102
103
|
}
|
|
103
104
|
};
|
|
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
|
-
}
|
|
122
105
|
async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
123
106
|
const deletedContentTypes = lodash.difference(lodash.keys(oldContentTypes), lodash.keys(contentTypes2)) ?? [];
|
|
124
107
|
if (deletedContentTypes.length) {
|
|
125
|
-
await utils.
|
|
108
|
+
await utils.async.map(deletedContentTypes, async (deletedContentTypeUID) => {
|
|
126
109
|
return strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: deletedContentTypeUID }).execute();
|
|
127
110
|
});
|
|
128
111
|
}
|
|
@@ -141,7 +124,7 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
141
124
|
}
|
|
142
125
|
}
|
|
143
126
|
});
|
|
144
|
-
utils.
|
|
127
|
+
utils.async.map(releasesWithoutStatus, async (release2) => {
|
|
145
128
|
const actions = release2.actions;
|
|
146
129
|
const notValidatedActions = actions.filter((action) => action.isEntryValid === null);
|
|
147
130
|
for (const action of notValidatedActions) {
|
|
@@ -172,7 +155,7 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
172
155
|
}
|
|
173
156
|
}
|
|
174
157
|
});
|
|
175
|
-
utils.
|
|
158
|
+
utils.async.map(publishedReleases, async (release2) => {
|
|
176
159
|
return strapi.db.query(RELEASE_MODEL_UID).update({
|
|
177
160
|
where: {
|
|
178
161
|
id: release2.id
|
|
@@ -185,11 +168,9 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
185
168
|
}
|
|
186
169
|
async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
187
170
|
if (oldContentTypes !== void 0 && contentTypes2 !== void 0) {
|
|
188
|
-
const contentTypesWithDraftAndPublish = Object.keys(oldContentTypes)
|
|
189
|
-
(uid) => oldContentTypes[uid]?.options?.draftAndPublish
|
|
190
|
-
);
|
|
171
|
+
const contentTypesWithDraftAndPublish = Object.keys(oldContentTypes);
|
|
191
172
|
const releasesAffected = /* @__PURE__ */ new Set();
|
|
192
|
-
utils.
|
|
173
|
+
utils.async.map(contentTypesWithDraftAndPublish, async (contentTypeUID) => {
|
|
193
174
|
const oldContentType = oldContentTypes[contentTypeUID];
|
|
194
175
|
const contentType = contentTypes2[contentTypeUID];
|
|
195
176
|
if (!isEqual__default.default(oldContentType?.attributes, contentType?.attributes)) {
|
|
@@ -202,8 +183,8 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
202
183
|
release: true
|
|
203
184
|
}
|
|
204
185
|
});
|
|
205
|
-
await utils.
|
|
206
|
-
if (action.entry) {
|
|
186
|
+
await utils.async.map(actions, async (action) => {
|
|
187
|
+
if (action.entry && action.release) {
|
|
207
188
|
const populatedEntry = await getPopulatedEntry(contentTypeUID, action.entry.id, {
|
|
208
189
|
strapi
|
|
209
190
|
});
|
|
@@ -225,26 +206,67 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
225
206
|
});
|
|
226
207
|
}
|
|
227
208
|
}).then(() => {
|
|
228
|
-
utils.
|
|
209
|
+
utils.async.map(releasesAffected, async (releaseId) => {
|
|
229
210
|
return getService("release", { strapi }).updateReleaseStatus(releaseId);
|
|
230
211
|
});
|
|
231
212
|
});
|
|
232
213
|
}
|
|
233
214
|
}
|
|
234
|
-
|
|
215
|
+
async function disableContentTypeLocalized({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
216
|
+
if (!oldContentTypes) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
for (const uid in contentTypes2) {
|
|
220
|
+
if (!oldContentTypes[uid]) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
const oldContentType = oldContentTypes[uid];
|
|
224
|
+
const contentType = contentTypes2[uid];
|
|
225
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
226
|
+
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
227
|
+
if (isLocalizedContentType(oldContentType) && !isLocalizedContentType(contentType)) {
|
|
228
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
229
|
+
locale: null
|
|
230
|
+
}).where({ contentType: uid }).execute();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async function enableContentTypeLocalized({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
235
|
+
if (!oldContentTypes) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
for (const uid in contentTypes2) {
|
|
239
|
+
if (!oldContentTypes[uid]) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
const oldContentType = oldContentTypes[uid];
|
|
243
|
+
const contentType = contentTypes2[uid];
|
|
244
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
245
|
+
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
246
|
+
const { getDefaultLocale } = i18nPlugin.service("locales");
|
|
247
|
+
if (!isLocalizedContentType(oldContentType) && isLocalizedContentType(contentType)) {
|
|
248
|
+
const defaultLocale = await getDefaultLocale();
|
|
249
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
250
|
+
locale: defaultLocale
|
|
251
|
+
}).where({ contentType: uid }).execute();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
235
255
|
const register = async ({ strapi: strapi2 }) => {
|
|
236
|
-
if (features
|
|
256
|
+
if (strapi2.ee.features.isEnabled("cms-content-releases")) {
|
|
237
257
|
await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
|
|
238
|
-
strapi2.hook("strapi::content-types.beforeSync").register(
|
|
239
|
-
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
258
|
+
strapi2.hook("strapi::content-types.beforeSync").register(disableContentTypeLocalized);
|
|
259
|
+
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(enableContentTypeLocalized).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
260
|
+
}
|
|
261
|
+
if (strapi2.plugin("graphql")) {
|
|
262
|
+
const graphqlExtensionService = strapi2.plugin("graphql").service("extension");
|
|
263
|
+
graphqlExtensionService.shadowCRUD(RELEASE_MODEL_UID).disable();
|
|
264
|
+
graphqlExtensionService.shadowCRUD(RELEASE_ACTION_MODEL_UID).disable();
|
|
240
265
|
}
|
|
241
266
|
};
|
|
242
|
-
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
243
267
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
244
|
-
if (features
|
|
245
|
-
const contentTypesWithDraftAndPublish = Object.keys(strapi2.contentTypes)
|
|
246
|
-
(uid) => strapi2.contentTypes[uid]?.options?.draftAndPublish
|
|
247
|
-
);
|
|
268
|
+
if (strapi2.ee.features.isEnabled("cms-content-releases")) {
|
|
269
|
+
const contentTypesWithDraftAndPublish = Object.keys(strapi2.contentTypes);
|
|
248
270
|
strapi2.db.lifecycles.subscribe({
|
|
249
271
|
models: contentTypesWithDraftAndPublish,
|
|
250
272
|
async afterDelete(event) {
|
|
@@ -280,7 +302,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
280
302
|
*/
|
|
281
303
|
async beforeDeleteMany(event) {
|
|
282
304
|
const { model, params } = event;
|
|
283
|
-
if (model.kind === "collectionType"
|
|
305
|
+
if (model.kind === "collectionType") {
|
|
284
306
|
const { where } = params;
|
|
285
307
|
const entriesToDelete = await strapi2.db.query(model.uid).findMany({ select: ["id"], where });
|
|
286
308
|
event.state.entriesToDelete = entriesToDelete;
|
|
@@ -362,27 +384,23 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
362
384
|
}
|
|
363
385
|
}
|
|
364
386
|
});
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
});
|
|
375
|
-
}
|
|
387
|
+
getService("scheduling", { strapi: strapi2 }).syncFromDatabase().catch((err) => {
|
|
388
|
+
strapi2.log.error(
|
|
389
|
+
"Error while syncing scheduled jobs from the database in the content-releases plugin. This could lead to errors in the releases scheduling."
|
|
390
|
+
);
|
|
391
|
+
throw err;
|
|
392
|
+
});
|
|
393
|
+
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
|
394
|
+
strapi2.webhookStore.addAllowedEvent(key, value);
|
|
395
|
+
});
|
|
376
396
|
}
|
|
377
397
|
};
|
|
378
398
|
const destroy = async ({ strapi: strapi2 }) => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
job.cancel();
|
|
385
|
-
}
|
|
399
|
+
const scheduledJobs = getService("scheduling", {
|
|
400
|
+
strapi: strapi2
|
|
401
|
+
}).getAll();
|
|
402
|
+
for (const [, job] of scheduledJobs) {
|
|
403
|
+
job.cancel();
|
|
386
404
|
}
|
|
387
405
|
};
|
|
388
406
|
const schema$1 = {
|
|
@@ -507,6 +525,94 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
507
525
|
release: release2
|
|
508
526
|
});
|
|
509
527
|
};
|
|
528
|
+
const publishSingleTypeAction = async (uid, actionType, entryId) => {
|
|
529
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
530
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
531
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
532
|
+
const entry = await strapi2.entityService.findOne(uid, entryId, { populate });
|
|
533
|
+
try {
|
|
534
|
+
if (actionType === "publish") {
|
|
535
|
+
await entityManagerService.publish(entry, uid);
|
|
536
|
+
} else {
|
|
537
|
+
await entityManagerService.unpublish(entry, uid);
|
|
538
|
+
}
|
|
539
|
+
} catch (error) {
|
|
540
|
+
if (error instanceof utils.errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
541
|
+
;
|
|
542
|
+
else {
|
|
543
|
+
throw error;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
const publishCollectionTypeAction = async (uid, entriesToPublishIds, entriestoUnpublishIds) => {
|
|
548
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
549
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
550
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
551
|
+
const entriesToPublish = await strapi2.entityService.findMany(uid, {
|
|
552
|
+
filters: {
|
|
553
|
+
id: {
|
|
554
|
+
$in: entriesToPublishIds
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
populate
|
|
558
|
+
});
|
|
559
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(uid, {
|
|
560
|
+
filters: {
|
|
561
|
+
id: {
|
|
562
|
+
$in: entriestoUnpublishIds
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
populate
|
|
566
|
+
});
|
|
567
|
+
if (entriesToPublish.length > 0) {
|
|
568
|
+
await entityManagerService.publishMany(entriesToPublish, uid);
|
|
569
|
+
}
|
|
570
|
+
if (entriesToUnpublish.length > 0) {
|
|
571
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, uid);
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
const getFormattedActions = async (releaseId) => {
|
|
575
|
+
const actions = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findMany({
|
|
576
|
+
where: {
|
|
577
|
+
release: {
|
|
578
|
+
id: releaseId
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
populate: {
|
|
582
|
+
entry: {
|
|
583
|
+
fields: ["id"]
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
if (actions.length === 0) {
|
|
588
|
+
throw new utils.errors.ValidationError("No entries to publish");
|
|
589
|
+
}
|
|
590
|
+
const collectionTypeActions = {};
|
|
591
|
+
const singleTypeActions = [];
|
|
592
|
+
for (const action of actions) {
|
|
593
|
+
const contentTypeUid = action.contentType;
|
|
594
|
+
if (strapi2.contentTypes[contentTypeUid].kind === "collectionType") {
|
|
595
|
+
if (!collectionTypeActions[contentTypeUid]) {
|
|
596
|
+
collectionTypeActions[contentTypeUid] = {
|
|
597
|
+
entriesToPublishIds: [],
|
|
598
|
+
entriesToUnpublishIds: []
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
if (action.type === "publish") {
|
|
602
|
+
collectionTypeActions[contentTypeUid].entriesToPublishIds.push(action.entry.id);
|
|
603
|
+
} else {
|
|
604
|
+
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
605
|
+
}
|
|
606
|
+
} else {
|
|
607
|
+
singleTypeActions.push({
|
|
608
|
+
uid: contentTypeUid,
|
|
609
|
+
action: action.type,
|
|
610
|
+
id: action.entry.id
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return { collectionTypeActions, singleTypeActions };
|
|
615
|
+
};
|
|
510
616
|
return {
|
|
511
617
|
async create(releaseData, { user }) {
|
|
512
618
|
const releaseWithCreatorFields = await utils.setCreatorFields({ user })(releaseData);
|
|
@@ -520,13 +626,13 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
520
626
|
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name),
|
|
521
627
|
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
522
628
|
]);
|
|
523
|
-
const release2 = await strapi2.
|
|
629
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).create({
|
|
524
630
|
data: {
|
|
525
631
|
...releaseWithCreatorFields,
|
|
526
632
|
status: "empty"
|
|
527
633
|
}
|
|
528
634
|
});
|
|
529
|
-
if (
|
|
635
|
+
if (releaseWithCreatorFields.scheduledAt) {
|
|
530
636
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
531
637
|
await schedulingService.set(release2.id, release2.scheduledAt);
|
|
532
638
|
}
|
|
@@ -534,17 +640,19 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
534
640
|
return release2;
|
|
535
641
|
},
|
|
536
642
|
async findOne(id, query = {}) {
|
|
537
|
-
const
|
|
538
|
-
|
|
643
|
+
const dbQuery = utils.convertQueryParams.transformParamsToQuery(RELEASE_MODEL_UID, query);
|
|
644
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
645
|
+
...dbQuery,
|
|
646
|
+
where: { id }
|
|
539
647
|
});
|
|
540
648
|
return release2;
|
|
541
649
|
},
|
|
542
650
|
findPage(query) {
|
|
543
|
-
|
|
544
|
-
|
|
651
|
+
const dbQuery = utils.convertQueryParams.transformParamsToQuery(RELEASE_MODEL_UID, query ?? {});
|
|
652
|
+
return strapi2.db.query(RELEASE_MODEL_UID).findPage({
|
|
653
|
+
...dbQuery,
|
|
545
654
|
populate: {
|
|
546
655
|
actions: {
|
|
547
|
-
// @ts-expect-error Ignore missing properties
|
|
548
656
|
count: true
|
|
549
657
|
}
|
|
550
658
|
}
|
|
@@ -636,28 +744,22 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
636
744
|
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name, id),
|
|
637
745
|
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
638
746
|
]);
|
|
639
|
-
const release2 = await strapi2.
|
|
747
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id } });
|
|
640
748
|
if (!release2) {
|
|
641
749
|
throw new utils.errors.NotFoundError(`No release found for id ${id}`);
|
|
642
750
|
}
|
|
643
751
|
if (release2.releasedAt) {
|
|
644
752
|
throw new utils.errors.ValidationError("Release already published");
|
|
645
753
|
}
|
|
646
|
-
const updatedRelease = await strapi2.
|
|
647
|
-
|
|
648
|
-
* The type returned from the entity service: Partial<Input<"plugin::content-releases.release">>
|
|
649
|
-
* is not compatible with the type we are passing here: UpdateRelease.Request['body']
|
|
650
|
-
*/
|
|
651
|
-
// @ts-expect-error see above
|
|
754
|
+
const updatedRelease = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
755
|
+
where: { id },
|
|
652
756
|
data: releaseWithCreatorFields
|
|
653
757
|
});
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
schedulingService.cancel(id);
|
|
660
|
-
}
|
|
758
|
+
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
759
|
+
if (releaseData.scheduledAt) {
|
|
760
|
+
await schedulingService.set(id, releaseData.scheduledAt);
|
|
761
|
+
} else if (release2.scheduledAt) {
|
|
762
|
+
schedulingService.cancel(id);
|
|
661
763
|
}
|
|
662
764
|
this.updateReleaseStatus(id);
|
|
663
765
|
strapi2.telemetry.send("didUpdateContentRelease");
|
|
@@ -671,7 +773,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
671
773
|
validateEntryContentType(action.entry.contentType),
|
|
672
774
|
validateUniqueEntry(releaseId, action)
|
|
673
775
|
]);
|
|
674
|
-
const release2 = await strapi2.
|
|
776
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id: releaseId } });
|
|
675
777
|
if (!release2) {
|
|
676
778
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
677
779
|
}
|
|
@@ -681,7 +783,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
681
783
|
const { entry, type } = action;
|
|
682
784
|
const populatedEntry = await getPopulatedEntry(entry.contentType, entry.id, { strapi: strapi2 });
|
|
683
785
|
const isEntryValid = await getEntryValidStatus(entry.contentType, populatedEntry, { strapi: strapi2 });
|
|
684
|
-
const releaseAction2 = await strapi2.
|
|
786
|
+
const releaseAction2 = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).create({
|
|
685
787
|
data: {
|
|
686
788
|
type,
|
|
687
789
|
contentType: entry.contentType,
|
|
@@ -694,32 +796,41 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
694
796
|
},
|
|
695
797
|
release: releaseId
|
|
696
798
|
},
|
|
697
|
-
populate: { release: {
|
|
799
|
+
populate: { release: { select: ["id"] }, entry: { select: ["id"] } }
|
|
698
800
|
});
|
|
699
801
|
this.updateReleaseStatus(releaseId);
|
|
700
802
|
return releaseAction2;
|
|
701
803
|
},
|
|
702
804
|
async findActions(releaseId, query) {
|
|
703
|
-
const release2 = await strapi2.
|
|
704
|
-
|
|
805
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
806
|
+
where: { id: releaseId },
|
|
807
|
+
select: ["id"]
|
|
705
808
|
});
|
|
706
809
|
if (!release2) {
|
|
707
810
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
708
811
|
}
|
|
709
|
-
|
|
710
|
-
|
|
812
|
+
const dbQuery = utils.convertQueryParams.transformParamsToQuery(
|
|
813
|
+
RELEASE_ACTION_MODEL_UID,
|
|
814
|
+
query ?? {}
|
|
815
|
+
);
|
|
816
|
+
return strapi2.db.query(RELEASE_ACTION_MODEL_UID).findPage({
|
|
817
|
+
...dbQuery,
|
|
711
818
|
populate: {
|
|
712
819
|
entry: {
|
|
713
820
|
populate: "*"
|
|
714
821
|
}
|
|
715
822
|
},
|
|
716
|
-
|
|
823
|
+
where: {
|
|
717
824
|
release: releaseId
|
|
718
825
|
}
|
|
719
826
|
});
|
|
720
827
|
},
|
|
721
828
|
async countActions(query) {
|
|
722
|
-
|
|
829
|
+
const dbQuery = utils.convertQueryParams.transformParamsToQuery(
|
|
830
|
+
RELEASE_ACTION_MODEL_UID,
|
|
831
|
+
query ?? {}
|
|
832
|
+
);
|
|
833
|
+
return strapi2.db.query(RELEASE_ACTION_MODEL_UID).count(dbQuery);
|
|
723
834
|
},
|
|
724
835
|
async groupActions(actions, groupBy) {
|
|
725
836
|
const contentTypeUids = actions.reduce((acc, action) => {
|
|
@@ -800,10 +911,11 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
800
911
|
return componentsMap;
|
|
801
912
|
},
|
|
802
913
|
async delete(releaseId) {
|
|
803
|
-
const release2 = await strapi2.
|
|
914
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
915
|
+
where: { id: releaseId },
|
|
804
916
|
populate: {
|
|
805
917
|
actions: {
|
|
806
|
-
|
|
918
|
+
select: ["id"]
|
|
807
919
|
}
|
|
808
920
|
}
|
|
809
921
|
});
|
|
@@ -821,9 +933,13 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
821
933
|
}
|
|
822
934
|
}
|
|
823
935
|
});
|
|
824
|
-
await strapi2.
|
|
936
|
+
await strapi2.db.query(RELEASE_MODEL_UID).delete({
|
|
937
|
+
where: {
|
|
938
|
+
id: releaseId
|
|
939
|
+
}
|
|
940
|
+
});
|
|
825
941
|
});
|
|
826
|
-
if (
|
|
942
|
+
if (release2.scheduledAt) {
|
|
827
943
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
828
944
|
await schedulingService.cancel(release2.id);
|
|
829
945
|
}
|
|
@@ -831,145 +947,71 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
831
947
|
return release2;
|
|
832
948
|
},
|
|
833
949
|
async publish(releaseId) {
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
actions: {
|
|
841
|
-
populate: {
|
|
842
|
-
entry: {
|
|
843
|
-
fields: ["id"]
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
);
|
|
850
|
-
if (!releaseWithPopulatedActionEntries) {
|
|
950
|
+
const {
|
|
951
|
+
release: release2,
|
|
952
|
+
error
|
|
953
|
+
} = await strapi2.db.transaction(async ({ trx }) => {
|
|
954
|
+
const lockedRelease = await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).select(["id", "name", "releasedAt", "status"]).first().transacting(trx).forUpdate().execute();
|
|
955
|
+
if (!lockedRelease) {
|
|
851
956
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
852
957
|
}
|
|
853
|
-
if (
|
|
958
|
+
if (lockedRelease.releasedAt) {
|
|
854
959
|
throw new utils.errors.ValidationError("Release already published");
|
|
855
960
|
}
|
|
856
|
-
if (
|
|
857
|
-
throw new utils.errors.ValidationError("
|
|
961
|
+
if (lockedRelease.status === "failed") {
|
|
962
|
+
throw new utils.errors.ValidationError("Release failed to publish");
|
|
858
963
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
entriesToUnpublishIds: []
|
|
868
|
-
};
|
|
869
|
-
}
|
|
870
|
-
if (action.type === "publish") {
|
|
871
|
-
collectionTypeActions[contentTypeUid].entriestoPublishIds.push(action.entry.id);
|
|
872
|
-
} else {
|
|
873
|
-
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
874
|
-
}
|
|
875
|
-
} else {
|
|
876
|
-
singleTypeActions.push({
|
|
877
|
-
uid: contentTypeUid,
|
|
878
|
-
action: action.type,
|
|
879
|
-
id: action.entry.id
|
|
880
|
-
});
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
884
|
-
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
885
|
-
await strapi2.db.transaction(async () => {
|
|
886
|
-
for (const { uid, action, id } of singleTypeActions) {
|
|
887
|
-
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
888
|
-
const entry = await strapi2.entityService.findOne(uid, id, { populate });
|
|
889
|
-
try {
|
|
890
|
-
if (action === "publish") {
|
|
891
|
-
await entityManagerService.publish(entry, uid);
|
|
892
|
-
} else {
|
|
893
|
-
await entityManagerService.unpublish(entry, uid);
|
|
894
|
-
}
|
|
895
|
-
} catch (error) {
|
|
896
|
-
if (error instanceof utils.errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft")) {
|
|
897
|
-
} else {
|
|
898
|
-
throw error;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
903
|
-
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
904
|
-
const { entriestoPublishIds, entriesToUnpublishIds } = collectionTypeActions[contentTypeUid];
|
|
905
|
-
const entriesToPublish = await strapi2.entityService.findMany(
|
|
906
|
-
contentTypeUid,
|
|
907
|
-
{
|
|
908
|
-
filters: {
|
|
909
|
-
id: {
|
|
910
|
-
$in: entriestoPublishIds
|
|
911
|
-
}
|
|
912
|
-
},
|
|
913
|
-
populate
|
|
914
|
-
}
|
|
915
|
-
);
|
|
916
|
-
const entriesToUnpublish = await strapi2.entityService.findMany(
|
|
917
|
-
contentTypeUid,
|
|
918
|
-
{
|
|
919
|
-
filters: {
|
|
920
|
-
id: {
|
|
921
|
-
$in: entriesToUnpublishIds
|
|
922
|
-
}
|
|
923
|
-
},
|
|
924
|
-
populate
|
|
925
|
-
}
|
|
926
|
-
);
|
|
927
|
-
if (entriesToPublish.length > 0) {
|
|
928
|
-
await entityManagerService.publishMany(entriesToPublish, contentTypeUid);
|
|
964
|
+
try {
|
|
965
|
+
strapi2.log.info(`[Content Releases] Starting to publish release ${lockedRelease.name}`);
|
|
966
|
+
const { collectionTypeActions, singleTypeActions } = await getFormattedActions(
|
|
967
|
+
releaseId
|
|
968
|
+
);
|
|
969
|
+
await strapi2.db.transaction(async () => {
|
|
970
|
+
for (const { uid, action, id } of singleTypeActions) {
|
|
971
|
+
await publishSingleTypeAction(uid, action, id);
|
|
929
972
|
}
|
|
930
|
-
|
|
931
|
-
|
|
973
|
+
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
974
|
+
const uid = contentTypeUid;
|
|
975
|
+
await publishCollectionTypeAction(
|
|
976
|
+
uid,
|
|
977
|
+
collectionTypeActions[uid].entriesToPublishIds,
|
|
978
|
+
collectionTypeActions[uid].entriesToUnpublishIds
|
|
979
|
+
);
|
|
932
980
|
}
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
releasedAt: /* @__PURE__ */ new Date()
|
|
942
|
-
},
|
|
943
|
-
populate: {
|
|
944
|
-
actions: {
|
|
945
|
-
// @ts-expect-error is not expecting count but it is working
|
|
946
|
-
count: true
|
|
981
|
+
});
|
|
982
|
+
const release22 = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
983
|
+
where: {
|
|
984
|
+
id: releaseId
|
|
985
|
+
},
|
|
986
|
+
data: {
|
|
987
|
+
status: "done",
|
|
988
|
+
releasedAt: /* @__PURE__ */ new Date()
|
|
947
989
|
}
|
|
948
|
-
}
|
|
949
|
-
});
|
|
950
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
990
|
+
});
|
|
951
991
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
952
992
|
isPublished: true,
|
|
953
|
-
release:
|
|
993
|
+
release: release22
|
|
954
994
|
});
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
} catch (error) {
|
|
959
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
995
|
+
strapi2.telemetry.send("didPublishContentRelease");
|
|
996
|
+
return { release: release22, error: null };
|
|
997
|
+
} catch (error2) {
|
|
960
998
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
961
999
|
isPublished: false,
|
|
962
|
-
error
|
|
1000
|
+
error: error2
|
|
963
1001
|
});
|
|
964
|
-
|
|
965
|
-
strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
966
|
-
where: { id: releaseId },
|
|
967
|
-
data: {
|
|
1002
|
+
await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).update({
|
|
968
1003
|
status: "failed"
|
|
969
|
-
}
|
|
970
|
-
|
|
1004
|
+
}).transacting(trx).execute();
|
|
1005
|
+
return {
|
|
1006
|
+
release: null,
|
|
1007
|
+
error: error2
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
1011
|
+
if (error instanceof Error) {
|
|
971
1012
|
throw error;
|
|
972
1013
|
}
|
|
1014
|
+
return release2;
|
|
973
1015
|
},
|
|
974
1016
|
async updateAction(actionId, releaseId, update) {
|
|
975
1017
|
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
@@ -1056,10 +1098,19 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
1056
1098
|
}
|
|
1057
1099
|
};
|
|
1058
1100
|
};
|
|
1101
|
+
class AlreadyOnReleaseError extends utils.errors.ApplicationError {
|
|
1102
|
+
constructor(message) {
|
|
1103
|
+
super(message);
|
|
1104
|
+
this.name = "AlreadyOnReleaseError";
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1059
1107
|
const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
1060
1108
|
async validateUniqueEntry(releaseId, releaseActionArgs) {
|
|
1061
|
-
const release2 = await strapi2.
|
|
1062
|
-
|
|
1109
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
1110
|
+
where: {
|
|
1111
|
+
id: releaseId
|
|
1112
|
+
},
|
|
1113
|
+
populate: { actions: { populate: { entry: { select: ["id"] } } } }
|
|
1063
1114
|
});
|
|
1064
1115
|
if (!release2) {
|
|
1065
1116
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
@@ -1068,7 +1119,7 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1068
1119
|
(action) => Number(action.entry.id) === Number(releaseActionArgs.entry.id) && action.contentType === releaseActionArgs.entry.contentType
|
|
1069
1120
|
);
|
|
1070
1121
|
if (isEntryInRelease) {
|
|
1071
|
-
throw new
|
|
1122
|
+
throw new AlreadyOnReleaseError(
|
|
1072
1123
|
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
|
|
1073
1124
|
);
|
|
1074
1125
|
}
|
|
@@ -1078,17 +1129,9 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1078
1129
|
if (!contentType) {
|
|
1079
1130
|
throw new utils.errors.NotFoundError(`No content type found for uid ${contentTypeUid}`);
|
|
1080
1131
|
}
|
|
1081
|
-
if (!contentType.options?.draftAndPublish) {
|
|
1082
|
-
throw new utils.errors.ValidationError(
|
|
1083
|
-
`Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`
|
|
1084
|
-
);
|
|
1085
|
-
}
|
|
1086
1132
|
},
|
|
1087
1133
|
async validatePendingReleasesLimit() {
|
|
1088
|
-
const maximumPendingReleases = (
|
|
1089
|
-
// @ts-expect-error - options is not typed into features
|
|
1090
|
-
EE__default.default.features.get("cms-content-releases")?.options?.maximumReleases || 3
|
|
1091
|
-
);
|
|
1134
|
+
const maximumPendingReleases = strapi2.ee.features.get("cms-content-releases")?.options?.maximumReleases || 3;
|
|
1092
1135
|
const [, pendingReleasesCount] = await strapi2.db.query(RELEASE_MODEL_UID).findWithCount({
|
|
1093
1136
|
filters: {
|
|
1094
1137
|
releasedAt: {
|
|
@@ -1101,8 +1144,8 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1101
1144
|
}
|
|
1102
1145
|
},
|
|
1103
1146
|
async validateUniqueNameForPendingRelease(name, id) {
|
|
1104
|
-
const pendingReleases = await strapi2.
|
|
1105
|
-
|
|
1147
|
+
const pendingReleases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
1148
|
+
where: {
|
|
1106
1149
|
releasedAt: {
|
|
1107
1150
|
$null: true
|
|
1108
1151
|
},
|
|
@@ -1176,7 +1219,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1176
1219
|
const services = {
|
|
1177
1220
|
release: createReleaseService,
|
|
1178
1221
|
"release-validation": createReleaseValidationService,
|
|
1179
|
-
|
|
1222
|
+
scheduling: createSchedulingService
|
|
1180
1223
|
};
|
|
1181
1224
|
const RELEASE_SCHEMA = yup__namespace.object().shape({
|
|
1182
1225
|
name: yup__namespace.string().trim().required(),
|
|
@@ -1229,7 +1272,7 @@ const releaseController = {
|
|
|
1229
1272
|
}
|
|
1230
1273
|
};
|
|
1231
1274
|
});
|
|
1232
|
-
const pendingReleasesCount = await strapi.query(RELEASE_MODEL_UID).count({
|
|
1275
|
+
const pendingReleasesCount = await strapi.db.query(RELEASE_MODEL_UID).count({
|
|
1233
1276
|
where: {
|
|
1234
1277
|
releasedAt: null
|
|
1235
1278
|
}
|
|
@@ -1352,6 +1395,38 @@ const releaseActionController = {
|
|
|
1352
1395
|
data: releaseAction2
|
|
1353
1396
|
};
|
|
1354
1397
|
},
|
|
1398
|
+
async createMany(ctx) {
|
|
1399
|
+
const releaseId = ctx.params.releaseId;
|
|
1400
|
+
const releaseActionsArgs = ctx.request.body;
|
|
1401
|
+
await Promise.all(
|
|
1402
|
+
releaseActionsArgs.map((releaseActionArgs) => validateReleaseAction(releaseActionArgs))
|
|
1403
|
+
);
|
|
1404
|
+
const releaseService = getService("release", { strapi });
|
|
1405
|
+
const releaseActions = await strapi.db.transaction(async () => {
|
|
1406
|
+
const releaseActions2 = await Promise.all(
|
|
1407
|
+
releaseActionsArgs.map(async (releaseActionArgs) => {
|
|
1408
|
+
try {
|
|
1409
|
+
const action = await releaseService.createAction(releaseId, releaseActionArgs);
|
|
1410
|
+
return action;
|
|
1411
|
+
} catch (error) {
|
|
1412
|
+
if (error instanceof AlreadyOnReleaseError) {
|
|
1413
|
+
return null;
|
|
1414
|
+
}
|
|
1415
|
+
throw error;
|
|
1416
|
+
}
|
|
1417
|
+
})
|
|
1418
|
+
);
|
|
1419
|
+
return releaseActions2;
|
|
1420
|
+
});
|
|
1421
|
+
const newReleaseActions = releaseActions.filter((action) => action !== null);
|
|
1422
|
+
ctx.body = {
|
|
1423
|
+
data: newReleaseActions,
|
|
1424
|
+
meta: {
|
|
1425
|
+
entriesAlreadyInRelease: releaseActions.length - newReleaseActions.length,
|
|
1426
|
+
totalEntries: releaseActions.length
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
},
|
|
1355
1430
|
async findMany(ctx) {
|
|
1356
1431
|
const releaseId = ctx.params.releaseId;
|
|
1357
1432
|
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
@@ -1375,7 +1450,7 @@ const releaseActionController = {
|
|
|
1375
1450
|
acc[action.contentType] = contentTypePermissionsManager.sanitizeOutput;
|
|
1376
1451
|
return acc;
|
|
1377
1452
|
}, {});
|
|
1378
|
-
const sanitizedResults = await utils.
|
|
1453
|
+
const sanitizedResults = await utils.async.map(results, async (action) => ({
|
|
1379
1454
|
...action,
|
|
1380
1455
|
entry: await contentTypeOutputSanitizers[action.contentType](action.entry)
|
|
1381
1456
|
}));
|
|
@@ -1537,6 +1612,22 @@ const releaseAction = {
|
|
|
1537
1612
|
]
|
|
1538
1613
|
}
|
|
1539
1614
|
},
|
|
1615
|
+
{
|
|
1616
|
+
method: "POST",
|
|
1617
|
+
path: "/:releaseId/actions/bulk",
|
|
1618
|
+
handler: "release-action.createMany",
|
|
1619
|
+
config: {
|
|
1620
|
+
policies: [
|
|
1621
|
+
"admin::isAuthenticatedAdmin",
|
|
1622
|
+
{
|
|
1623
|
+
name: "admin::hasPermissions",
|
|
1624
|
+
config: {
|
|
1625
|
+
actions: ["plugin::content-releases.create-action"]
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
]
|
|
1629
|
+
}
|
|
1630
|
+
},
|
|
1540
1631
|
{
|
|
1541
1632
|
method: "GET",
|
|
1542
1633
|
path: "/:releaseId/actions",
|
|
@@ -1591,9 +1682,8 @@ const routes = {
|
|
|
1591
1682
|
release,
|
|
1592
1683
|
"release-action": releaseAction
|
|
1593
1684
|
};
|
|
1594
|
-
const { features } = require("@strapi/strapi/dist/utils/ee");
|
|
1595
1685
|
const getPlugin = () => {
|
|
1596
|
-
if (features.isEnabled("cms-content-releases")) {
|
|
1686
|
+
if (strapi.ee.features.isEnabled("cms-content-releases")) {
|
|
1597
1687
|
return {
|
|
1598
1688
|
register,
|
|
1599
1689
|
bootstrap,
|
|
@@ -1605,6 +1695,9 @@ const getPlugin = () => {
|
|
|
1605
1695
|
};
|
|
1606
1696
|
}
|
|
1607
1697
|
return {
|
|
1698
|
+
// Always return register, it handles its own feature check
|
|
1699
|
+
register,
|
|
1700
|
+
// Always return contentTypes to avoid losing data when the feature is disabled
|
|
1608
1701
|
contentTypes
|
|
1609
1702
|
};
|
|
1610
1703
|
};
|