@strapi/content-releases 4.20.4 → 4.21.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-HVXzE3i3.mjs} +105 -113
- package/dist/_chunks/App-HVXzE3i3.mjs.map +1 -0
- package/dist/_chunks/{App-P1kyM3gT.js → App-l62gIUTX.js} +104 -112
- package/dist/_chunks/App-l62gIUTX.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-2xzbhaQP.js → index-ML_b3php.js} +9 -9
- package/dist/_chunks/index-ML_b3php.js.map +1 -0
- package/dist/_chunks/{index-_eBuegHN.mjs → index-Ys87ROOe.mjs} +9 -9
- package/dist/_chunks/index-Ys87ROOe.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +264 -154
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +264 -154
- package/dist/server/index.mjs.map +1 -1
- package/package.json +11 -11
- 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
|
@@ -203,7 +203,7 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
203
203
|
}
|
|
204
204
|
});
|
|
205
205
|
await utils.mapAsync(actions, async (action) => {
|
|
206
|
-
if (action.entry) {
|
|
206
|
+
if (action.entry && action.release) {
|
|
207
207
|
const populatedEntry = await getPopulatedEntry(contentTypeUID, action.entry.id, {
|
|
208
208
|
strapi
|
|
209
209
|
});
|
|
@@ -231,12 +231,57 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
|
+
async function disableContentTypeLocalized({ 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
|
+
if (isLocalizedContentType(oldContentType) && !isLocalizedContentType(contentType)) {
|
|
247
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
248
|
+
locale: null
|
|
249
|
+
}).where({ contentType: uid }).execute();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
async function enableContentTypeLocalized({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
254
|
+
if (!oldContentTypes) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
for (const uid in contentTypes2) {
|
|
258
|
+
if (!oldContentTypes[uid]) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
const oldContentType = oldContentTypes[uid];
|
|
262
|
+
const contentType = contentTypes2[uid];
|
|
263
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
264
|
+
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
265
|
+
const { getDefaultLocale } = i18nPlugin.service("locales");
|
|
266
|
+
if (!isLocalizedContentType(oldContentType) && isLocalizedContentType(contentType)) {
|
|
267
|
+
const defaultLocale = await getDefaultLocale();
|
|
268
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
269
|
+
locale: defaultLocale
|
|
270
|
+
}).where({ contentType: uid }).execute();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
234
274
|
const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
|
|
235
275
|
const register = async ({ strapi: strapi2 }) => {
|
|
236
276
|
if (features$2.isEnabled("cms-content-releases")) {
|
|
237
277
|
await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
|
|
238
|
-
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish);
|
|
239
|
-
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
278
|
+
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish).register(disableContentTypeLocalized);
|
|
279
|
+
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(enableContentTypeLocalized).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
280
|
+
}
|
|
281
|
+
if (strapi2.plugin("graphql")) {
|
|
282
|
+
const graphqlExtensionService = strapi2.plugin("graphql").service("extension");
|
|
283
|
+
graphqlExtensionService.shadowCRUD(RELEASE_MODEL_UID).disable();
|
|
284
|
+
graphqlExtensionService.shadowCRUD(RELEASE_ACTION_MODEL_UID).disable();
|
|
240
285
|
}
|
|
241
286
|
};
|
|
242
287
|
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
@@ -362,27 +407,23 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
362
407
|
}
|
|
363
408
|
}
|
|
364
409
|
});
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
});
|
|
375
|
-
}
|
|
410
|
+
getService("scheduling", { strapi: strapi2 }).syncFromDatabase().catch((err) => {
|
|
411
|
+
strapi2.log.error(
|
|
412
|
+
"Error while syncing scheduled jobs from the database in the content-releases plugin. This could lead to errors in the releases scheduling."
|
|
413
|
+
);
|
|
414
|
+
throw err;
|
|
415
|
+
});
|
|
416
|
+
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
|
417
|
+
strapi2.webhookStore.addAllowedEvent(key, value);
|
|
418
|
+
});
|
|
376
419
|
}
|
|
377
420
|
};
|
|
378
421
|
const destroy = async ({ strapi: strapi2 }) => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
job.cancel();
|
|
385
|
-
}
|
|
422
|
+
const scheduledJobs = getService("scheduling", {
|
|
423
|
+
strapi: strapi2
|
|
424
|
+
}).getAll();
|
|
425
|
+
for (const [, job] of scheduledJobs) {
|
|
426
|
+
job.cancel();
|
|
386
427
|
}
|
|
387
428
|
};
|
|
388
429
|
const schema$1 = {
|
|
@@ -507,6 +548,94 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
507
548
|
release: release2
|
|
508
549
|
});
|
|
509
550
|
};
|
|
551
|
+
const publishSingleTypeAction = async (uid, actionType, entryId) => {
|
|
552
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
553
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
554
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
555
|
+
const entry = await strapi2.entityService.findOne(uid, entryId, { populate });
|
|
556
|
+
try {
|
|
557
|
+
if (actionType === "publish") {
|
|
558
|
+
await entityManagerService.publish(entry, uid);
|
|
559
|
+
} else {
|
|
560
|
+
await entityManagerService.unpublish(entry, uid);
|
|
561
|
+
}
|
|
562
|
+
} catch (error) {
|
|
563
|
+
if (error instanceof utils.errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
564
|
+
;
|
|
565
|
+
else {
|
|
566
|
+
throw error;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
const publishCollectionTypeAction = async (uid, entriesToPublishIds, entriestoUnpublishIds) => {
|
|
571
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
572
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
573
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
574
|
+
const entriesToPublish = await strapi2.entityService.findMany(uid, {
|
|
575
|
+
filters: {
|
|
576
|
+
id: {
|
|
577
|
+
$in: entriesToPublishIds
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
populate
|
|
581
|
+
});
|
|
582
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(uid, {
|
|
583
|
+
filters: {
|
|
584
|
+
id: {
|
|
585
|
+
$in: entriestoUnpublishIds
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
populate
|
|
589
|
+
});
|
|
590
|
+
if (entriesToPublish.length > 0) {
|
|
591
|
+
await entityManagerService.publishMany(entriesToPublish, uid);
|
|
592
|
+
}
|
|
593
|
+
if (entriesToUnpublish.length > 0) {
|
|
594
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, uid);
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
const getFormattedActions = async (releaseId) => {
|
|
598
|
+
const actions = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findMany({
|
|
599
|
+
where: {
|
|
600
|
+
release: {
|
|
601
|
+
id: releaseId
|
|
602
|
+
}
|
|
603
|
+
},
|
|
604
|
+
populate: {
|
|
605
|
+
entry: {
|
|
606
|
+
fields: ["id"]
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
if (actions.length === 0) {
|
|
611
|
+
throw new utils.errors.ValidationError("No entries to publish");
|
|
612
|
+
}
|
|
613
|
+
const collectionTypeActions = {};
|
|
614
|
+
const singleTypeActions = [];
|
|
615
|
+
for (const action of actions) {
|
|
616
|
+
const contentTypeUid = action.contentType;
|
|
617
|
+
if (strapi2.contentTypes[contentTypeUid].kind === "collectionType") {
|
|
618
|
+
if (!collectionTypeActions[contentTypeUid]) {
|
|
619
|
+
collectionTypeActions[contentTypeUid] = {
|
|
620
|
+
entriesToPublishIds: [],
|
|
621
|
+
entriesToUnpublishIds: []
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
if (action.type === "publish") {
|
|
625
|
+
collectionTypeActions[contentTypeUid].entriesToPublishIds.push(action.entry.id);
|
|
626
|
+
} else {
|
|
627
|
+
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
628
|
+
}
|
|
629
|
+
} else {
|
|
630
|
+
singleTypeActions.push({
|
|
631
|
+
uid: contentTypeUid,
|
|
632
|
+
action: action.type,
|
|
633
|
+
id: action.entry.id
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return { collectionTypeActions, singleTypeActions };
|
|
638
|
+
};
|
|
510
639
|
return {
|
|
511
640
|
async create(releaseData, { user }) {
|
|
512
641
|
const releaseWithCreatorFields = await utils.setCreatorFields({ user })(releaseData);
|
|
@@ -526,7 +655,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
526
655
|
status: "empty"
|
|
527
656
|
}
|
|
528
657
|
});
|
|
529
|
-
if (
|
|
658
|
+
if (releaseWithCreatorFields.scheduledAt) {
|
|
530
659
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
531
660
|
await schedulingService.set(release2.id, release2.scheduledAt);
|
|
532
661
|
}
|
|
@@ -651,13 +780,11 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
651
780
|
// @ts-expect-error see above
|
|
652
781
|
data: releaseWithCreatorFields
|
|
653
782
|
});
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
schedulingService.cancel(id);
|
|
660
|
-
}
|
|
783
|
+
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
784
|
+
if (releaseData.scheduledAt) {
|
|
785
|
+
await schedulingService.set(id, releaseData.scheduledAt);
|
|
786
|
+
} else if (release2.scheduledAt) {
|
|
787
|
+
schedulingService.cancel(id);
|
|
661
788
|
}
|
|
662
789
|
this.updateReleaseStatus(id);
|
|
663
790
|
strapi2.telemetry.send("didUpdateContentRelease");
|
|
@@ -823,7 +950,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
823
950
|
});
|
|
824
951
|
await strapi2.entityService.delete(RELEASE_MODEL_UID, releaseId);
|
|
825
952
|
});
|
|
826
|
-
if (
|
|
953
|
+
if (release2.scheduledAt) {
|
|
827
954
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
828
955
|
await schedulingService.cancel(release2.id);
|
|
829
956
|
}
|
|
@@ -831,145 +958,71 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
831
958
|
return release2;
|
|
832
959
|
},
|
|
833
960
|
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) {
|
|
961
|
+
const {
|
|
962
|
+
release: release2,
|
|
963
|
+
error
|
|
964
|
+
} = await strapi2.db.transaction(async ({ trx }) => {
|
|
965
|
+
const lockedRelease = await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).select(["id", "name", "releasedAt", "status"]).first().transacting(trx).forUpdate().execute();
|
|
966
|
+
if (!lockedRelease) {
|
|
851
967
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
852
968
|
}
|
|
853
|
-
if (
|
|
969
|
+
if (lockedRelease.releasedAt) {
|
|
854
970
|
throw new utils.errors.ValidationError("Release already published");
|
|
855
971
|
}
|
|
856
|
-
if (
|
|
857
|
-
throw new utils.errors.ValidationError("
|
|
972
|
+
if (lockedRelease.status === "failed") {
|
|
973
|
+
throw new utils.errors.ValidationError("Release failed to publish");
|
|
858
974
|
}
|
|
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);
|
|
975
|
+
try {
|
|
976
|
+
strapi2.log.info(`[Content Releases] Starting to publish release ${lockedRelease.name}`);
|
|
977
|
+
const { collectionTypeActions, singleTypeActions } = await getFormattedActions(
|
|
978
|
+
releaseId
|
|
979
|
+
);
|
|
980
|
+
await strapi2.db.transaction(async () => {
|
|
981
|
+
for (const { uid, action, id } of singleTypeActions) {
|
|
982
|
+
await publishSingleTypeAction(uid, action, id);
|
|
929
983
|
}
|
|
930
|
-
|
|
931
|
-
|
|
984
|
+
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
985
|
+
const uid = contentTypeUid;
|
|
986
|
+
await publishCollectionTypeAction(
|
|
987
|
+
uid,
|
|
988
|
+
collectionTypeActions[uid].entriesToPublishIds,
|
|
989
|
+
collectionTypeActions[uid].entriesToUnpublishIds
|
|
990
|
+
);
|
|
932
991
|
}
|
|
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
|
|
992
|
+
});
|
|
993
|
+
const release22 = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
994
|
+
where: {
|
|
995
|
+
id: releaseId
|
|
996
|
+
},
|
|
997
|
+
data: {
|
|
998
|
+
status: "done",
|
|
999
|
+
releasedAt: /* @__PURE__ */ new Date()
|
|
947
1000
|
}
|
|
948
|
-
}
|
|
949
|
-
});
|
|
950
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
1001
|
+
});
|
|
951
1002
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
952
1003
|
isPublished: true,
|
|
953
|
-
release:
|
|
1004
|
+
release: release22
|
|
954
1005
|
});
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
} catch (error) {
|
|
959
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
1006
|
+
strapi2.telemetry.send("didPublishContentRelease");
|
|
1007
|
+
return { release: release22, error: null };
|
|
1008
|
+
} catch (error2) {
|
|
960
1009
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
961
1010
|
isPublished: false,
|
|
962
|
-
error
|
|
1011
|
+
error: error2
|
|
963
1012
|
});
|
|
964
|
-
|
|
965
|
-
strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
966
|
-
where: { id: releaseId },
|
|
967
|
-
data: {
|
|
1013
|
+
await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).update({
|
|
968
1014
|
status: "failed"
|
|
969
|
-
}
|
|
970
|
-
|
|
1015
|
+
}).transacting(trx).execute();
|
|
1016
|
+
return {
|
|
1017
|
+
release: null,
|
|
1018
|
+
error: error2
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
if (error) {
|
|
971
1023
|
throw error;
|
|
972
1024
|
}
|
|
1025
|
+
return release2;
|
|
973
1026
|
},
|
|
974
1027
|
async updateAction(actionId, releaseId, update) {
|
|
975
1028
|
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
@@ -1056,6 +1109,12 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
1056
1109
|
}
|
|
1057
1110
|
};
|
|
1058
1111
|
};
|
|
1112
|
+
class AlreadyOnReleaseError extends utils.errors.ApplicationError {
|
|
1113
|
+
constructor(message) {
|
|
1114
|
+
super(message);
|
|
1115
|
+
this.name = "AlreadyOnReleaseError";
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1059
1118
|
const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
1060
1119
|
async validateUniqueEntry(releaseId, releaseActionArgs) {
|
|
1061
1120
|
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
@@ -1068,7 +1127,7 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1068
1127
|
(action) => Number(action.entry.id) === Number(releaseActionArgs.entry.id) && action.contentType === releaseActionArgs.entry.contentType
|
|
1069
1128
|
);
|
|
1070
1129
|
if (isEntryInRelease) {
|
|
1071
|
-
throw new
|
|
1130
|
+
throw new AlreadyOnReleaseError(
|
|
1072
1131
|
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
|
|
1073
1132
|
);
|
|
1074
1133
|
}
|
|
@@ -1176,7 +1235,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1176
1235
|
const services = {
|
|
1177
1236
|
release: createReleaseService,
|
|
1178
1237
|
"release-validation": createReleaseValidationService,
|
|
1179
|
-
|
|
1238
|
+
scheduling: createSchedulingService
|
|
1180
1239
|
};
|
|
1181
1240
|
const RELEASE_SCHEMA = yup__namespace.object().shape({
|
|
1182
1241
|
name: yup__namespace.string().trim().required(),
|
|
@@ -1352,6 +1411,38 @@ const releaseActionController = {
|
|
|
1352
1411
|
data: releaseAction2
|
|
1353
1412
|
};
|
|
1354
1413
|
},
|
|
1414
|
+
async createMany(ctx) {
|
|
1415
|
+
const releaseId = ctx.params.releaseId;
|
|
1416
|
+
const releaseActionsArgs = ctx.request.body;
|
|
1417
|
+
await Promise.all(
|
|
1418
|
+
releaseActionsArgs.map((releaseActionArgs) => validateReleaseAction(releaseActionArgs))
|
|
1419
|
+
);
|
|
1420
|
+
const releaseService = getService("release", { strapi });
|
|
1421
|
+
const releaseActions = await strapi.db.transaction(async () => {
|
|
1422
|
+
const releaseActions2 = await Promise.all(
|
|
1423
|
+
releaseActionsArgs.map(async (releaseActionArgs) => {
|
|
1424
|
+
try {
|
|
1425
|
+
const action = await releaseService.createAction(releaseId, releaseActionArgs);
|
|
1426
|
+
return action;
|
|
1427
|
+
} catch (error) {
|
|
1428
|
+
if (error instanceof AlreadyOnReleaseError) {
|
|
1429
|
+
return null;
|
|
1430
|
+
}
|
|
1431
|
+
throw error;
|
|
1432
|
+
}
|
|
1433
|
+
})
|
|
1434
|
+
);
|
|
1435
|
+
return releaseActions2;
|
|
1436
|
+
});
|
|
1437
|
+
const newReleaseActions = releaseActions.filter((action) => action !== null);
|
|
1438
|
+
ctx.body = {
|
|
1439
|
+
data: newReleaseActions,
|
|
1440
|
+
meta: {
|
|
1441
|
+
entriesAlreadyInRelease: releaseActions.length - newReleaseActions.length,
|
|
1442
|
+
totalEntries: releaseActions.length
|
|
1443
|
+
}
|
|
1444
|
+
};
|
|
1445
|
+
},
|
|
1355
1446
|
async findMany(ctx) {
|
|
1356
1447
|
const releaseId = ctx.params.releaseId;
|
|
1357
1448
|
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
@@ -1537,6 +1628,22 @@ const releaseAction = {
|
|
|
1537
1628
|
]
|
|
1538
1629
|
}
|
|
1539
1630
|
},
|
|
1631
|
+
{
|
|
1632
|
+
method: "POST",
|
|
1633
|
+
path: "/:releaseId/actions/bulk",
|
|
1634
|
+
handler: "release-action.createMany",
|
|
1635
|
+
config: {
|
|
1636
|
+
policies: [
|
|
1637
|
+
"admin::isAuthenticatedAdmin",
|
|
1638
|
+
{
|
|
1639
|
+
name: "admin::hasPermissions",
|
|
1640
|
+
config: {
|
|
1641
|
+
actions: ["plugin::content-releases.create-action"]
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
]
|
|
1645
|
+
}
|
|
1646
|
+
},
|
|
1540
1647
|
{
|
|
1541
1648
|
method: "GET",
|
|
1542
1649
|
path: "/:releaseId/actions",
|
|
@@ -1605,6 +1712,9 @@ const getPlugin = () => {
|
|
|
1605
1712
|
};
|
|
1606
1713
|
}
|
|
1607
1714
|
return {
|
|
1715
|
+
// Always return register, it handles its own feature check
|
|
1716
|
+
register,
|
|
1717
|
+
// Always return contentTypes to avoid losing data when the feature is disabled
|
|
1608
1718
|
contentTypes
|
|
1609
1719
|
};
|
|
1610
1720
|
};
|