@strapi/content-releases 0.0.0-next.d10040847b91742ccb8083938399b63ffa289c7a → 0.0.0-next.de77e236e318525454da54a1a2617d86742e6e6c
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-lnXbSPgp.js → App-HjWtUYmc.js} +673 -630
- package/dist/_chunks/App-HjWtUYmc.js.map +1 -0
- package/dist/_chunks/{App-g3vtS2Wa.mjs → App-gu1aiP6i.mjs} +686 -643
- package/dist/_chunks/App-gu1aiP6i.mjs.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-3tRbmbY3.mjs} +2 -2
- package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-bpIYXOfu.js} +2 -2
- package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
- package/dist/_chunks/{en-gcJJ5htG.js → en-HrREghh3.js} +11 -3
- package/dist/_chunks/en-HrREghh3.js.map +1 -0
- package/dist/_chunks/{en-WuuhP6Bn.mjs → en-ltT1TlKQ.mjs} +11 -3
- package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
- package/dist/_chunks/{index-ItlgrLcr.js → index-ZNwxYN8H.js} +319 -18
- package/dist/_chunks/index-ZNwxYN8H.js.map +1 -0
- package/dist/_chunks/{index-uGex_IIQ.mjs → index-mvj9PSKd.mjs} +334 -33
- package/dist/_chunks/index-mvj9PSKd.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +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 +12 -12
- 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.mjs
CHANGED
|
@@ -179,7 +179,7 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
179
179
|
}
|
|
180
180
|
});
|
|
181
181
|
await mapAsync(actions, async (action) => {
|
|
182
|
-
if (action.entry) {
|
|
182
|
+
if (action.entry && action.release) {
|
|
183
183
|
const populatedEntry = await getPopulatedEntry(contentTypeUID, action.entry.id, {
|
|
184
184
|
strapi
|
|
185
185
|
});
|
|
@@ -207,12 +207,63 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
207
207
|
});
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
|
+
async function disableContentTypeLocalized({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
211
|
+
if (!oldContentTypes) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
215
|
+
if (!i18nPlugin) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
for (const uid in contentTypes2) {
|
|
219
|
+
if (!oldContentTypes[uid]) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
const oldContentType = oldContentTypes[uid];
|
|
223
|
+
const contentType = contentTypes2[uid];
|
|
224
|
+
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
225
|
+
if (isLocalizedContentType(oldContentType) && !isLocalizedContentType(contentType)) {
|
|
226
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
227
|
+
locale: null
|
|
228
|
+
}).where({ contentType: uid }).execute();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function enableContentTypeLocalized({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
233
|
+
if (!oldContentTypes) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
237
|
+
if (!i18nPlugin) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
for (const uid in contentTypes2) {
|
|
241
|
+
if (!oldContentTypes[uid]) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const oldContentType = oldContentTypes[uid];
|
|
245
|
+
const contentType = contentTypes2[uid];
|
|
246
|
+
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
247
|
+
const { getDefaultLocale } = i18nPlugin.service("locales");
|
|
248
|
+
if (!isLocalizedContentType(oldContentType) && isLocalizedContentType(contentType)) {
|
|
249
|
+
const defaultLocale = await getDefaultLocale();
|
|
250
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
251
|
+
locale: defaultLocale
|
|
252
|
+
}).where({ contentType: uid }).execute();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
210
256
|
const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
|
|
211
257
|
const register = async ({ strapi: strapi2 }) => {
|
|
212
258
|
if (features$2.isEnabled("cms-content-releases")) {
|
|
213
259
|
await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
|
|
214
|
-
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish);
|
|
215
|
-
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
260
|
+
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish).register(disableContentTypeLocalized);
|
|
261
|
+
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(enableContentTypeLocalized).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
262
|
+
}
|
|
263
|
+
if (strapi2.plugin("graphql")) {
|
|
264
|
+
const graphqlExtensionService = strapi2.plugin("graphql").service("extension");
|
|
265
|
+
graphqlExtensionService.shadowCRUD(RELEASE_MODEL_UID).disable();
|
|
266
|
+
graphqlExtensionService.shadowCRUD(RELEASE_ACTION_MODEL_UID).disable();
|
|
216
267
|
}
|
|
217
268
|
};
|
|
218
269
|
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
@@ -338,27 +389,23 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
338
389
|
}
|
|
339
390
|
}
|
|
340
391
|
});
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
});
|
|
351
|
-
}
|
|
392
|
+
getService("scheduling", { strapi: strapi2 }).syncFromDatabase().catch((err) => {
|
|
393
|
+
strapi2.log.error(
|
|
394
|
+
"Error while syncing scheduled jobs from the database in the content-releases plugin. This could lead to errors in the releases scheduling."
|
|
395
|
+
);
|
|
396
|
+
throw err;
|
|
397
|
+
});
|
|
398
|
+
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
|
399
|
+
strapi2.webhookStore.addAllowedEvent(key, value);
|
|
400
|
+
});
|
|
352
401
|
}
|
|
353
402
|
};
|
|
354
403
|
const destroy = async ({ strapi: strapi2 }) => {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
job.cancel();
|
|
361
|
-
}
|
|
404
|
+
const scheduledJobs = getService("scheduling", {
|
|
405
|
+
strapi: strapi2
|
|
406
|
+
}).getAll();
|
|
407
|
+
for (const [, job] of scheduledJobs) {
|
|
408
|
+
job.cancel();
|
|
362
409
|
}
|
|
363
410
|
};
|
|
364
411
|
const schema$1 = {
|
|
@@ -483,6 +530,94 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
483
530
|
release: release2
|
|
484
531
|
});
|
|
485
532
|
};
|
|
533
|
+
const publishSingleTypeAction = async (uid, actionType, entryId) => {
|
|
534
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
535
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
536
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
537
|
+
const entry = await strapi2.entityService.findOne(uid, entryId, { populate });
|
|
538
|
+
try {
|
|
539
|
+
if (actionType === "publish") {
|
|
540
|
+
await entityManagerService.publish(entry, uid);
|
|
541
|
+
} else {
|
|
542
|
+
await entityManagerService.unpublish(entry, uid);
|
|
543
|
+
}
|
|
544
|
+
} catch (error) {
|
|
545
|
+
if (error instanceof errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
546
|
+
;
|
|
547
|
+
else {
|
|
548
|
+
throw error;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
const publishCollectionTypeAction = async (uid, entriesToPublishIds, entriestoUnpublishIds) => {
|
|
553
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
554
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
555
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
556
|
+
const entriesToPublish = await strapi2.entityService.findMany(uid, {
|
|
557
|
+
filters: {
|
|
558
|
+
id: {
|
|
559
|
+
$in: entriesToPublishIds
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
populate
|
|
563
|
+
});
|
|
564
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(uid, {
|
|
565
|
+
filters: {
|
|
566
|
+
id: {
|
|
567
|
+
$in: entriestoUnpublishIds
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
populate
|
|
571
|
+
});
|
|
572
|
+
if (entriesToPublish.length > 0) {
|
|
573
|
+
await entityManagerService.publishMany(entriesToPublish, uid);
|
|
574
|
+
}
|
|
575
|
+
if (entriesToUnpublish.length > 0) {
|
|
576
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, uid);
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
const getFormattedActions = async (releaseId) => {
|
|
580
|
+
const actions = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findMany({
|
|
581
|
+
where: {
|
|
582
|
+
release: {
|
|
583
|
+
id: releaseId
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
populate: {
|
|
587
|
+
entry: {
|
|
588
|
+
fields: ["id"]
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
if (actions.length === 0) {
|
|
593
|
+
throw new errors.ValidationError("No entries to publish");
|
|
594
|
+
}
|
|
595
|
+
const collectionTypeActions = {};
|
|
596
|
+
const singleTypeActions = [];
|
|
597
|
+
for (const action of actions) {
|
|
598
|
+
const contentTypeUid = action.contentType;
|
|
599
|
+
if (strapi2.contentTypes[contentTypeUid].kind === "collectionType") {
|
|
600
|
+
if (!collectionTypeActions[contentTypeUid]) {
|
|
601
|
+
collectionTypeActions[contentTypeUid] = {
|
|
602
|
+
entriesToPublishIds: [],
|
|
603
|
+
entriesToUnpublishIds: []
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
if (action.type === "publish") {
|
|
607
|
+
collectionTypeActions[contentTypeUid].entriesToPublishIds.push(action.entry.id);
|
|
608
|
+
} else {
|
|
609
|
+
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
610
|
+
}
|
|
611
|
+
} else {
|
|
612
|
+
singleTypeActions.push({
|
|
613
|
+
uid: contentTypeUid,
|
|
614
|
+
action: action.type,
|
|
615
|
+
id: action.entry.id
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return { collectionTypeActions, singleTypeActions };
|
|
620
|
+
};
|
|
486
621
|
return {
|
|
487
622
|
async create(releaseData, { user }) {
|
|
488
623
|
const releaseWithCreatorFields = await setCreatorFields({ user })(releaseData);
|
|
@@ -502,7 +637,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
502
637
|
status: "empty"
|
|
503
638
|
}
|
|
504
639
|
});
|
|
505
|
-
if (
|
|
640
|
+
if (releaseWithCreatorFields.scheduledAt) {
|
|
506
641
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
507
642
|
await schedulingService.set(release2.id, release2.scheduledAt);
|
|
508
643
|
}
|
|
@@ -526,12 +661,18 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
526
661
|
}
|
|
527
662
|
});
|
|
528
663
|
},
|
|
529
|
-
async findManyWithContentTypeEntryAttached(contentTypeUid,
|
|
664
|
+
async findManyWithContentTypeEntryAttached(contentTypeUid, entriesIds) {
|
|
665
|
+
let entries = entriesIds;
|
|
666
|
+
if (!Array.isArray(entriesIds)) {
|
|
667
|
+
entries = [entriesIds];
|
|
668
|
+
}
|
|
530
669
|
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
531
670
|
where: {
|
|
532
671
|
actions: {
|
|
533
672
|
target_type: contentTypeUid,
|
|
534
|
-
target_id:
|
|
673
|
+
target_id: {
|
|
674
|
+
$in: entries
|
|
675
|
+
}
|
|
535
676
|
},
|
|
536
677
|
releasedAt: {
|
|
537
678
|
$null: true
|
|
@@ -542,18 +683,25 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
542
683
|
actions: {
|
|
543
684
|
where: {
|
|
544
685
|
target_type: contentTypeUid,
|
|
545
|
-
target_id:
|
|
686
|
+
target_id: {
|
|
687
|
+
$in: entries
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
populate: {
|
|
691
|
+
entry: {
|
|
692
|
+
select: ["id"]
|
|
693
|
+
}
|
|
546
694
|
}
|
|
547
695
|
}
|
|
548
696
|
}
|
|
549
697
|
});
|
|
550
698
|
return releases.map((release2) => {
|
|
551
699
|
if (release2.actions?.length) {
|
|
552
|
-
const
|
|
700
|
+
const actionsForEntry = release2.actions;
|
|
553
701
|
delete release2.actions;
|
|
554
702
|
return {
|
|
555
703
|
...release2,
|
|
556
|
-
|
|
704
|
+
actions: actionsForEntry
|
|
557
705
|
};
|
|
558
706
|
}
|
|
559
707
|
return release2;
|
|
@@ -627,13 +775,11 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
627
775
|
// @ts-expect-error see above
|
|
628
776
|
data: releaseWithCreatorFields
|
|
629
777
|
});
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
schedulingService.cancel(id);
|
|
636
|
-
}
|
|
778
|
+
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
779
|
+
if (releaseData.scheduledAt) {
|
|
780
|
+
await schedulingService.set(id, releaseData.scheduledAt);
|
|
781
|
+
} else if (release2.scheduledAt) {
|
|
782
|
+
schedulingService.cancel(id);
|
|
637
783
|
}
|
|
638
784
|
this.updateReleaseStatus(id);
|
|
639
785
|
strapi2.telemetry.send("didUpdateContentRelease");
|
|
@@ -799,7 +945,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
799
945
|
});
|
|
800
946
|
await strapi2.entityService.delete(RELEASE_MODEL_UID, releaseId);
|
|
801
947
|
});
|
|
802
|
-
if (
|
|
948
|
+
if (release2.scheduledAt) {
|
|
803
949
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
804
950
|
await schedulingService.cancel(release2.id);
|
|
805
951
|
}
|
|
@@ -807,145 +953,71 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
807
953
|
return release2;
|
|
808
954
|
},
|
|
809
955
|
async publish(releaseId) {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
actions: {
|
|
817
|
-
populate: {
|
|
818
|
-
entry: {
|
|
819
|
-
fields: ["id"]
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
);
|
|
826
|
-
if (!releaseWithPopulatedActionEntries) {
|
|
956
|
+
const {
|
|
957
|
+
release: release2,
|
|
958
|
+
error
|
|
959
|
+
} = await strapi2.db.transaction(async ({ trx }) => {
|
|
960
|
+
const lockedRelease = await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).select(["id", "name", "releasedAt", "status"]).first().transacting(trx).forUpdate().execute();
|
|
961
|
+
if (!lockedRelease) {
|
|
827
962
|
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
828
963
|
}
|
|
829
|
-
if (
|
|
964
|
+
if (lockedRelease.releasedAt) {
|
|
830
965
|
throw new errors.ValidationError("Release already published");
|
|
831
966
|
}
|
|
832
|
-
if (
|
|
833
|
-
throw new errors.ValidationError("
|
|
967
|
+
if (lockedRelease.status === "failed") {
|
|
968
|
+
throw new errors.ValidationError("Release failed to publish");
|
|
834
969
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
entriesToUnpublishIds: []
|
|
844
|
-
};
|
|
845
|
-
}
|
|
846
|
-
if (action.type === "publish") {
|
|
847
|
-
collectionTypeActions[contentTypeUid].entriestoPublishIds.push(action.entry.id);
|
|
848
|
-
} else {
|
|
849
|
-
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
850
|
-
}
|
|
851
|
-
} else {
|
|
852
|
-
singleTypeActions.push({
|
|
853
|
-
uid: contentTypeUid,
|
|
854
|
-
action: action.type,
|
|
855
|
-
id: action.entry.id
|
|
856
|
-
});
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
860
|
-
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
861
|
-
await strapi2.db.transaction(async () => {
|
|
862
|
-
for (const { uid, action, id } of singleTypeActions) {
|
|
863
|
-
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
864
|
-
const entry = await strapi2.entityService.findOne(uid, id, { populate });
|
|
865
|
-
try {
|
|
866
|
-
if (action === "publish") {
|
|
867
|
-
await entityManagerService.publish(entry, uid);
|
|
868
|
-
} else {
|
|
869
|
-
await entityManagerService.unpublish(entry, uid);
|
|
870
|
-
}
|
|
871
|
-
} catch (error) {
|
|
872
|
-
if (error instanceof errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft")) {
|
|
873
|
-
} else {
|
|
874
|
-
throw error;
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
879
|
-
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
880
|
-
const { entriestoPublishIds, entriesToUnpublishIds } = collectionTypeActions[contentTypeUid];
|
|
881
|
-
const entriesToPublish = await strapi2.entityService.findMany(
|
|
882
|
-
contentTypeUid,
|
|
883
|
-
{
|
|
884
|
-
filters: {
|
|
885
|
-
id: {
|
|
886
|
-
$in: entriestoPublishIds
|
|
887
|
-
}
|
|
888
|
-
},
|
|
889
|
-
populate
|
|
890
|
-
}
|
|
891
|
-
);
|
|
892
|
-
const entriesToUnpublish = await strapi2.entityService.findMany(
|
|
893
|
-
contentTypeUid,
|
|
894
|
-
{
|
|
895
|
-
filters: {
|
|
896
|
-
id: {
|
|
897
|
-
$in: entriesToUnpublishIds
|
|
898
|
-
}
|
|
899
|
-
},
|
|
900
|
-
populate
|
|
901
|
-
}
|
|
902
|
-
);
|
|
903
|
-
if (entriesToPublish.length > 0) {
|
|
904
|
-
await entityManagerService.publishMany(entriesToPublish, contentTypeUid);
|
|
970
|
+
try {
|
|
971
|
+
strapi2.log.info(`[Content Releases] Starting to publish release ${lockedRelease.name}`);
|
|
972
|
+
const { collectionTypeActions, singleTypeActions } = await getFormattedActions(
|
|
973
|
+
releaseId
|
|
974
|
+
);
|
|
975
|
+
await strapi2.db.transaction(async () => {
|
|
976
|
+
for (const { uid, action, id } of singleTypeActions) {
|
|
977
|
+
await publishSingleTypeAction(uid, action, id);
|
|
905
978
|
}
|
|
906
|
-
|
|
907
|
-
|
|
979
|
+
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
980
|
+
const uid = contentTypeUid;
|
|
981
|
+
await publishCollectionTypeAction(
|
|
982
|
+
uid,
|
|
983
|
+
collectionTypeActions[uid].entriesToPublishIds,
|
|
984
|
+
collectionTypeActions[uid].entriesToUnpublishIds
|
|
985
|
+
);
|
|
908
986
|
}
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
releasedAt: /* @__PURE__ */ new Date()
|
|
918
|
-
},
|
|
919
|
-
populate: {
|
|
920
|
-
actions: {
|
|
921
|
-
// @ts-expect-error is not expecting count but it is working
|
|
922
|
-
count: true
|
|
987
|
+
});
|
|
988
|
+
const release22 = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
989
|
+
where: {
|
|
990
|
+
id: releaseId
|
|
991
|
+
},
|
|
992
|
+
data: {
|
|
993
|
+
status: "done",
|
|
994
|
+
releasedAt: /* @__PURE__ */ new Date()
|
|
923
995
|
}
|
|
924
|
-
}
|
|
925
|
-
});
|
|
926
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
996
|
+
});
|
|
927
997
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
928
998
|
isPublished: true,
|
|
929
|
-
release:
|
|
999
|
+
release: release22
|
|
930
1000
|
});
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
} catch (error) {
|
|
935
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
1001
|
+
strapi2.telemetry.send("didPublishContentRelease");
|
|
1002
|
+
return { release: release22, error: null };
|
|
1003
|
+
} catch (error2) {
|
|
936
1004
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
937
1005
|
isPublished: false,
|
|
938
|
-
error
|
|
1006
|
+
error: error2
|
|
939
1007
|
});
|
|
940
|
-
|
|
941
|
-
strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
942
|
-
where: { id: releaseId },
|
|
943
|
-
data: {
|
|
1008
|
+
await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).update({
|
|
944
1009
|
status: "failed"
|
|
945
|
-
}
|
|
946
|
-
|
|
1010
|
+
}).transacting(trx).execute();
|
|
1011
|
+
return {
|
|
1012
|
+
release: null,
|
|
1013
|
+
error: error2
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1017
|
+
if (error) {
|
|
947
1018
|
throw error;
|
|
948
1019
|
}
|
|
1020
|
+
return release2;
|
|
949
1021
|
},
|
|
950
1022
|
async updateAction(actionId, releaseId, update) {
|
|
951
1023
|
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
@@ -1032,6 +1104,12 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
1032
1104
|
}
|
|
1033
1105
|
};
|
|
1034
1106
|
};
|
|
1107
|
+
class AlreadyOnReleaseError extends errors.ApplicationError {
|
|
1108
|
+
constructor(message) {
|
|
1109
|
+
super(message);
|
|
1110
|
+
this.name = "AlreadyOnReleaseError";
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1035
1113
|
const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
1036
1114
|
async validateUniqueEntry(releaseId, releaseActionArgs) {
|
|
1037
1115
|
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
@@ -1044,7 +1122,7 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1044
1122
|
(action) => Number(action.entry.id) === Number(releaseActionArgs.entry.id) && action.contentType === releaseActionArgs.entry.contentType
|
|
1045
1123
|
);
|
|
1046
1124
|
if (isEntryInRelease) {
|
|
1047
|
-
throw new
|
|
1125
|
+
throw new AlreadyOnReleaseError(
|
|
1048
1126
|
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
|
|
1049
1127
|
);
|
|
1050
1128
|
}
|
|
@@ -1152,7 +1230,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1152
1230
|
const services = {
|
|
1153
1231
|
release: createReleaseService,
|
|
1154
1232
|
"release-validation": createReleaseValidationService,
|
|
1155
|
-
|
|
1233
|
+
scheduling: createSchedulingService
|
|
1156
1234
|
};
|
|
1157
1235
|
const RELEASE_SCHEMA = yup.object().shape({
|
|
1158
1236
|
name: yup.string().trim().required(),
|
|
@@ -1239,6 +1317,33 @@ const releaseController = {
|
|
|
1239
1317
|
};
|
|
1240
1318
|
ctx.body = { data };
|
|
1241
1319
|
},
|
|
1320
|
+
async mapEntriesToReleases(ctx) {
|
|
1321
|
+
const { contentTypeUid, entriesIds } = ctx.query;
|
|
1322
|
+
if (!contentTypeUid || !entriesIds) {
|
|
1323
|
+
throw new errors.ValidationError("Missing required query parameters");
|
|
1324
|
+
}
|
|
1325
|
+
const releaseService = getService("release", { strapi });
|
|
1326
|
+
const releasesWithActions = await releaseService.findManyWithContentTypeEntryAttached(
|
|
1327
|
+
contentTypeUid,
|
|
1328
|
+
entriesIds
|
|
1329
|
+
);
|
|
1330
|
+
const mappedEntriesInReleases = releasesWithActions.reduce(
|
|
1331
|
+
(acc, release2) => {
|
|
1332
|
+
release2.actions.forEach((action) => {
|
|
1333
|
+
if (!acc[action.entry.id]) {
|
|
1334
|
+
acc[action.entry.id] = [{ id: release2.id, name: release2.name }];
|
|
1335
|
+
} else {
|
|
1336
|
+
acc[action.entry.id].push({ id: release2.id, name: release2.name });
|
|
1337
|
+
}
|
|
1338
|
+
});
|
|
1339
|
+
return acc;
|
|
1340
|
+
},
|
|
1341
|
+
{}
|
|
1342
|
+
);
|
|
1343
|
+
ctx.body = {
|
|
1344
|
+
data: mappedEntriesInReleases
|
|
1345
|
+
};
|
|
1346
|
+
},
|
|
1242
1347
|
async create(ctx) {
|
|
1243
1348
|
const user = ctx.state.user;
|
|
1244
1349
|
const releaseArgs = ctx.request.body;
|
|
@@ -1328,6 +1433,38 @@ const releaseActionController = {
|
|
|
1328
1433
|
data: releaseAction2
|
|
1329
1434
|
};
|
|
1330
1435
|
},
|
|
1436
|
+
async createMany(ctx) {
|
|
1437
|
+
const releaseId = ctx.params.releaseId;
|
|
1438
|
+
const releaseActionsArgs = ctx.request.body;
|
|
1439
|
+
await Promise.all(
|
|
1440
|
+
releaseActionsArgs.map((releaseActionArgs) => validateReleaseAction(releaseActionArgs))
|
|
1441
|
+
);
|
|
1442
|
+
const releaseService = getService("release", { strapi });
|
|
1443
|
+
const releaseActions = await strapi.db.transaction(async () => {
|
|
1444
|
+
const releaseActions2 = await Promise.all(
|
|
1445
|
+
releaseActionsArgs.map(async (releaseActionArgs) => {
|
|
1446
|
+
try {
|
|
1447
|
+
const action = await releaseService.createAction(releaseId, releaseActionArgs);
|
|
1448
|
+
return action;
|
|
1449
|
+
} catch (error) {
|
|
1450
|
+
if (error instanceof AlreadyOnReleaseError) {
|
|
1451
|
+
return null;
|
|
1452
|
+
}
|
|
1453
|
+
throw error;
|
|
1454
|
+
}
|
|
1455
|
+
})
|
|
1456
|
+
);
|
|
1457
|
+
return releaseActions2;
|
|
1458
|
+
});
|
|
1459
|
+
const newReleaseActions = releaseActions.filter((action) => action !== null);
|
|
1460
|
+
ctx.body = {
|
|
1461
|
+
data: newReleaseActions,
|
|
1462
|
+
meta: {
|
|
1463
|
+
entriesAlreadyInRelease: releaseActions.length - newReleaseActions.length,
|
|
1464
|
+
totalEntries: releaseActions.length
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
},
|
|
1331
1468
|
async findMany(ctx) {
|
|
1332
1469
|
const releaseId = ctx.params.releaseId;
|
|
1333
1470
|
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
@@ -1396,6 +1533,22 @@ const controllers = { release: releaseController, "release-action": releaseActio
|
|
|
1396
1533
|
const release = {
|
|
1397
1534
|
type: "admin",
|
|
1398
1535
|
routes: [
|
|
1536
|
+
{
|
|
1537
|
+
method: "GET",
|
|
1538
|
+
path: "/mapEntriesToReleases",
|
|
1539
|
+
handler: "release.mapEntriesToReleases",
|
|
1540
|
+
config: {
|
|
1541
|
+
policies: [
|
|
1542
|
+
"admin::isAuthenticatedAdmin",
|
|
1543
|
+
{
|
|
1544
|
+
name: "admin::hasPermissions",
|
|
1545
|
+
config: {
|
|
1546
|
+
actions: ["plugin::content-releases.read"]
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
]
|
|
1550
|
+
}
|
|
1551
|
+
},
|
|
1399
1552
|
{
|
|
1400
1553
|
method: "POST",
|
|
1401
1554
|
path: "/",
|
|
@@ -1513,6 +1666,22 @@ const releaseAction = {
|
|
|
1513
1666
|
]
|
|
1514
1667
|
}
|
|
1515
1668
|
},
|
|
1669
|
+
{
|
|
1670
|
+
method: "POST",
|
|
1671
|
+
path: "/:releaseId/actions/bulk",
|
|
1672
|
+
handler: "release-action.createMany",
|
|
1673
|
+
config: {
|
|
1674
|
+
policies: [
|
|
1675
|
+
"admin::isAuthenticatedAdmin",
|
|
1676
|
+
{
|
|
1677
|
+
name: "admin::hasPermissions",
|
|
1678
|
+
config: {
|
|
1679
|
+
actions: ["plugin::content-releases.create-action"]
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
]
|
|
1683
|
+
}
|
|
1684
|
+
},
|
|
1516
1685
|
{
|
|
1517
1686
|
method: "GET",
|
|
1518
1687
|
path: "/:releaseId/actions",
|
|
@@ -1581,6 +1750,9 @@ const getPlugin = () => {
|
|
|
1581
1750
|
};
|
|
1582
1751
|
}
|
|
1583
1752
|
return {
|
|
1753
|
+
// Always return register, it handles its own feature check
|
|
1754
|
+
register,
|
|
1755
|
+
// Always return contentTypes to avoid losing data when the feature is disabled
|
|
1584
1756
|
contentTypes
|
|
1585
1757
|
};
|
|
1586
1758
|
};
|