@strapi/content-releases 0.0.0-next.78ea7925e0dad75936ae2e937a041a0666e3d65a → 0.0.0-next.80375f19ecbd1a8f298515d011c3ddb5ed05f924

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.
Files changed (32) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/{App-p8aKBitd.js → App-dLXY5ei3.js} +138 -131
  3. package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
  4. package/dist/_chunks/{App-bpzO2Ljh.mjs → App-jrh58sXY.mjs} +141 -134
  5. package/dist/_chunks/App-jrh58sXY.mjs.map +1 -0
  6. package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-3tRbmbY3.mjs} +2 -2
  7. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
  8. package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-bpIYXOfu.js} +2 -2
  9. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
  10. package/dist/_chunks/{en-gcJJ5htG.js → en-HrREghh3.js} +11 -3
  11. package/dist/_chunks/en-HrREghh3.js.map +1 -0
  12. package/dist/_chunks/{en-WuuhP6Bn.mjs → en-ltT1TlKQ.mjs} +11 -3
  13. package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
  14. package/dist/_chunks/{index-fP3qoWZ4.js → index-CVO0Rqdm.js} +320 -18
  15. package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
  16. package/dist/_chunks/{index-AECgcaDa.mjs → index-PiOGBETy.mjs} +325 -23
  17. package/dist/_chunks/index-PiOGBETy.mjs.map +1 -0
  18. package/dist/admin/index.js +1 -1
  19. package/dist/admin/index.mjs +1 -1
  20. package/dist/server/index.js +154 -48
  21. package/dist/server/index.js.map +1 -1
  22. package/dist/server/index.mjs +154 -48
  23. package/dist/server/index.mjs.map +1 -1
  24. package/package.json +12 -12
  25. package/dist/_chunks/App-bpzO2Ljh.mjs.map +0 -1
  26. package/dist/_chunks/App-p8aKBitd.js.map +0 -1
  27. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +0 -1
  28. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +0 -1
  29. package/dist/_chunks/en-WuuhP6Bn.mjs.map +0 -1
  30. package/dist/_chunks/en-gcJJ5htG.js.map +0 -1
  31. package/dist/_chunks/index-AECgcaDa.mjs.map +0 -1
  32. package/dist/_chunks/index-fP3qoWZ4.js.map +0 -1
@@ -211,13 +211,16 @@ async function disableContentTypeLocalized({ oldContentTypes, contentTypes: cont
211
211
  if (!oldContentTypes) {
212
212
  return;
213
213
  }
214
+ const i18nPlugin = strapi.plugin("i18n");
215
+ if (!i18nPlugin) {
216
+ return;
217
+ }
214
218
  for (const uid in contentTypes2) {
215
219
  if (!oldContentTypes[uid]) {
216
220
  continue;
217
221
  }
218
222
  const oldContentType = oldContentTypes[uid];
219
223
  const contentType = contentTypes2[uid];
220
- const i18nPlugin = strapi.plugin("i18n");
221
224
  const { isLocalizedContentType } = i18nPlugin.service("content-types");
222
225
  if (isLocalizedContentType(oldContentType) && !isLocalizedContentType(contentType)) {
223
226
  await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
@@ -230,13 +233,16 @@ async function enableContentTypeLocalized({ oldContentTypes, contentTypes: conte
230
233
  if (!oldContentTypes) {
231
234
  return;
232
235
  }
236
+ const i18nPlugin = strapi.plugin("i18n");
237
+ if (!i18nPlugin) {
238
+ return;
239
+ }
233
240
  for (const uid in contentTypes2) {
234
241
  if (!oldContentTypes[uid]) {
235
242
  continue;
236
243
  }
237
244
  const oldContentType = oldContentTypes[uid];
238
245
  const contentType = contentTypes2[uid];
239
- const i18nPlugin = strapi.plugin("i18n");
240
246
  const { isLocalizedContentType } = i18nPlugin.service("content-types");
241
247
  const { getDefaultLocale } = i18nPlugin.service("locales");
242
248
  if (!isLocalizedContentType(oldContentType) && isLocalizedContentType(contentType)) {
@@ -383,27 +389,23 @@ const bootstrap = async ({ strapi: strapi2 }) => {
383
389
  }
384
390
  }
385
391
  });
386
- if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
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
- });
396
- }
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
+ });
397
401
  }
398
402
  };
399
403
  const destroy = async ({ strapi: strapi2 }) => {
400
- if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
401
- const scheduledJobs = getService("scheduling", {
402
- strapi: strapi2
403
- }).getAll();
404
- for (const [, job] of scheduledJobs) {
405
- job.cancel();
406
- }
404
+ const scheduledJobs = getService("scheduling", {
405
+ strapi: strapi2
406
+ }).getAll();
407
+ for (const [, job] of scheduledJobs) {
408
+ job.cancel();
407
409
  }
408
410
  };
409
411
  const schema$1 = {
@@ -635,7 +637,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
635
637
  status: "empty"
636
638
  }
637
639
  });
638
- if (strapi2.features.future.isEnabled("contentReleasesScheduling") && releaseWithCreatorFields.scheduledAt) {
640
+ if (releaseWithCreatorFields.scheduledAt) {
639
641
  const schedulingService = getService("scheduling", { strapi: strapi2 });
640
642
  await schedulingService.set(release2.id, release2.scheduledAt);
641
643
  }
@@ -659,12 +661,18 @@ const createReleaseService = ({ strapi: strapi2 }) => {
659
661
  }
660
662
  });
661
663
  },
662
- async findManyWithContentTypeEntryAttached(contentTypeUid, entryId) {
664
+ async findManyWithContentTypeEntryAttached(contentTypeUid, entriesIds) {
665
+ let entries = entriesIds;
666
+ if (!Array.isArray(entriesIds)) {
667
+ entries = [entriesIds];
668
+ }
663
669
  const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
664
670
  where: {
665
671
  actions: {
666
672
  target_type: contentTypeUid,
667
- target_id: entryId
673
+ target_id: {
674
+ $in: entries
675
+ }
668
676
  },
669
677
  releasedAt: {
670
678
  $null: true
@@ -675,18 +683,25 @@ const createReleaseService = ({ strapi: strapi2 }) => {
675
683
  actions: {
676
684
  where: {
677
685
  target_type: contentTypeUid,
678
- target_id: entryId
686
+ target_id: {
687
+ $in: entries
688
+ }
689
+ },
690
+ populate: {
691
+ entry: {
692
+ select: ["id"]
693
+ }
679
694
  }
680
695
  }
681
696
  }
682
697
  });
683
698
  return releases.map((release2) => {
684
699
  if (release2.actions?.length) {
685
- const [actionForEntry] = release2.actions;
700
+ const actionsForEntry = release2.actions;
686
701
  delete release2.actions;
687
702
  return {
688
703
  ...release2,
689
- action: actionForEntry
704
+ actions: actionsForEntry
690
705
  };
691
706
  }
692
707
  return release2;
@@ -760,13 +775,11 @@ const createReleaseService = ({ strapi: strapi2 }) => {
760
775
  // @ts-expect-error see above
761
776
  data: releaseWithCreatorFields
762
777
  });
763
- if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
764
- const schedulingService = getService("scheduling", { strapi: strapi2 });
765
- if (releaseData.scheduledAt) {
766
- await schedulingService.set(id, releaseData.scheduledAt);
767
- } else if (release2.scheduledAt) {
768
- schedulingService.cancel(id);
769
- }
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);
770
783
  }
771
784
  this.updateReleaseStatus(id);
772
785
  strapi2.telemetry.send("didUpdateContentRelease");
@@ -932,7 +945,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
932
945
  });
933
946
  await strapi2.entityService.delete(RELEASE_MODEL_UID, releaseId);
934
947
  });
935
- if (strapi2.features.future.isEnabled("contentReleasesScheduling") && release2.scheduledAt) {
948
+ if (release2.scheduledAt) {
936
949
  const schedulingService = getService("scheduling", { strapi: strapi2 });
937
950
  await schedulingService.cancel(release2.id);
938
951
  }
@@ -981,21 +994,17 @@ const createReleaseService = ({ strapi: strapi2 }) => {
981
994
  releasedAt: /* @__PURE__ */ new Date()
982
995
  }
983
996
  });
984
- if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
985
- dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
986
- isPublished: true,
987
- release: release22
988
- });
989
- }
997
+ dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
998
+ isPublished: true,
999
+ release: release22
1000
+ });
990
1001
  strapi2.telemetry.send("didPublishContentRelease");
991
1002
  return { release: release22, error: null };
992
1003
  } catch (error2) {
993
- if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
994
- dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
995
- isPublished: false,
996
- error: error2
997
- });
998
- }
1004
+ dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
1005
+ isPublished: false,
1006
+ error: error2
1007
+ });
999
1008
  await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).update({
1000
1009
  status: "failed"
1001
1010
  }).transacting(trx).execute();
@@ -1095,6 +1104,12 @@ const createReleaseService = ({ strapi: strapi2 }) => {
1095
1104
  }
1096
1105
  };
1097
1106
  };
1107
+ class AlreadyOnReleaseError extends errors.ApplicationError {
1108
+ constructor(message) {
1109
+ super(message);
1110
+ this.name = "AlreadyOnReleaseError";
1111
+ }
1112
+ }
1098
1113
  const createReleaseValidationService = ({ strapi: strapi2 }) => ({
1099
1114
  async validateUniqueEntry(releaseId, releaseActionArgs) {
1100
1115
  const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
@@ -1107,7 +1122,7 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
1107
1122
  (action) => Number(action.entry.id) === Number(releaseActionArgs.entry.id) && action.contentType === releaseActionArgs.entry.contentType
1108
1123
  );
1109
1124
  if (isEntryInRelease) {
1110
- throw new errors.ValidationError(
1125
+ throw new AlreadyOnReleaseError(
1111
1126
  `Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
1112
1127
  );
1113
1128
  }
@@ -1215,7 +1230,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
1215
1230
  const services = {
1216
1231
  release: createReleaseService,
1217
1232
  "release-validation": createReleaseValidationService,
1218
- ...strapi.features.future.isEnabled("contentReleasesScheduling") ? { scheduling: createSchedulingService } : {}
1233
+ scheduling: createSchedulingService
1219
1234
  };
1220
1235
  const RELEASE_SCHEMA = yup.object().shape({
1221
1236
  name: yup.string().trim().required(),
@@ -1302,6 +1317,33 @@ const releaseController = {
1302
1317
  };
1303
1318
  ctx.body = { data };
1304
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
+ },
1305
1347
  async create(ctx) {
1306
1348
  const user = ctx.state.user;
1307
1349
  const releaseArgs = ctx.request.body;
@@ -1391,6 +1433,38 @@ const releaseActionController = {
1391
1433
  data: releaseAction2
1392
1434
  };
1393
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
+ },
1394
1468
  async findMany(ctx) {
1395
1469
  const releaseId = ctx.params.releaseId;
1396
1470
  const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
@@ -1459,6 +1533,22 @@ const controllers = { release: releaseController, "release-action": releaseActio
1459
1533
  const release = {
1460
1534
  type: "admin",
1461
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
+ },
1462
1552
  {
1463
1553
  method: "POST",
1464
1554
  path: "/",
@@ -1576,6 +1666,22 @@ const releaseAction = {
1576
1666
  ]
1577
1667
  }
1578
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
+ },
1579
1685
  {
1580
1686
  method: "GET",
1581
1687
  path: "/:releaseId/actions",