@strapi/content-releases 0.0.0-next.d10040847b91742ccb8083938399b63ffa289c7a → 0.0.0-next.d54a672641d83234230d3d80d92aaf87f60f8c75
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/LICENSE +17 -1
- package/dist/_chunks/{App-lnXbSPgp.js → App-dLXY5ei3.js} +673 -630
- package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
- package/dist/_chunks/{App-g3vtS2Wa.mjs → App-jrh58sXY.mjs} +686 -643
- package/dist/_chunks/App-jrh58sXY.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-ItlgrLcr.js → index-CVO0Rqdm.js} +320 -18
- package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
- package/dist/_chunks/{index-uGex_IIQ.mjs → index-PiOGBETy.mjs} +335 -33
- package/dist/_chunks/index-PiOGBETy.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +331 -159
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +331 -159
- package/dist/server/index.mjs.map +1 -1
- package/package.json +13 -13
- package/dist/_chunks/App-g3vtS2Wa.mjs.map +0 -1
- package/dist/_chunks/App-lnXbSPgp.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-ItlgrLcr.js.map +0 -1
- package/dist/_chunks/index-uGex_IIQ.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,63 @@ 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
|
+
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
|
+
}
|
|
234
280
|
const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
|
|
235
281
|
const register = async ({ strapi: strapi2 }) => {
|
|
236
282
|
if (features$2.isEnabled("cms-content-releases")) {
|
|
237
283
|
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);
|
|
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();
|
|
240
291
|
}
|
|
241
292
|
};
|
|
242
293
|
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
@@ -362,27 +413,23 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
362
413
|
}
|
|
363
414
|
}
|
|
364
415
|
});
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
});
|
|
375
|
-
}
|
|
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
|
+
});
|
|
376
425
|
}
|
|
377
426
|
};
|
|
378
427
|
const destroy = async ({ strapi: strapi2 }) => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
job.cancel();
|
|
385
|
-
}
|
|
428
|
+
const scheduledJobs = getService("scheduling", {
|
|
429
|
+
strapi: strapi2
|
|
430
|
+
}).getAll();
|
|
431
|
+
for (const [, job] of scheduledJobs) {
|
|
432
|
+
job.cancel();
|
|
386
433
|
}
|
|
387
434
|
};
|
|
388
435
|
const schema$1 = {
|
|
@@ -507,6 +554,94 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
507
554
|
release: release2
|
|
508
555
|
});
|
|
509
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
|
+
};
|
|
510
645
|
return {
|
|
511
646
|
async create(releaseData, { user }) {
|
|
512
647
|
const releaseWithCreatorFields = await utils.setCreatorFields({ user })(releaseData);
|
|
@@ -526,7 +661,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
526
661
|
status: "empty"
|
|
527
662
|
}
|
|
528
663
|
});
|
|
529
|
-
if (
|
|
664
|
+
if (releaseWithCreatorFields.scheduledAt) {
|
|
530
665
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
531
666
|
await schedulingService.set(release2.id, release2.scheduledAt);
|
|
532
667
|
}
|
|
@@ -550,12 +685,18 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
550
685
|
}
|
|
551
686
|
});
|
|
552
687
|
},
|
|
553
|
-
async findManyWithContentTypeEntryAttached(contentTypeUid,
|
|
688
|
+
async findManyWithContentTypeEntryAttached(contentTypeUid, entriesIds) {
|
|
689
|
+
let entries = entriesIds;
|
|
690
|
+
if (!Array.isArray(entriesIds)) {
|
|
691
|
+
entries = [entriesIds];
|
|
692
|
+
}
|
|
554
693
|
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
555
694
|
where: {
|
|
556
695
|
actions: {
|
|
557
696
|
target_type: contentTypeUid,
|
|
558
|
-
target_id:
|
|
697
|
+
target_id: {
|
|
698
|
+
$in: entries
|
|
699
|
+
}
|
|
559
700
|
},
|
|
560
701
|
releasedAt: {
|
|
561
702
|
$null: true
|
|
@@ -566,18 +707,25 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
566
707
|
actions: {
|
|
567
708
|
where: {
|
|
568
709
|
target_type: contentTypeUid,
|
|
569
|
-
target_id:
|
|
710
|
+
target_id: {
|
|
711
|
+
$in: entries
|
|
712
|
+
}
|
|
713
|
+
},
|
|
714
|
+
populate: {
|
|
715
|
+
entry: {
|
|
716
|
+
select: ["id"]
|
|
717
|
+
}
|
|
570
718
|
}
|
|
571
719
|
}
|
|
572
720
|
}
|
|
573
721
|
});
|
|
574
722
|
return releases.map((release2) => {
|
|
575
723
|
if (release2.actions?.length) {
|
|
576
|
-
const
|
|
724
|
+
const actionsForEntry = release2.actions;
|
|
577
725
|
delete release2.actions;
|
|
578
726
|
return {
|
|
579
727
|
...release2,
|
|
580
|
-
|
|
728
|
+
actions: actionsForEntry
|
|
581
729
|
};
|
|
582
730
|
}
|
|
583
731
|
return release2;
|
|
@@ -651,13 +799,11 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
651
799
|
// @ts-expect-error see above
|
|
652
800
|
data: releaseWithCreatorFields
|
|
653
801
|
});
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
schedulingService.cancel(id);
|
|
660
|
-
}
|
|
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);
|
|
661
807
|
}
|
|
662
808
|
this.updateReleaseStatus(id);
|
|
663
809
|
strapi2.telemetry.send("didUpdateContentRelease");
|
|
@@ -823,7 +969,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
823
969
|
});
|
|
824
970
|
await strapi2.entityService.delete(RELEASE_MODEL_UID, releaseId);
|
|
825
971
|
});
|
|
826
|
-
if (
|
|
972
|
+
if (release2.scheduledAt) {
|
|
827
973
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
828
974
|
await schedulingService.cancel(release2.id);
|
|
829
975
|
}
|
|
@@ -831,145 +977,71 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
831
977
|
return release2;
|
|
832
978
|
},
|
|
833
979
|
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) {
|
|
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) {
|
|
851
986
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
852
987
|
}
|
|
853
|
-
if (
|
|
988
|
+
if (lockedRelease.releasedAt) {
|
|
854
989
|
throw new utils.errors.ValidationError("Release already published");
|
|
855
990
|
}
|
|
856
|
-
if (
|
|
857
|
-
throw new utils.errors.ValidationError("
|
|
991
|
+
if (lockedRelease.status === "failed") {
|
|
992
|
+
throw new utils.errors.ValidationError("Release failed to publish");
|
|
858
993
|
}
|
|
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);
|
|
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);
|
|
929
1002
|
}
|
|
930
|
-
|
|
931
|
-
|
|
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
|
+
);
|
|
932
1010
|
}
|
|
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
|
|
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()
|
|
947
1019
|
}
|
|
948
|
-
}
|
|
949
|
-
});
|
|
950
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
1020
|
+
});
|
|
951
1021
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
952
1022
|
isPublished: true,
|
|
953
|
-
release:
|
|
1023
|
+
release: release22
|
|
954
1024
|
});
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
} catch (error) {
|
|
959
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
1025
|
+
strapi2.telemetry.send("didPublishContentRelease");
|
|
1026
|
+
return { release: release22, error: null };
|
|
1027
|
+
} catch (error2) {
|
|
960
1028
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
961
1029
|
isPublished: false,
|
|
962
|
-
error
|
|
1030
|
+
error: error2
|
|
963
1031
|
});
|
|
964
|
-
|
|
965
|
-
strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
966
|
-
where: { id: releaseId },
|
|
967
|
-
data: {
|
|
1032
|
+
await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).update({
|
|
968
1033
|
status: "failed"
|
|
969
|
-
}
|
|
970
|
-
|
|
1034
|
+
}).transacting(trx).execute();
|
|
1035
|
+
return {
|
|
1036
|
+
release: null,
|
|
1037
|
+
error: error2
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
if (error) {
|
|
971
1042
|
throw error;
|
|
972
1043
|
}
|
|
1044
|
+
return release2;
|
|
973
1045
|
},
|
|
974
1046
|
async updateAction(actionId, releaseId, update) {
|
|
975
1047
|
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
@@ -1056,6 +1128,12 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
1056
1128
|
}
|
|
1057
1129
|
};
|
|
1058
1130
|
};
|
|
1131
|
+
class AlreadyOnReleaseError extends utils.errors.ApplicationError {
|
|
1132
|
+
constructor(message) {
|
|
1133
|
+
super(message);
|
|
1134
|
+
this.name = "AlreadyOnReleaseError";
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1059
1137
|
const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
1060
1138
|
async validateUniqueEntry(releaseId, releaseActionArgs) {
|
|
1061
1139
|
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
@@ -1068,7 +1146,7 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1068
1146
|
(action) => Number(action.entry.id) === Number(releaseActionArgs.entry.id) && action.contentType === releaseActionArgs.entry.contentType
|
|
1069
1147
|
);
|
|
1070
1148
|
if (isEntryInRelease) {
|
|
1071
|
-
throw new
|
|
1149
|
+
throw new AlreadyOnReleaseError(
|
|
1072
1150
|
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
|
|
1073
1151
|
);
|
|
1074
1152
|
}
|
|
@@ -1176,7 +1254,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1176
1254
|
const services = {
|
|
1177
1255
|
release: createReleaseService,
|
|
1178
1256
|
"release-validation": createReleaseValidationService,
|
|
1179
|
-
|
|
1257
|
+
scheduling: createSchedulingService
|
|
1180
1258
|
};
|
|
1181
1259
|
const RELEASE_SCHEMA = yup__namespace.object().shape({
|
|
1182
1260
|
name: yup__namespace.string().trim().required(),
|
|
@@ -1263,6 +1341,33 @@ const releaseController = {
|
|
|
1263
1341
|
};
|
|
1264
1342
|
ctx.body = { data };
|
|
1265
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
|
+
},
|
|
1266
1371
|
async create(ctx) {
|
|
1267
1372
|
const user = ctx.state.user;
|
|
1268
1373
|
const releaseArgs = ctx.request.body;
|
|
@@ -1352,6 +1457,38 @@ const releaseActionController = {
|
|
|
1352
1457
|
data: releaseAction2
|
|
1353
1458
|
};
|
|
1354
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
|
+
},
|
|
1355
1492
|
async findMany(ctx) {
|
|
1356
1493
|
const releaseId = ctx.params.releaseId;
|
|
1357
1494
|
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
@@ -1420,6 +1557,22 @@ const controllers = { release: releaseController, "release-action": releaseActio
|
|
|
1420
1557
|
const release = {
|
|
1421
1558
|
type: "admin",
|
|
1422
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
|
+
},
|
|
1423
1576
|
{
|
|
1424
1577
|
method: "POST",
|
|
1425
1578
|
path: "/",
|
|
@@ -1537,6 +1690,22 @@ const releaseAction = {
|
|
|
1537
1690
|
]
|
|
1538
1691
|
}
|
|
1539
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
|
+
},
|
|
1540
1709
|
{
|
|
1541
1710
|
method: "GET",
|
|
1542
1711
|
path: "/:releaseId/actions",
|
|
@@ -1605,6 +1774,9 @@ const getPlugin = () => {
|
|
|
1605
1774
|
};
|
|
1606
1775
|
}
|
|
1607
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
|
|
1608
1780
|
contentTypes
|
|
1609
1781
|
};
|
|
1610
1782
|
};
|