@strapi/content-releases 0.0.0-experimental.e47108ccbbc4ad1bfaf4526fa6b70d6ace1ca7a9 → 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813

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 (110) hide show
  1. package/dist/_chunks/{App-XbK-TdJn.mjs → App-BsUSTHVD.mjs} +241 -210
  2. package/dist/_chunks/App-BsUSTHVD.mjs.map +1 -0
  3. package/dist/_chunks/{App-ftICpqDz.js → App-CXRpb2hi.js} +256 -225
  4. package/dist/_chunks/App-CXRpb2hi.js.map +1 -0
  5. package/dist/_chunks/{PurchaseContentReleases-bpIYXOfu.js → PurchaseContentReleases-Be3acS2L.js} +7 -6
  6. package/dist/_chunks/PurchaseContentReleases-Be3acS2L.js.map +1 -0
  7. package/dist/_chunks/{PurchaseContentReleases-3tRbmbY3.mjs → PurchaseContentReleases-_MxP6-Dt.mjs} +8 -7
  8. package/dist/_chunks/PurchaseContentReleases-_MxP6-Dt.mjs.map +1 -0
  9. package/dist/_chunks/{en-pOJ6G5fC.mjs → en-B9Ur3VsE.mjs} +10 -1
  10. package/dist/_chunks/en-B9Ur3VsE.mjs.map +1 -0
  11. package/dist/_chunks/{en-4CUzVH2g.js → en-DtFJ5ViE.js} +10 -1
  12. package/dist/_chunks/en-DtFJ5ViE.js.map +1 -0
  13. package/dist/_chunks/{index-RYVGXFeL.js → index-B6-lic1Q.js} +340 -113
  14. package/dist/_chunks/index-B6-lic1Q.js.map +1 -0
  15. package/dist/_chunks/{index-8LrruHqK.mjs → index-DJLIZdZv.mjs} +339 -112
  16. package/dist/_chunks/index-DJLIZdZv.mjs.map +1 -0
  17. package/dist/admin/index.js +1 -15
  18. package/dist/admin/index.js.map +1 -1
  19. package/dist/admin/index.mjs +2 -16
  20. package/dist/admin/index.mjs.map +1 -1
  21. package/dist/admin/src/components/CMReleasesContainer.d.ts +22 -0
  22. package/dist/admin/src/components/RelativeTime.d.ts +28 -0
  23. package/dist/admin/src/components/ReleaseAction.d.ts +3 -0
  24. package/dist/admin/src/components/ReleaseActionMenu.d.ts +26 -0
  25. package/dist/admin/src/components/ReleaseActionOptions.d.ts +9 -0
  26. package/dist/admin/src/components/ReleaseListCell.d.ts +0 -0
  27. package/dist/admin/src/components/ReleaseModal.d.ts +16 -0
  28. package/dist/admin/src/constants.d.ts +58 -0
  29. package/dist/admin/src/index.d.ts +3 -0
  30. package/dist/admin/src/pages/App.d.ts +1 -0
  31. package/dist/admin/src/pages/PurchaseContentReleases.d.ts +2 -0
  32. package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +2 -0
  33. package/dist/admin/src/pages/ReleasesPage.d.ts +8 -0
  34. package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +181 -0
  35. package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +39 -0
  36. package/dist/admin/src/pluginId.d.ts +1 -0
  37. package/dist/admin/src/services/axios.d.ts +29 -0
  38. package/dist/admin/src/services/release.d.ts +429 -0
  39. package/dist/admin/src/store/hooks.d.ts +7 -0
  40. package/dist/admin/src/utils/prefixPluginTranslations.d.ts +3 -0
  41. package/dist/admin/src/utils/time.d.ts +1 -0
  42. package/dist/server/index.js +152 -93
  43. package/dist/server/index.js.map +1 -1
  44. package/dist/server/index.mjs +153 -93
  45. package/dist/server/index.mjs.map +1 -1
  46. package/dist/server/src/bootstrap.d.ts +5 -0
  47. package/dist/server/src/bootstrap.d.ts.map +1 -0
  48. package/dist/server/src/constants.d.ts +12 -0
  49. package/dist/server/src/constants.d.ts.map +1 -0
  50. package/dist/server/src/content-types/index.d.ts +99 -0
  51. package/dist/server/src/content-types/index.d.ts.map +1 -0
  52. package/dist/server/src/content-types/release/index.d.ts +48 -0
  53. package/dist/server/src/content-types/release/index.d.ts.map +1 -0
  54. package/dist/server/src/content-types/release/schema.d.ts +47 -0
  55. package/dist/server/src/content-types/release/schema.d.ts.map +1 -0
  56. package/dist/server/src/content-types/release-action/index.d.ts +50 -0
  57. package/dist/server/src/content-types/release-action/index.d.ts.map +1 -0
  58. package/dist/server/src/content-types/release-action/schema.d.ts +49 -0
  59. package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -0
  60. package/dist/server/src/controllers/index.d.ts +20 -0
  61. package/dist/server/src/controllers/index.d.ts.map +1 -0
  62. package/dist/server/src/controllers/release-action.d.ts +10 -0
  63. package/dist/server/src/controllers/release-action.d.ts.map +1 -0
  64. package/dist/server/src/controllers/release.d.ts +12 -0
  65. package/dist/server/src/controllers/release.d.ts.map +1 -0
  66. package/dist/server/src/controllers/validation/release-action.d.ts +8 -0
  67. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -0
  68. package/dist/server/src/controllers/validation/release.d.ts +2 -0
  69. package/dist/server/src/controllers/validation/release.d.ts.map +1 -0
  70. package/dist/server/src/destroy.d.ts +5 -0
  71. package/dist/server/src/destroy.d.ts.map +1 -0
  72. package/dist/server/src/index.d.ts +2096 -0
  73. package/dist/server/src/index.d.ts.map +1 -0
  74. package/dist/server/src/migrations/index.d.ts +13 -0
  75. package/dist/server/src/migrations/index.d.ts.map +1 -0
  76. package/dist/server/src/register.d.ts +5 -0
  77. package/dist/server/src/register.d.ts.map +1 -0
  78. package/dist/server/src/routes/index.d.ts +35 -0
  79. package/dist/server/src/routes/index.d.ts.map +1 -0
  80. package/dist/server/src/routes/release-action.d.ts +18 -0
  81. package/dist/server/src/routes/release-action.d.ts.map +1 -0
  82. package/dist/server/src/routes/release.d.ts +18 -0
  83. package/dist/server/src/routes/release.d.ts.map +1 -0
  84. package/dist/server/src/services/index.d.ts +1826 -0
  85. package/dist/server/src/services/index.d.ts.map +1 -0
  86. package/dist/server/src/services/release.d.ts +66 -0
  87. package/dist/server/src/services/release.d.ts.map +1 -0
  88. package/dist/server/src/services/scheduling.d.ts +18 -0
  89. package/dist/server/src/services/scheduling.d.ts.map +1 -0
  90. package/dist/server/src/services/validation.d.ts +18 -0
  91. package/dist/server/src/services/validation.d.ts.map +1 -0
  92. package/dist/server/src/utils/index.d.ts +14 -0
  93. package/dist/server/src/utils/index.d.ts.map +1 -0
  94. package/dist/shared/contracts/release-actions.d.ts +131 -0
  95. package/dist/shared/contracts/release-actions.d.ts.map +1 -0
  96. package/dist/shared/contracts/releases.d.ts +182 -0
  97. package/dist/shared/contracts/releases.d.ts.map +1 -0
  98. package/dist/shared/types.d.ts +24 -0
  99. package/dist/shared/types.d.ts.map +1 -0
  100. package/dist/shared/validation-schemas.d.ts +2 -0
  101. package/dist/shared/validation-schemas.d.ts.map +1 -0
  102. package/package.json +26 -31
  103. package/dist/_chunks/App-XbK-TdJn.mjs.map +0 -1
  104. package/dist/_chunks/App-ftICpqDz.js.map +0 -1
  105. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +0 -1
  106. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +0 -1
  107. package/dist/_chunks/en-4CUzVH2g.js.map +0 -1
  108. package/dist/_chunks/en-pOJ6G5fC.mjs.map +0 -1
  109. package/dist/_chunks/index-8LrruHqK.mjs.map +0 -1
  110. package/dist/_chunks/index-RYVGXFeL.js.map +0 -1
@@ -1,8 +1,7 @@
1
- import { contentTypes as contentTypes$1, mapAsync, setCreatorFields, errors, validateYupSchema, yup as yup$1 } from "@strapi/utils";
1
+ import { contentTypes as contentTypes$1, async, setCreatorFields, errors, validateYupSchema, yup as yup$1 } from "@strapi/utils";
2
2
  import isEqual from "lodash/isEqual";
3
3
  import { difference, keys } from "lodash";
4
4
  import _ from "lodash/fp";
5
- import EE from "@strapi/strapi/dist/utils/ee";
6
5
  import { scheduleJob } from "node-schedule";
7
6
  import * as yup from "yup";
8
7
  const RELEASE_MODEL_UID = "plugin::content-releases.release";
@@ -54,16 +53,19 @@ const ACTIONS = [
54
53
  const ALLOWED_WEBHOOK_EVENTS = {
55
54
  RELEASES_PUBLISH: "releases.publish"
56
55
  };
57
- const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
56
+ const getService = (name, { strapi: strapi2 }) => {
58
57
  return strapi2.plugin("content-releases").service(name);
59
58
  };
60
- const getPopulatedEntry = async (contentTypeUid, entryId, { strapi: strapi2 } = { strapi: global.strapi }) => {
59
+ const getPopulatedEntry = async (contentTypeUid, entryId, { strapi: strapi2 }) => {
61
60
  const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
62
61
  const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
63
- const entry = await strapi2.entityService.findOne(contentTypeUid, entryId, { populate });
62
+ const entry = await strapi2.db.query(contentTypeUid).findOne({
63
+ where: { id: entryId },
64
+ populate
65
+ });
64
66
  return entry;
65
67
  };
66
- const getEntryValidStatus = async (contentTypeUid, entry, { strapi: strapi2 } = { strapi: global.strapi }) => {
68
+ const getEntryValidStatus = async (contentTypeUid, entry, { strapi: strapi2 }) => {
67
69
  try {
68
70
  await strapi2.entityValidator.validateEntityCreation(
69
71
  strapi2.getModel(contentTypeUid),
@@ -98,7 +100,7 @@ async function deleteActionsOnDisableDraftAndPublish({
98
100
  async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes: contentTypes2 }) {
99
101
  const deletedContentTypes = difference(keys(oldContentTypes), keys(contentTypes2)) ?? [];
100
102
  if (deletedContentTypes.length) {
101
- await mapAsync(deletedContentTypes, async (deletedContentTypeUID) => {
103
+ await async.map(deletedContentTypes, async (deletedContentTypeUID) => {
102
104
  return strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: deletedContentTypeUID }).execute();
103
105
  });
104
106
  }
@@ -117,7 +119,7 @@ async function migrateIsValidAndStatusReleases() {
117
119
  }
118
120
  }
119
121
  });
120
- mapAsync(releasesWithoutStatus, async (release2) => {
122
+ async.map(releasesWithoutStatus, async (release2) => {
121
123
  const actions = release2.actions;
122
124
  const notValidatedActions = actions.filter((action) => action.isEntryValid === null);
123
125
  for (const action of notValidatedActions) {
@@ -148,7 +150,7 @@ async function migrateIsValidAndStatusReleases() {
148
150
  }
149
151
  }
150
152
  });
151
- mapAsync(publishedReleases, async (release2) => {
153
+ async.map(publishedReleases, async (release2) => {
152
154
  return strapi.db.query(RELEASE_MODEL_UID).update({
153
155
  where: {
154
156
  id: release2.id
@@ -165,7 +167,7 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
165
167
  (uid) => oldContentTypes[uid]?.options?.draftAndPublish
166
168
  );
167
169
  const releasesAffected = /* @__PURE__ */ new Set();
168
- mapAsync(contentTypesWithDraftAndPublish, async (contentTypeUID) => {
170
+ async.map(contentTypesWithDraftAndPublish, async (contentTypeUID) => {
169
171
  const oldContentType = oldContentTypes[contentTypeUID];
170
172
  const contentType = contentTypes2[contentTypeUID];
171
173
  if (!isEqual(oldContentType?.attributes, contentType?.attributes)) {
@@ -178,7 +180,7 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
178
180
  release: true
179
181
  }
180
182
  });
181
- await mapAsync(actions, async (action) => {
183
+ await async.map(actions, async (action) => {
182
184
  if (action.entry && action.release) {
183
185
  const populatedEntry = await getPopulatedEntry(contentTypeUID, action.entry.id, {
184
186
  strapi
@@ -201,7 +203,7 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
201
203
  });
202
204
  }
203
205
  }).then(() => {
204
- mapAsync(releasesAffected, async (releaseId) => {
206
+ async.map(releasesAffected, async (releaseId) => {
205
207
  return getService("release", { strapi }).updateReleaseStatus(releaseId);
206
208
  });
207
209
  });
@@ -211,13 +213,16 @@ async function disableContentTypeLocalized({ oldContentTypes, contentTypes: cont
211
213
  if (!oldContentTypes) {
212
214
  return;
213
215
  }
216
+ const i18nPlugin = strapi.plugin("i18n");
217
+ if (!i18nPlugin) {
218
+ return;
219
+ }
214
220
  for (const uid in contentTypes2) {
215
221
  if (!oldContentTypes[uid]) {
216
222
  continue;
217
223
  }
218
224
  const oldContentType = oldContentTypes[uid];
219
225
  const contentType = contentTypes2[uid];
220
- const i18nPlugin = strapi.plugin("i18n");
221
226
  const { isLocalizedContentType } = i18nPlugin.service("content-types");
222
227
  if (isLocalizedContentType(oldContentType) && !isLocalizedContentType(contentType)) {
223
228
  await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
@@ -230,13 +235,16 @@ async function enableContentTypeLocalized({ oldContentTypes, contentTypes: conte
230
235
  if (!oldContentTypes) {
231
236
  return;
232
237
  }
238
+ const i18nPlugin = strapi.plugin("i18n");
239
+ if (!i18nPlugin) {
240
+ return;
241
+ }
233
242
  for (const uid in contentTypes2) {
234
243
  if (!oldContentTypes[uid]) {
235
244
  continue;
236
245
  }
237
246
  const oldContentType = oldContentTypes[uid];
238
247
  const contentType = contentTypes2[uid];
239
- const i18nPlugin = strapi.plugin("i18n");
240
248
  const { isLocalizedContentType } = i18nPlugin.service("content-types");
241
249
  const { getDefaultLocale } = i18nPlugin.service("locales");
242
250
  if (!isLocalizedContentType(oldContentType) && isLocalizedContentType(contentType)) {
@@ -247,11 +255,10 @@ async function enableContentTypeLocalized({ oldContentTypes, contentTypes: conte
247
255
  }
248
256
  }
249
257
  }
250
- const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
251
258
  const register = async ({ strapi: strapi2 }) => {
252
- if (features$2.isEnabled("cms-content-releases")) {
253
- await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
254
- strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish).register(disableContentTypeLocalized);
259
+ if (strapi2.ee.features.isEnabled("cms-content-releases")) {
260
+ await strapi2.service("admin::permission").actionProvider.registerMany(ACTIONS);
261
+ strapi2.hook("strapi::content-types.beforeSync").register(disableContentTypeLocalized).register(deleteActionsOnDisableDraftAndPublish);
255
262
  strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(enableContentTypeLocalized).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
256
263
  }
257
264
  if (strapi2.plugin("graphql")) {
@@ -260,9 +267,8 @@ const register = async ({ strapi: strapi2 }) => {
260
267
  graphqlExtensionService.shadowCRUD(RELEASE_ACTION_MODEL_UID).disable();
261
268
  }
262
269
  };
263
- const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
264
270
  const bootstrap = async ({ strapi: strapi2 }) => {
265
- if (features$1.isEnabled("cms-content-releases")) {
271
+ if (strapi2.ee.features.isEnabled("cms-content-releases")) {
266
272
  const contentTypesWithDraftAndPublish = Object.keys(strapi2.contentTypes).filter(
267
273
  (uid) => strapi2.contentTypes[uid]?.options?.draftAndPublish
268
274
  );
@@ -321,9 +327,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
321
327
  actions: {
322
328
  target_type: model.uid,
323
329
  target_id: {
324
- $in: entriesToDelete.map(
325
- (entry) => entry.id
326
- )
330
+ $in: entriesToDelete.map((entry) => entry.id)
327
331
  }
328
332
  }
329
333
  }
@@ -350,13 +354,9 @@ const bootstrap = async ({ strapi: strapi2 }) => {
350
354
  try {
351
355
  const { model, result } = event;
352
356
  if (model.kind === "collectionType" && model.options?.draftAndPublish) {
353
- const isEntryValid = await getEntryValidStatus(
354
- model.uid,
355
- result,
356
- {
357
- strapi: strapi2
358
- }
359
- );
357
+ const isEntryValid = await getEntryValidStatus(model.uid, result, {
358
+ strapi: strapi2
359
+ });
360
360
  await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
361
361
  where: {
362
362
  target_type: model.uid,
@@ -390,7 +390,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
390
390
  throw err;
391
391
  });
392
392
  Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
393
- strapi2.webhookStore.addAllowedEvent(key, value);
393
+ strapi2.get("webhookStore").addAllowedEvent(key, value);
394
394
  });
395
395
  }
396
396
  };
@@ -625,7 +625,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
625
625
  validateUniqueNameForPendingRelease(releaseWithCreatorFields.name),
626
626
  validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
627
627
  ]);
628
- const release2 = await strapi2.entityService.create(RELEASE_MODEL_UID, {
628
+ const release2 = await strapi2.db.query(RELEASE_MODEL_UID).create({
629
629
  data: {
630
630
  ...releaseWithCreatorFields,
631
631
  status: "empty"
@@ -639,28 +639,36 @@ const createReleaseService = ({ strapi: strapi2 }) => {
639
639
  return release2;
640
640
  },
641
641
  async findOne(id, query = {}) {
642
- const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, id, {
643
- ...query
642
+ const dbQuery = strapi2.get("query-params").transform(RELEASE_MODEL_UID, query);
643
+ const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
644
+ ...dbQuery,
645
+ where: { id }
644
646
  });
645
647
  return release2;
646
648
  },
647
649
  findPage(query) {
648
- return strapi2.entityService.findPage(RELEASE_MODEL_UID, {
649
- ...query,
650
+ const dbQuery = strapi2.get("query-params").transform(RELEASE_MODEL_UID, query ?? {});
651
+ return strapi2.db.query(RELEASE_MODEL_UID).findPage({
652
+ ...dbQuery,
650
653
  populate: {
651
654
  actions: {
652
- // @ts-expect-error Ignore missing properties
653
655
  count: true
654
656
  }
655
657
  }
656
658
  });
657
659
  },
658
- async findManyWithContentTypeEntryAttached(contentTypeUid, entryId) {
660
+ async findManyWithContentTypeEntryAttached(contentTypeUid, entriesIds) {
661
+ let entries = entriesIds;
662
+ if (!Array.isArray(entriesIds)) {
663
+ entries = [entriesIds];
664
+ }
659
665
  const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
660
666
  where: {
661
667
  actions: {
662
668
  target_type: contentTypeUid,
663
- target_id: entryId
669
+ target_id: {
670
+ $in: entries
671
+ }
664
672
  },
665
673
  releasedAt: {
666
674
  $null: true
@@ -671,18 +679,25 @@ const createReleaseService = ({ strapi: strapi2 }) => {
671
679
  actions: {
672
680
  where: {
673
681
  target_type: contentTypeUid,
674
- target_id: entryId
682
+ target_id: {
683
+ $in: entries
684
+ }
685
+ },
686
+ populate: {
687
+ entry: {
688
+ select: ["id"]
689
+ }
675
690
  }
676
691
  }
677
692
  }
678
693
  });
679
694
  return releases.map((release2) => {
680
695
  if (release2.actions?.length) {
681
- const [actionForEntry] = release2.actions;
696
+ const actionsForEntry = release2.actions;
682
697
  delete release2.actions;
683
698
  return {
684
699
  ...release2,
685
- action: actionForEntry
700
+ actions: actionsForEntry
686
701
  };
687
702
  }
688
703
  return release2;
@@ -741,19 +756,15 @@ const createReleaseService = ({ strapi: strapi2 }) => {
741
756
  validateUniqueNameForPendingRelease(releaseWithCreatorFields.name, id),
742
757
  validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
743
758
  ]);
744
- const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, id);
759
+ const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id } });
745
760
  if (!release2) {
746
761
  throw new errors.NotFoundError(`No release found for id ${id}`);
747
762
  }
748
763
  if (release2.releasedAt) {
749
764
  throw new errors.ValidationError("Release already published");
750
765
  }
751
- const updatedRelease = await strapi2.entityService.update(RELEASE_MODEL_UID, id, {
752
- /*
753
- * The type returned from the entity service: Partial<Input<"plugin::content-releases.release">>
754
- * is not compatible with the type we are passing here: UpdateRelease.Request['body']
755
- */
756
- // @ts-expect-error see above
766
+ const updatedRelease = await strapi2.db.query(RELEASE_MODEL_UID).update({
767
+ where: { id },
757
768
  data: releaseWithCreatorFields
758
769
  });
759
770
  const schedulingService = getService("scheduling", { strapi: strapi2 });
@@ -774,7 +785,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
774
785
  validateEntryContentType(action.entry.contentType),
775
786
  validateUniqueEntry(releaseId, action)
776
787
  ]);
777
- const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId);
788
+ const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id: releaseId } });
778
789
  if (!release2) {
779
790
  throw new errors.NotFoundError(`No release found for id ${releaseId}`);
780
791
  }
@@ -784,7 +795,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
784
795
  const { entry, type } = action;
785
796
  const populatedEntry = await getPopulatedEntry(entry.contentType, entry.id, { strapi: strapi2 });
786
797
  const isEntryValid = await getEntryValidStatus(entry.contentType, populatedEntry, { strapi: strapi2 });
787
- const releaseAction2 = await strapi2.entityService.create(RELEASE_ACTION_MODEL_UID, {
798
+ const releaseAction2 = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).create({
788
799
  data: {
789
800
  type,
790
801
  contentType: entry.contentType,
@@ -797,32 +808,35 @@ const createReleaseService = ({ strapi: strapi2 }) => {
797
808
  },
798
809
  release: releaseId
799
810
  },
800
- populate: { release: { fields: ["id"] }, entry: { fields: ["id"] } }
811
+ populate: { release: { select: ["id"] }, entry: { select: ["id"] } }
801
812
  });
802
813
  this.updateReleaseStatus(releaseId);
803
814
  return releaseAction2;
804
815
  },
805
816
  async findActions(releaseId, query) {
806
- const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
807
- fields: ["id"]
817
+ const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
818
+ where: { id: releaseId },
819
+ select: ["id"]
808
820
  });
809
821
  if (!release2) {
810
822
  throw new errors.NotFoundError(`No release found for id ${releaseId}`);
811
823
  }
812
- return strapi2.entityService.findPage(RELEASE_ACTION_MODEL_UID, {
813
- ...query,
824
+ const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
825
+ return strapi2.db.query(RELEASE_ACTION_MODEL_UID).findPage({
826
+ ...dbQuery,
814
827
  populate: {
815
828
  entry: {
816
829
  populate: "*"
817
830
  }
818
831
  },
819
- filters: {
832
+ where: {
820
833
  release: releaseId
821
834
  }
822
835
  });
823
836
  },
824
837
  async countActions(query) {
825
- return strapi2.entityService.count(RELEASE_ACTION_MODEL_UID, query);
838
+ const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
839
+ return strapi2.db.query(RELEASE_ACTION_MODEL_UID).count(dbQuery);
826
840
  },
827
841
  async groupActions(actions, groupBy) {
828
842
  const contentTypeUids = actions.reduce((acc, action) => {
@@ -831,9 +845,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
831
845
  }
832
846
  return acc;
833
847
  }, []);
834
- const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(
835
- contentTypeUids
836
- );
848
+ const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(contentTypeUids);
837
849
  const allLocalesDictionary = await this.getLocalesDataForActions();
838
850
  const formattedData = actions.map((action) => {
839
851
  const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
@@ -903,10 +915,11 @@ const createReleaseService = ({ strapi: strapi2 }) => {
903
915
  return componentsMap;
904
916
  },
905
917
  async delete(releaseId) {
906
- const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
918
+ const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
919
+ where: { id: releaseId },
907
920
  populate: {
908
921
  actions: {
909
- fields: ["id"]
922
+ select: ["id"]
910
923
  }
911
924
  }
912
925
  });
@@ -924,7 +937,11 @@ const createReleaseService = ({ strapi: strapi2 }) => {
924
937
  }
925
938
  }
926
939
  });
927
- await strapi2.entityService.delete(RELEASE_MODEL_UID, releaseId);
940
+ await strapi2.db.query(RELEASE_MODEL_UID).delete({
941
+ where: {
942
+ id: releaseId
943
+ }
944
+ });
928
945
  });
929
946
  if (release2.scheduledAt) {
930
947
  const schedulingService = getService("scheduling", { strapi: strapi2 });
@@ -950,9 +967,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
950
967
  }
951
968
  try {
952
969
  strapi2.log.info(`[Content Releases] Starting to publish release ${lockedRelease.name}`);
953
- const { collectionTypeActions, singleTypeActions } = await getFormattedActions(
954
- releaseId
955
- );
970
+ const { collectionTypeActions, singleTypeActions } = await getFormattedActions(releaseId);
956
971
  await strapi2.db.transaction(async () => {
957
972
  for (const { uid, action, id } of singleTypeActions) {
958
973
  await publishSingleTypeAction(uid, action, id);
@@ -995,7 +1010,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
995
1010
  };
996
1011
  }
997
1012
  });
998
- if (error) {
1013
+ if (error instanceof Error) {
999
1014
  throw error;
1000
1015
  }
1001
1016
  return release2;
@@ -1093,8 +1108,11 @@ class AlreadyOnReleaseError extends errors.ApplicationError {
1093
1108
  }
1094
1109
  const createReleaseValidationService = ({ strapi: strapi2 }) => ({
1095
1110
  async validateUniqueEntry(releaseId, releaseActionArgs) {
1096
- const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
1097
- populate: { actions: { populate: { entry: { fields: ["id"] } } } }
1111
+ const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
1112
+ where: {
1113
+ id: releaseId
1114
+ },
1115
+ populate: { actions: { populate: { entry: { select: ["id"] } } } }
1098
1116
  });
1099
1117
  if (!release2) {
1100
1118
  throw new errors.NotFoundError(`No release found for id ${releaseId}`);
@@ -1120,10 +1138,8 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
1120
1138
  }
1121
1139
  },
1122
1140
  async validatePendingReleasesLimit() {
1123
- const maximumPendingReleases = (
1124
- // @ts-expect-error - options is not typed into features
1125
- EE.features.get("cms-content-releases")?.options?.maximumReleases || 3
1126
- );
1141
+ const featureCfg = strapi2.ee.features.get("cms-content-releases");
1142
+ const maximumPendingReleases = typeof featureCfg === "object" && featureCfg?.options?.maximumReleases || 3;
1127
1143
  const [, pendingReleasesCount] = await strapi2.db.query(RELEASE_MODEL_UID).findWithCount({
1128
1144
  filters: {
1129
1145
  releasedAt: {
@@ -1136,8 +1152,8 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
1136
1152
  }
1137
1153
  },
1138
1154
  async validateUniqueNameForPendingRelease(name, id) {
1139
- const pendingReleases = await strapi2.entityService.findMany(RELEASE_MODEL_UID, {
1140
- filters: {
1155
+ const pendingReleases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
1156
+ where: {
1141
1157
  releasedAt: {
1142
1158
  $null: true
1143
1159
  },
@@ -1166,7 +1182,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
1166
1182
  }
1167
1183
  const job = scheduleJob(scheduleDate, async () => {
1168
1184
  try {
1169
- await getService("release").publish(releaseId);
1185
+ await getService("release", { strapi: strapi2 }).publish(releaseId);
1170
1186
  } catch (error) {
1171
1187
  }
1172
1188
  this.cancel(releaseId);
@@ -1236,7 +1252,7 @@ const RELEASE_SCHEMA = yup.object().shape({
1236
1252
  const validateRelease = validateYupSchema(RELEASE_SCHEMA);
1237
1253
  const releaseController = {
1238
1254
  async findMany(ctx) {
1239
- const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
1255
+ const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
1240
1256
  ability: ctx.state.userAbility,
1241
1257
  model: RELEASE_MODEL_UID
1242
1258
  });
@@ -1264,7 +1280,7 @@ const releaseController = {
1264
1280
  }
1265
1281
  };
1266
1282
  });
1267
- const pendingReleasesCount = await strapi.query(RELEASE_MODEL_UID).count({
1283
+ const pendingReleasesCount = await strapi.db.query(RELEASE_MODEL_UID).count({
1268
1284
  where: {
1269
1285
  releasedAt: null
1270
1286
  }
@@ -1286,7 +1302,7 @@ const releaseController = {
1286
1302
  });
1287
1303
  const sanitizedRelease = {
1288
1304
  ...release2,
1289
- createdBy: release2.createdBy ? strapi.admin.services.user.sanitizeUser(release2.createdBy) : null
1305
+ createdBy: release2.createdBy ? strapi.service("admin::user").sanitizeUser(release2.createdBy) : null
1290
1306
  };
1291
1307
  const data = {
1292
1308
  ...sanitizedRelease,
@@ -1298,19 +1314,48 @@ const releaseController = {
1298
1314
  };
1299
1315
  ctx.body = { data };
1300
1316
  },
1317
+ async mapEntriesToReleases(ctx) {
1318
+ const { contentTypeUid, entriesIds } = ctx.query;
1319
+ if (!contentTypeUid || !entriesIds) {
1320
+ throw new errors.ValidationError("Missing required query parameters");
1321
+ }
1322
+ const releaseService = getService("release", { strapi });
1323
+ const releasesWithActions = await releaseService.findManyWithContentTypeEntryAttached(
1324
+ contentTypeUid,
1325
+ entriesIds
1326
+ );
1327
+ const mappedEntriesInReleases = releasesWithActions.reduce(
1328
+ // TODO: Fix for v5 removed mappedEntriedToRelease
1329
+ (acc, release2) => {
1330
+ release2.actions.forEach((action) => {
1331
+ if (!acc[action.entry.id]) {
1332
+ acc[action.entry.id] = [{ id: release2.id, name: release2.name }];
1333
+ } else {
1334
+ acc[action.entry.id].push({ id: release2.id, name: release2.name });
1335
+ }
1336
+ });
1337
+ return acc;
1338
+ },
1339
+ // TODO: Fix for v5 removed mappedEntriedToRelease
1340
+ {}
1341
+ );
1342
+ ctx.body = {
1343
+ data: mappedEntriesInReleases
1344
+ };
1345
+ },
1301
1346
  async create(ctx) {
1302
1347
  const user = ctx.state.user;
1303
1348
  const releaseArgs = ctx.request.body;
1304
1349
  await validateRelease(releaseArgs);
1305
1350
  const releaseService = getService("release", { strapi });
1306
1351
  const release2 = await releaseService.create(releaseArgs, { user });
1307
- const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
1352
+ const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
1308
1353
  ability: ctx.state.userAbility,
1309
1354
  model: RELEASE_MODEL_UID
1310
1355
  });
1311
- ctx.body = {
1356
+ ctx.created({
1312
1357
  data: await permissionsManager.sanitizeOutput(release2)
1313
- };
1358
+ });
1314
1359
  },
1315
1360
  async update(ctx) {
1316
1361
  const user = ctx.state.user;
@@ -1319,7 +1364,7 @@ const releaseController = {
1319
1364
  await validateRelease(releaseArgs);
1320
1365
  const releaseService = getService("release", { strapi });
1321
1366
  const release2 = await releaseService.update(id, releaseArgs, { user });
1322
- const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
1367
+ const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
1323
1368
  ability: ctx.state.userAbility,
1324
1369
  model: RELEASE_MODEL_UID
1325
1370
  });
@@ -1383,9 +1428,9 @@ const releaseActionController = {
1383
1428
  await validateReleaseAction(releaseActionArgs);
1384
1429
  const releaseService = getService("release", { strapi });
1385
1430
  const releaseAction2 = await releaseService.createAction(releaseId, releaseActionArgs);
1386
- ctx.body = {
1431
+ ctx.created({
1387
1432
  data: releaseAction2
1388
- };
1433
+ });
1389
1434
  },
1390
1435
  async createMany(ctx) {
1391
1436
  const releaseId = ctx.params.releaseId;
@@ -1411,17 +1456,17 @@ const releaseActionController = {
1411
1456
  return releaseActions2;
1412
1457
  });
1413
1458
  const newReleaseActions = releaseActions.filter((action) => action !== null);
1414
- ctx.body = {
1459
+ ctx.created({
1415
1460
  data: newReleaseActions,
1416
1461
  meta: {
1417
1462
  entriesAlreadyInRelease: releaseActions.length - newReleaseActions.length,
1418
1463
  totalEntries: releaseActions.length
1419
1464
  }
1420
- };
1465
+ });
1421
1466
  },
1422
1467
  async findMany(ctx) {
1423
1468
  const releaseId = ctx.params.releaseId;
1424
- const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
1469
+ const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
1425
1470
  ability: ctx.state.userAbility,
1426
1471
  model: RELEASE_ACTION_MODEL_UID
1427
1472
  });
@@ -1435,14 +1480,14 @@ const releaseActionController = {
1435
1480
  if (acc[action.contentType]) {
1436
1481
  return acc;
1437
1482
  }
1438
- const contentTypePermissionsManager = strapi.admin.services.permission.createPermissionsManager({
1483
+ const contentTypePermissionsManager = strapi.service("admin::permission").createPermissionsManager({
1439
1484
  ability: ctx.state.userAbility,
1440
1485
  model: action.contentType
1441
1486
  });
1442
1487
  acc[action.contentType] = contentTypePermissionsManager.sanitizeOutput;
1443
1488
  return acc;
1444
1489
  }, {});
1445
- const sanitizedResults = await mapAsync(results, async (action) => ({
1490
+ const sanitizedResults = await async.map(results, async (action) => ({
1446
1491
  ...action,
1447
1492
  entry: await contentTypeOutputSanitizers[action.contentType](action.entry)
1448
1493
  }));
@@ -1487,6 +1532,22 @@ const controllers = { release: releaseController, "release-action": releaseActio
1487
1532
  const release = {
1488
1533
  type: "admin",
1489
1534
  routes: [
1535
+ {
1536
+ method: "GET",
1537
+ path: "/mapEntriesToReleases",
1538
+ handler: "release.mapEntriesToReleases",
1539
+ config: {
1540
+ policies: [
1541
+ "admin::isAuthenticatedAdmin",
1542
+ {
1543
+ name: "admin::hasPermissions",
1544
+ config: {
1545
+ actions: ["plugin::content-releases.read"]
1546
+ }
1547
+ }
1548
+ ]
1549
+ }
1550
+ },
1490
1551
  {
1491
1552
  method: "POST",
1492
1553
  path: "/",
@@ -1674,9 +1735,8 @@ const routes = {
1674
1735
  release,
1675
1736
  "release-action": releaseAction
1676
1737
  };
1677
- const { features } = require("@strapi/strapi/dist/utils/ee");
1678
1738
  const getPlugin = () => {
1679
- if (features.isEnabled("cms-content-releases")) {
1739
+ if (strapi.ee.features.isEnabled("cms-content-releases")) {
1680
1740
  return {
1681
1741
  register,
1682
1742
  bootstrap,