@strapi/content-releases 5.50.2 → 5.51.1

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.
@@ -8,6 +8,7 @@ const createSchedulingService = ({ strapi })=>{
8
8
  const scheduledJobs = new Map();
9
9
  return {
10
10
  async set (releaseId, scheduleDate) {
11
+ const id = String(releaseId); // callers pass both numeric (db row) and string (ctx.params) ids
11
12
  const release = await strapi.db.query(constants.RELEASE_MODEL_UID).findOne({
12
13
  where: {
13
14
  id: releaseId,
@@ -17,7 +18,7 @@ const createSchedulingService = ({ strapi })=>{
17
18
  if (!release) {
18
19
  throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
19
20
  }
20
- const taskName = `publishRelease_${releaseId}`;
21
+ const taskName = `publishRelease_${id}`;
21
22
  strapi.cron.add({
22
23
  [taskName]: {
23
24
  async task () {
@@ -28,16 +29,17 @@ const createSchedulingService = ({ strapi })=>{
28
29
  options: scheduleDate
29
30
  }
30
31
  });
31
- if (scheduledJobs.has(releaseId)) {
32
- this.cancel(releaseId);
32
+ if (scheduledJobs.has(id)) {
33
+ this.cancel(id);
33
34
  }
34
- scheduledJobs.set(releaseId, taskName);
35
+ scheduledJobs.set(id, taskName);
35
36
  return scheduledJobs;
36
37
  },
37
38
  cancel (releaseId) {
38
- if (scheduledJobs.has(releaseId)) {
39
- strapi.cron.remove(scheduledJobs.get(releaseId));
40
- scheduledJobs.delete(releaseId);
39
+ const id = String(releaseId); // normalise to match key from set()
40
+ if (scheduledJobs.has(id)) {
41
+ strapi.cron.remove(scheduledJobs.get(id));
42
+ scheduledJobs.delete(id);
41
43
  }
42
44
  return scheduledJobs;
43
45
  },
@@ -1 +1 @@
1
- {"version":3,"file":"scheduling.js","sources":["../../../server/src/services/scheduling.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { errors } from '@strapi/utils';\nimport { Release } from '../../../shared/contracts/releases';\nimport { getService } from '../utils';\nimport { RELEASE_MODEL_UID } from '../constants';\n\nconst createSchedulingService = ({ strapi }: { strapi: Core.Strapi }) => {\n const scheduledJobs = new Map<Release['id'], string>();\n\n return {\n async set(releaseId: Release['id'], scheduleDate: Date) {\n const release = await strapi.db\n .query(RELEASE_MODEL_UID)\n .findOne({ where: { id: releaseId, releasedAt: null } });\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n const taskName = `publishRelease_${releaseId}`;\n\n strapi.cron.add({\n [taskName]: {\n async task() {\n await getService('release', { strapi }).publish(releaseId);\n },\n options: scheduleDate,\n },\n });\n\n if (scheduledJobs.has(releaseId)) {\n this.cancel(releaseId);\n }\n\n scheduledJobs.set(releaseId, taskName);\n\n return scheduledJobs;\n },\n\n cancel(releaseId: Release['id']) {\n if (scheduledJobs.has(releaseId)) {\n strapi.cron.remove(scheduledJobs.get(releaseId)!);\n scheduledJobs.delete(releaseId);\n }\n\n return scheduledJobs;\n },\n\n getAll() {\n return scheduledJobs;\n },\n\n /**\n * On bootstrap, we can use this function to make sure to sync the scheduled jobs from the database that are not yet released\n * This is useful in case the server was restarted and the scheduled jobs were lost\n * This also could be used to sync different Strapi instances in case of a cluster\n */\n async syncFromDatabase() {\n const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({\n where: {\n scheduledAt: {\n $gte: new Date(),\n },\n releasedAt: null,\n },\n });\n\n for (const release of releases) {\n this.set(release.id, release.scheduledAt);\n }\n\n return scheduledJobs;\n },\n };\n};\n\nexport default createSchedulingService;\n"],"names":["createSchedulingService","strapi","scheduledJobs","Map","set","releaseId","scheduleDate","release","db","query","RELEASE_MODEL_UID","findOne","where","id","releasedAt","errors","NotFoundError","taskName","cron","add","task","getService","publish","options","has","cancel","remove","get","delete","getAll","syncFromDatabase","releases","findMany","scheduledAt","$gte","Date"],"mappings":";;;;;;AAOA,MAAMA,uBAAAA,GAA0B,CAAC,EAAEC,MAAM,EAA2B,GAAA;AAClE,IAAA,MAAMC,gBAAgB,IAAIC,GAAAA,EAAAA;IAE1B,OAAO;QACL,MAAMC,GAAAA,CAAAA,CAAIC,SAAwB,EAAEC,YAAkB,EAAA;YACpD,MAAMC,OAAAA,GAAU,MAAMN,MAAAA,CAAOO,EAAE,CAC5BC,KAAK,CAACC,2BAAAA,CAAAA,CACNC,OAAO,CAAC;gBAAEC,KAAAA,EAAO;oBAAEC,EAAAA,EAAIR,SAAAA;oBAAWS,UAAAA,EAAY;AAAK;AAAE,aAAA,CAAA;AAExD,YAAA,IAAI,CAACP,OAAAA,EAAS;AACZ,gBAAA,MAAM,IAAIQ,YAAAA,CAAOC,aAAa,CAAC,CAAC,wBAAwB,EAAEX,SAAAA,CAAAA,CAAW,CAAA;AACvE,YAAA;AAEA,YAAA,MAAMY,QAAAA,GAAW,CAAC,eAAe,EAAEZ,SAAAA,CAAAA,CAAW;YAE9CJ,MAAAA,CAAOiB,IAAI,CAACC,GAAG,CAAC;AACd,gBAAA,CAACF,WAAW;oBACV,MAAMG,IAAAA,CAAAA,GAAAA;AACJ,wBAAA,MAAMC,iBAAW,SAAA,EAAW;AAAEpB,4BAAAA;AAAO,yBAAA,CAAA,CAAGqB,OAAO,CAACjB,SAAAA,CAAAA;AAClD,oBAAA,CAAA;oBACAkB,OAAAA,EAASjB;AACX;AACF,aAAA,CAAA;YAEA,IAAIJ,aAAAA,CAAcsB,GAAG,CAACnB,SAAAA,CAAAA,EAAY;gBAChC,IAAI,CAACoB,MAAM,CAACpB,SAAAA,CAAAA;AACd,YAAA;YAEAH,aAAAA,CAAcE,GAAG,CAACC,SAAAA,EAAWY,QAAAA,CAAAA;YAE7B,OAAOf,aAAAA;AACT,QAAA,CAAA;AAEAuB,QAAAA,MAAAA,CAAAA,CAAOpB,SAAwB,EAAA;YAC7B,IAAIH,aAAAA,CAAcsB,GAAG,CAACnB,SAAAA,CAAAA,EAAY;AAChCJ,gBAAAA,MAAAA,CAAOiB,IAAI,CAACQ,MAAM,CAACxB,aAAAA,CAAcyB,GAAG,CAACtB,SAAAA,CAAAA,CAAAA;AACrCH,gBAAAA,aAAAA,CAAc0B,MAAM,CAACvB,SAAAA,CAAAA;AACvB,YAAA;YAEA,OAAOH,aAAAA;AACT,QAAA,CAAA;AAEA2B,QAAAA,MAAAA,CAAAA,GAAAA;YACE,OAAO3B,aAAAA;AACT,QAAA,CAAA;AAEA;;;;AAIC,QACD,MAAM4B,gBAAAA,CAAAA,GAAAA;YACJ,MAAMC,QAAAA,GAAW,MAAM9B,MAAAA,CAAOO,EAAE,CAACC,KAAK,CAACC,2BAAAA,CAAAA,CAAmBsB,QAAQ,CAAC;gBACjEpB,KAAAA,EAAO;oBACLqB,WAAAA,EAAa;AACXC,wBAAAA,IAAAA,EAAM,IAAIC,IAAAA;AACZ,qBAAA;oBACArB,UAAAA,EAAY;AACd;AACF,aAAA,CAAA;YAEA,KAAK,MAAMP,WAAWwB,QAAAA,CAAU;AAC9B,gBAAA,IAAI,CAAC3B,GAAG,CAACG,QAAQM,EAAE,EAAEN,QAAQ0B,WAAW,CAAA;AAC1C,YAAA;YAEA,OAAO/B,aAAAA;AACT,QAAA;AACF,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"scheduling.js","sources":["../../../server/src/services/scheduling.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { errors } from '@strapi/utils';\nimport { Release } from '../../../shared/contracts/releases';\nimport { getService } from '../utils';\nimport { RELEASE_MODEL_UID } from '../constants';\n\nconst createSchedulingService = ({ strapi }: { strapi: Core.Strapi }) => {\n const scheduledJobs = new Map<Release['id'], string>();\n\n return {\n async set(releaseId: Release['id'], scheduleDate: Date) {\n const id = String(releaseId); // callers pass both numeric (db row) and string (ctx.params) ids\n\n const release = await strapi.db\n .query(RELEASE_MODEL_UID)\n .findOne({ where: { id: releaseId, releasedAt: null } });\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n const taskName = `publishRelease_${id}`;\n\n strapi.cron.add({\n [taskName]: {\n async task() {\n await getService('release', { strapi }).publish(releaseId);\n },\n options: scheduleDate,\n },\n });\n\n if (scheduledJobs.has(id)) {\n this.cancel(id);\n }\n\n scheduledJobs.set(id, taskName);\n\n return scheduledJobs;\n },\n\n cancel(releaseId: Release['id']) {\n const id = String(releaseId); // normalise to match key from set()\n\n if (scheduledJobs.has(id)) {\n strapi.cron.remove(scheduledJobs.get(id)!);\n scheduledJobs.delete(id);\n }\n\n return scheduledJobs;\n },\n\n getAll() {\n return scheduledJobs;\n },\n\n /**\n * On bootstrap, we can use this function to make sure to sync the scheduled jobs from the database that are not yet released\n * This is useful in case the server was restarted and the scheduled jobs were lost\n * This also could be used to sync different Strapi instances in case of a cluster\n */\n async syncFromDatabase() {\n const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({\n where: {\n scheduledAt: {\n $gte: new Date(),\n },\n releasedAt: null,\n },\n });\n\n for (const release of releases) {\n this.set(release.id, release.scheduledAt);\n }\n\n return scheduledJobs;\n },\n };\n};\n\nexport default createSchedulingService;\n"],"names":["createSchedulingService","strapi","scheduledJobs","Map","set","releaseId","scheduleDate","id","String","release","db","query","RELEASE_MODEL_UID","findOne","where","releasedAt","errors","NotFoundError","taskName","cron","add","task","getService","publish","options","has","cancel","remove","get","delete","getAll","syncFromDatabase","releases","findMany","scheduledAt","$gte","Date"],"mappings":";;;;;;AAOA,MAAMA,uBAAAA,GAA0B,CAAC,EAAEC,MAAM,EAA2B,GAAA;AAClE,IAAA,MAAMC,gBAAgB,IAAIC,GAAAA,EAAAA;IAE1B,OAAO;QACL,MAAMC,GAAAA,CAAAA,CAAIC,SAAwB,EAAEC,YAAkB,EAAA;YACpD,MAAMC,EAAAA,GAAKC,MAAAA,CAAOH,SAAAA,CAAAA,CAAAA;YAElB,MAAMI,OAAAA,GAAU,MAAMR,MAAAA,CAAOS,EAAE,CAC5BC,KAAK,CAACC,2BAAAA,CAAAA,CACNC,OAAO,CAAC;gBAAEC,KAAAA,EAAO;oBAAEP,EAAAA,EAAIF,SAAAA;oBAAWU,UAAAA,EAAY;AAAK;AAAE,aAAA,CAAA;AAExD,YAAA,IAAI,CAACN,OAAAA,EAAS;AACZ,gBAAA,MAAM,IAAIO,YAAAA,CAAOC,aAAa,CAAC,CAAC,wBAAwB,EAAEZ,SAAAA,CAAAA,CAAW,CAAA;AACvE,YAAA;AAEA,YAAA,MAAMa,QAAAA,GAAW,CAAC,eAAe,EAAEX,EAAAA,CAAAA,CAAI;YAEvCN,MAAAA,CAAOkB,IAAI,CAACC,GAAG,CAAC;AACd,gBAAA,CAACF,WAAW;oBACV,MAAMG,IAAAA,CAAAA,GAAAA;AACJ,wBAAA,MAAMC,iBAAW,SAAA,EAAW;AAAErB,4BAAAA;AAAO,yBAAA,CAAA,CAAGsB,OAAO,CAAClB,SAAAA,CAAAA;AAClD,oBAAA,CAAA;oBACAmB,OAAAA,EAASlB;AACX;AACF,aAAA,CAAA;YAEA,IAAIJ,aAAAA,CAAcuB,GAAG,CAAClB,EAAAA,CAAAA,EAAK;gBACzB,IAAI,CAACmB,MAAM,CAACnB,EAAAA,CAAAA;AACd,YAAA;YAEAL,aAAAA,CAAcE,GAAG,CAACG,EAAAA,EAAIW,QAAAA,CAAAA;YAEtB,OAAOhB,aAAAA;AACT,QAAA,CAAA;AAEAwB,QAAAA,MAAAA,CAAAA,CAAOrB,SAAwB,EAAA;YAC7B,MAAME,EAAAA,GAAKC,MAAAA,CAAOH,SAAAA,CAAAA,CAAAA;YAElB,IAAIH,aAAAA,CAAcuB,GAAG,CAAClB,EAAAA,CAAAA,EAAK;AACzBN,gBAAAA,MAAAA,CAAOkB,IAAI,CAACQ,MAAM,CAACzB,aAAAA,CAAc0B,GAAG,CAACrB,EAAAA,CAAAA,CAAAA;AACrCL,gBAAAA,aAAAA,CAAc2B,MAAM,CAACtB,EAAAA,CAAAA;AACvB,YAAA;YAEA,OAAOL,aAAAA;AACT,QAAA,CAAA;AAEA4B,QAAAA,MAAAA,CAAAA,GAAAA;YACE,OAAO5B,aAAAA;AACT,QAAA,CAAA;AAEA;;;;AAIC,QACD,MAAM6B,gBAAAA,CAAAA,GAAAA;YACJ,MAAMC,QAAAA,GAAW,MAAM/B,MAAAA,CAAOS,EAAE,CAACC,KAAK,CAACC,2BAAAA,CAAAA,CAAmBqB,QAAQ,CAAC;gBACjEnB,KAAAA,EAAO;oBACLoB,WAAAA,EAAa;AACXC,wBAAAA,IAAAA,EAAM,IAAIC,IAAAA;AACZ,qBAAA;oBACArB,UAAAA,EAAY;AACd;AACF,aAAA,CAAA;YAEA,KAAK,MAAMN,WAAWuB,QAAAA,CAAU;AAC9B,gBAAA,IAAI,CAAC5B,GAAG,CAACK,QAAQF,EAAE,EAAEE,QAAQyB,WAAW,CAAA;AAC1C,YAAA;YAEA,OAAOhC,aAAAA;AACT,QAAA;AACF,KAAA;AACF;;;;"}
@@ -6,6 +6,7 @@ const createSchedulingService = ({ strapi })=>{
6
6
  const scheduledJobs = new Map();
7
7
  return {
8
8
  async set (releaseId, scheduleDate) {
9
+ const id = String(releaseId); // callers pass both numeric (db row) and string (ctx.params) ids
9
10
  const release = await strapi.db.query(RELEASE_MODEL_UID).findOne({
10
11
  where: {
11
12
  id: releaseId,
@@ -15,7 +16,7 @@ const createSchedulingService = ({ strapi })=>{
15
16
  if (!release) {
16
17
  throw new errors.NotFoundError(`No release found for id ${releaseId}`);
17
18
  }
18
- const taskName = `publishRelease_${releaseId}`;
19
+ const taskName = `publishRelease_${id}`;
19
20
  strapi.cron.add({
20
21
  [taskName]: {
21
22
  async task () {
@@ -26,16 +27,17 @@ const createSchedulingService = ({ strapi })=>{
26
27
  options: scheduleDate
27
28
  }
28
29
  });
29
- if (scheduledJobs.has(releaseId)) {
30
- this.cancel(releaseId);
30
+ if (scheduledJobs.has(id)) {
31
+ this.cancel(id);
31
32
  }
32
- scheduledJobs.set(releaseId, taskName);
33
+ scheduledJobs.set(id, taskName);
33
34
  return scheduledJobs;
34
35
  },
35
36
  cancel (releaseId) {
36
- if (scheduledJobs.has(releaseId)) {
37
- strapi.cron.remove(scheduledJobs.get(releaseId));
38
- scheduledJobs.delete(releaseId);
37
+ const id = String(releaseId); // normalise to match key from set()
38
+ if (scheduledJobs.has(id)) {
39
+ strapi.cron.remove(scheduledJobs.get(id));
40
+ scheduledJobs.delete(id);
39
41
  }
40
42
  return scheduledJobs;
41
43
  },
@@ -1 +1 @@
1
- {"version":3,"file":"scheduling.mjs","sources":["../../../server/src/services/scheduling.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { errors } from '@strapi/utils';\nimport { Release } from '../../../shared/contracts/releases';\nimport { getService } from '../utils';\nimport { RELEASE_MODEL_UID } from '../constants';\n\nconst createSchedulingService = ({ strapi }: { strapi: Core.Strapi }) => {\n const scheduledJobs = new Map<Release['id'], string>();\n\n return {\n async set(releaseId: Release['id'], scheduleDate: Date) {\n const release = await strapi.db\n .query(RELEASE_MODEL_UID)\n .findOne({ where: { id: releaseId, releasedAt: null } });\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n const taskName = `publishRelease_${releaseId}`;\n\n strapi.cron.add({\n [taskName]: {\n async task() {\n await getService('release', { strapi }).publish(releaseId);\n },\n options: scheduleDate,\n },\n });\n\n if (scheduledJobs.has(releaseId)) {\n this.cancel(releaseId);\n }\n\n scheduledJobs.set(releaseId, taskName);\n\n return scheduledJobs;\n },\n\n cancel(releaseId: Release['id']) {\n if (scheduledJobs.has(releaseId)) {\n strapi.cron.remove(scheduledJobs.get(releaseId)!);\n scheduledJobs.delete(releaseId);\n }\n\n return scheduledJobs;\n },\n\n getAll() {\n return scheduledJobs;\n },\n\n /**\n * On bootstrap, we can use this function to make sure to sync the scheduled jobs from the database that are not yet released\n * This is useful in case the server was restarted and the scheduled jobs were lost\n * This also could be used to sync different Strapi instances in case of a cluster\n */\n async syncFromDatabase() {\n const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({\n where: {\n scheduledAt: {\n $gte: new Date(),\n },\n releasedAt: null,\n },\n });\n\n for (const release of releases) {\n this.set(release.id, release.scheduledAt);\n }\n\n return scheduledJobs;\n },\n };\n};\n\nexport default createSchedulingService;\n"],"names":["createSchedulingService","strapi","scheduledJobs","Map","set","releaseId","scheduleDate","release","db","query","RELEASE_MODEL_UID","findOne","where","id","releasedAt","errors","NotFoundError","taskName","cron","add","task","getService","publish","options","has","cancel","remove","get","delete","getAll","syncFromDatabase","releases","findMany","scheduledAt","$gte","Date"],"mappings":";;;;AAOA,MAAMA,uBAAAA,GAA0B,CAAC,EAAEC,MAAM,EAA2B,GAAA;AAClE,IAAA,MAAMC,gBAAgB,IAAIC,GAAAA,EAAAA;IAE1B,OAAO;QACL,MAAMC,GAAAA,CAAAA,CAAIC,SAAwB,EAAEC,YAAkB,EAAA;YACpD,MAAMC,OAAAA,GAAU,MAAMN,MAAAA,CAAOO,EAAE,CAC5BC,KAAK,CAACC,iBAAAA,CAAAA,CACNC,OAAO,CAAC;gBAAEC,KAAAA,EAAO;oBAAEC,EAAAA,EAAIR,SAAAA;oBAAWS,UAAAA,EAAY;AAAK;AAAE,aAAA,CAAA;AAExD,YAAA,IAAI,CAACP,OAAAA,EAAS;AACZ,gBAAA,MAAM,IAAIQ,MAAAA,CAAOC,aAAa,CAAC,CAAC,wBAAwB,EAAEX,SAAAA,CAAAA,CAAW,CAAA;AACvE,YAAA;AAEA,YAAA,MAAMY,QAAAA,GAAW,CAAC,eAAe,EAAEZ,SAAAA,CAAAA,CAAW;YAE9CJ,MAAAA,CAAOiB,IAAI,CAACC,GAAG,CAAC;AACd,gBAAA,CAACF,WAAW;oBACV,MAAMG,IAAAA,CAAAA,GAAAA;AACJ,wBAAA,MAAMC,WAAW,SAAA,EAAW;AAAEpB,4BAAAA;AAAO,yBAAA,CAAA,CAAGqB,OAAO,CAACjB,SAAAA,CAAAA;AAClD,oBAAA,CAAA;oBACAkB,OAAAA,EAASjB;AACX;AACF,aAAA,CAAA;YAEA,IAAIJ,aAAAA,CAAcsB,GAAG,CAACnB,SAAAA,CAAAA,EAAY;gBAChC,IAAI,CAACoB,MAAM,CAACpB,SAAAA,CAAAA;AACd,YAAA;YAEAH,aAAAA,CAAcE,GAAG,CAACC,SAAAA,EAAWY,QAAAA,CAAAA;YAE7B,OAAOf,aAAAA;AACT,QAAA,CAAA;AAEAuB,QAAAA,MAAAA,CAAAA,CAAOpB,SAAwB,EAAA;YAC7B,IAAIH,aAAAA,CAAcsB,GAAG,CAACnB,SAAAA,CAAAA,EAAY;AAChCJ,gBAAAA,MAAAA,CAAOiB,IAAI,CAACQ,MAAM,CAACxB,aAAAA,CAAcyB,GAAG,CAACtB,SAAAA,CAAAA,CAAAA;AACrCH,gBAAAA,aAAAA,CAAc0B,MAAM,CAACvB,SAAAA,CAAAA;AACvB,YAAA;YAEA,OAAOH,aAAAA;AACT,QAAA,CAAA;AAEA2B,QAAAA,MAAAA,CAAAA,GAAAA;YACE,OAAO3B,aAAAA;AACT,QAAA,CAAA;AAEA;;;;AAIC,QACD,MAAM4B,gBAAAA,CAAAA,GAAAA;YACJ,MAAMC,QAAAA,GAAW,MAAM9B,MAAAA,CAAOO,EAAE,CAACC,KAAK,CAACC,iBAAAA,CAAAA,CAAmBsB,QAAQ,CAAC;gBACjEpB,KAAAA,EAAO;oBACLqB,WAAAA,EAAa;AACXC,wBAAAA,IAAAA,EAAM,IAAIC,IAAAA;AACZ,qBAAA;oBACArB,UAAAA,EAAY;AACd;AACF,aAAA,CAAA;YAEA,KAAK,MAAMP,WAAWwB,QAAAA,CAAU;AAC9B,gBAAA,IAAI,CAAC3B,GAAG,CAACG,QAAQM,EAAE,EAAEN,QAAQ0B,WAAW,CAAA;AAC1C,YAAA;YAEA,OAAO/B,aAAAA;AACT,QAAA;AACF,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"scheduling.mjs","sources":["../../../server/src/services/scheduling.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { errors } from '@strapi/utils';\nimport { Release } from '../../../shared/contracts/releases';\nimport { getService } from '../utils';\nimport { RELEASE_MODEL_UID } from '../constants';\n\nconst createSchedulingService = ({ strapi }: { strapi: Core.Strapi }) => {\n const scheduledJobs = new Map<Release['id'], string>();\n\n return {\n async set(releaseId: Release['id'], scheduleDate: Date) {\n const id = String(releaseId); // callers pass both numeric (db row) and string (ctx.params) ids\n\n const release = await strapi.db\n .query(RELEASE_MODEL_UID)\n .findOne({ where: { id: releaseId, releasedAt: null } });\n\n if (!release) {\n throw new errors.NotFoundError(`No release found for id ${releaseId}`);\n }\n\n const taskName = `publishRelease_${id}`;\n\n strapi.cron.add({\n [taskName]: {\n async task() {\n await getService('release', { strapi }).publish(releaseId);\n },\n options: scheduleDate,\n },\n });\n\n if (scheduledJobs.has(id)) {\n this.cancel(id);\n }\n\n scheduledJobs.set(id, taskName);\n\n return scheduledJobs;\n },\n\n cancel(releaseId: Release['id']) {\n const id = String(releaseId); // normalise to match key from set()\n\n if (scheduledJobs.has(id)) {\n strapi.cron.remove(scheduledJobs.get(id)!);\n scheduledJobs.delete(id);\n }\n\n return scheduledJobs;\n },\n\n getAll() {\n return scheduledJobs;\n },\n\n /**\n * On bootstrap, we can use this function to make sure to sync the scheduled jobs from the database that are not yet released\n * This is useful in case the server was restarted and the scheduled jobs were lost\n * This also could be used to sync different Strapi instances in case of a cluster\n */\n async syncFromDatabase() {\n const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({\n where: {\n scheduledAt: {\n $gte: new Date(),\n },\n releasedAt: null,\n },\n });\n\n for (const release of releases) {\n this.set(release.id, release.scheduledAt);\n }\n\n return scheduledJobs;\n },\n };\n};\n\nexport default createSchedulingService;\n"],"names":["createSchedulingService","strapi","scheduledJobs","Map","set","releaseId","scheduleDate","id","String","release","db","query","RELEASE_MODEL_UID","findOne","where","releasedAt","errors","NotFoundError","taskName","cron","add","task","getService","publish","options","has","cancel","remove","get","delete","getAll","syncFromDatabase","releases","findMany","scheduledAt","$gte","Date"],"mappings":";;;;AAOA,MAAMA,uBAAAA,GAA0B,CAAC,EAAEC,MAAM,EAA2B,GAAA;AAClE,IAAA,MAAMC,gBAAgB,IAAIC,GAAAA,EAAAA;IAE1B,OAAO;QACL,MAAMC,GAAAA,CAAAA,CAAIC,SAAwB,EAAEC,YAAkB,EAAA;YACpD,MAAMC,EAAAA,GAAKC,MAAAA,CAAOH,SAAAA,CAAAA,CAAAA;YAElB,MAAMI,OAAAA,GAAU,MAAMR,MAAAA,CAAOS,EAAE,CAC5BC,KAAK,CAACC,iBAAAA,CAAAA,CACNC,OAAO,CAAC;gBAAEC,KAAAA,EAAO;oBAAEP,EAAAA,EAAIF,SAAAA;oBAAWU,UAAAA,EAAY;AAAK;AAAE,aAAA,CAAA;AAExD,YAAA,IAAI,CAACN,OAAAA,EAAS;AACZ,gBAAA,MAAM,IAAIO,MAAAA,CAAOC,aAAa,CAAC,CAAC,wBAAwB,EAAEZ,SAAAA,CAAAA,CAAW,CAAA;AACvE,YAAA;AAEA,YAAA,MAAMa,QAAAA,GAAW,CAAC,eAAe,EAAEX,EAAAA,CAAAA,CAAI;YAEvCN,MAAAA,CAAOkB,IAAI,CAACC,GAAG,CAAC;AACd,gBAAA,CAACF,WAAW;oBACV,MAAMG,IAAAA,CAAAA,GAAAA;AACJ,wBAAA,MAAMC,WAAW,SAAA,EAAW;AAAErB,4BAAAA;AAAO,yBAAA,CAAA,CAAGsB,OAAO,CAAClB,SAAAA,CAAAA;AAClD,oBAAA,CAAA;oBACAmB,OAAAA,EAASlB;AACX;AACF,aAAA,CAAA;YAEA,IAAIJ,aAAAA,CAAcuB,GAAG,CAAClB,EAAAA,CAAAA,EAAK;gBACzB,IAAI,CAACmB,MAAM,CAACnB,EAAAA,CAAAA;AACd,YAAA;YAEAL,aAAAA,CAAcE,GAAG,CAACG,EAAAA,EAAIW,QAAAA,CAAAA;YAEtB,OAAOhB,aAAAA;AACT,QAAA,CAAA;AAEAwB,QAAAA,MAAAA,CAAAA,CAAOrB,SAAwB,EAAA;YAC7B,MAAME,EAAAA,GAAKC,MAAAA,CAAOH,SAAAA,CAAAA,CAAAA;YAElB,IAAIH,aAAAA,CAAcuB,GAAG,CAAClB,EAAAA,CAAAA,EAAK;AACzBN,gBAAAA,MAAAA,CAAOkB,IAAI,CAACQ,MAAM,CAACzB,aAAAA,CAAc0B,GAAG,CAACrB,EAAAA,CAAAA,CAAAA;AACrCL,gBAAAA,aAAAA,CAAc2B,MAAM,CAACtB,EAAAA,CAAAA;AACvB,YAAA;YAEA,OAAOL,aAAAA;AACT,QAAA,CAAA;AAEA4B,QAAAA,MAAAA,CAAAA,GAAAA;YACE,OAAO5B,aAAAA;AACT,QAAA,CAAA;AAEA;;;;AAIC,QACD,MAAM6B,gBAAAA,CAAAA,GAAAA;YACJ,MAAMC,QAAAA,GAAW,MAAM/B,MAAAA,CAAOS,EAAE,CAACC,KAAK,CAACC,iBAAAA,CAAAA,CAAmBqB,QAAQ,CAAC;gBACjEnB,KAAAA,EAAO;oBACLoB,WAAAA,EAAa;AACXC,wBAAAA,IAAAA,EAAM,IAAIC,IAAAA;AACZ,qBAAA;oBACArB,UAAAA,EAAY;AACd;AACF,aAAA,CAAA;YAEA,KAAK,MAAMN,WAAWuB,QAAAA,CAAU;AAC9B,gBAAA,IAAI,CAAC5B,GAAG,CAACK,QAAQF,EAAE,EAAEE,QAAQyB,WAAW,CAAA;AAC1C,YAAA;YAEA,OAAOhC,aAAAA;AACT,QAAA;AACF,KAAA;AACF;;;;"}
@@ -210,7 +210,9 @@ declare const _default: {
210
210
  };
211
211
  };
212
212
  routes: {
213
- homepage: import("@strapi/types/dist/core/router.js").Router;
213
+ homepage: import("@strapi/types/dist/core/router.js").Router | ((params: {
214
+ strapi: import("@strapi/types/dist/core/strapi.js").Strapi;
215
+ }) => import("@strapi/types/dist/core/router.js").Router);
214
216
  settings: {
215
217
  type: string;
216
218
  routes: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../server/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA+BylF,sEAA6B;;;;;;;;;;;;;;;8BAA2gG,yEAAgC;+BAAuxC,0EAAiC;;;;;;8BAAlgL,sFAAsC;0CAA4I,CAAC;;gCAAmiE,oFAAoC;;;;;;;;;;;;6BAAkvI,sFAAsC,yBAA8B,sFAAsC;6BAA63C,sFAAsC,yBAA8B,sFAAsC;;;;;;2CAPzgT,sFACwB;8CAMysC,oFAAoC,kCAAqC,oFAAoC;;sDAAi2C,uEAA8B,eAAkB,yEAAgC;2DAAse,uEAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAD9wG,wBAA2B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../server/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA+BylF,sEAA6B;;;;;;;;;;;;;;;8BAA2gG,yEAAgC;+BAAuxC,0EAAiC;;;;;;8BAAlgL,sFAAsC;0CAA4I,CAAC;;gCAAmiE,oFAAoC;;;;;;;;;;;;6BAAkvI,sFAAsC,yBAA8B,sFAAsC;6BAA63C,sFAAsC,yBAA8B,sFAAsC;;;;;;2CAPzgT,sFACwB;8CAMysC,oFAAoC,kCAAqC,oFAAoC;;sDAAi2C,uEAA8B,eAAkB,yEAAgC;2DAAse,uEAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAD9wG,wBAA2B"}
@@ -1,5 +1,7 @@
1
1
  export declare const routes: {
2
- homepage: import("@strapi/types/dist/core/router.js").Router;
2
+ homepage: import("@strapi/types/dist/core/router.js").Router | ((params: {
3
+ strapi: import("@strapi/types/dist/core/strapi.js").Strapi;
4
+ }) => import("@strapi/types/dist/core/router.js").Router);
3
5
  settings: {
4
6
  type: string;
5
7
  routes: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/src/routes/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKlB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/src/routes/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKlB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"scheduling.d.ts","sourceRoot":"","sources":["../../../../server/src/services/scheduling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAI7D,QAAA,MAAM,uBAAuB,GAAI,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE;mBAI3C,OAAO,CAAC,IAAI,CAAC,gBAAgB,IAAI;sBA6BpC,OAAO,CAAC,IAAI,CAAC;;IAa/B;;;;OAIG;;CAkBN,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"scheduling.d.ts","sourceRoot":"","sources":["../../../../server/src/services/scheduling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAI7D,QAAA,MAAM,uBAAuB,GAAI,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE;mBAI3C,OAAO,CAAC,IAAI,CAAC,gBAAgB,IAAI;sBA+BpC,OAAO,CAAC,IAAI,CAAC;;IAe/B;;;;OAIG;;CAkBN,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/src/utils/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,KAAK,QAAQ,GAAG;IACd,OAAO,EAAE,cAAc,CAAC;IACxB,oBAAoB,EAAE,GAAG,CAAC;IAC1B,UAAU,EAAE,GAAG,CAAC;IAChB,gBAAgB,EAAE,oBAAoB,CAAC;IACvC,eAAe,EAAE,GAAG,CAAC;IACrB,QAAQ,EAAE,eAAe,CAAC;CAC3B,CAAC;AAEF,UAAU,MAAM;IACd,WAAW,EAAE,GAAG,CAAC,WAAW,CAAC;IAC7B,UAAU,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,UAAU,GAAI,KAAK,SAAS,MAAM,QAAQ,EACrD,MAAM,KAAK,EACX,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,KAClC,QAAQ,CAAC,KAAK,CAEhB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,qCAAqC,MAAM,EAC3C,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,qBASpC,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,gBAAgB,MAAM,EACtB,OAAO,GAAG,EACV,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,qBA0BpC,CAAC;AAEF,eAAO,MAAM,QAAQ,GACnB,wDAMG,MAAM,GAAG;IAAE,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAA;CAAE,EAC7D,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,wFAmBpC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAU,aAAa,GAAG,CAAC,WAAW,EAAE,OAAO,IAAI,CAAC,WAAW,gDAwBzF,CAAC;AA+CF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,8BAA8B,GACzC,iBAAiB,GAAG,CAAC,WAAW,EAAE,EAClC,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,KAClC,GAAG,CAAC,WAAW,EAsDjB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/src/utils/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,KAAK,QAAQ,GAAG;IACd,OAAO,EAAE,cAAc,CAAC;IACxB,oBAAoB,EAAE,GAAG,CAAC;IAC1B,UAAU,EAAE,GAAG,CAAC;IAChB,gBAAgB,EAAE,oBAAoB,CAAC;IACvC,eAAe,EAAE,GAAG,CAAC;IACrB,QAAQ,EAAE,eAAe,CAAC;CAC3B,CAAC;AAEF,UAAU,MAAM;IACd,WAAW,EAAE,GAAG,CAAC,WAAW,CAAC;IAC7B,UAAU,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,UAAU,GAAI,KAAK,SAAS,MAAM,QAAQ,EACrD,MAAM,KAAK,EACX,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,KAClC,QAAQ,CAAC,KAAK,CAEhB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,qCAAqC,MAAM,EAC3C,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,qBASpC,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,gBAAgB,MAAM,EACtB,OAAO,GAAG,EACV,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,qBAoCpC,CAAC;AAEF,eAAO,MAAM,QAAQ,GACnB,wDAMG,MAAM,GAAG;IAAE,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAA;CAAE,EAC7D,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,wFAmBpC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAU,aAAa,GAAG,CAAC,WAAW,EAAE,OAAO,IAAI,CAAC,WAAW,gDAwBzF,CAAC;AA+CF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,8BAA8B,GACzC,iBAAiB,GAAG,CAAC,WAAW,EAAE,EAClC,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,KAClC,GAAG,CAAC,WAAW,EAsDjB,CAAC"}
@@ -23,8 +23,18 @@ const getDraftEntryValidStatus = async ({ contentType, documentId, locale }, { s
23
23
  };
24
24
  const isEntryValid = async (contentTypeUid, entry, { strapi: strapi1 })=>{
25
25
  try {
26
+ // Mirror the document-service publish path: when `api.documents.strictRelations`
27
+ // is on, required media/relations are enforced on non-draft writes. Reading the
28
+ // flag here keeps the release "valid" badge consistent with what publish will
29
+ // actually accept (otherwise the UI can mark an entry valid that publish rejects).
30
+ const rawStrictRelations = strapi1.config.get('api.documents.strictRelations', undefined);
31
+ const strictRelations = rawStrictRelations === true;
26
32
  // @TODO: When documents service has validateEntityCreation method, use it instead
27
- await strapi1.entityValidator.validateEntityCreation(strapi1.getModel(contentTypeUid), entry, undefined, // @ts-expect-error - FIXME: entity here is unnecessary
33
+ await strapi1.entityValidator.validateEntityCreation(strapi1.getModel(contentTypeUid), entry, {
34
+ isDraft: false,
35
+ locale: entry?.locale,
36
+ strictRelations
37
+ }, // @ts-expect-error - FIXME: entity here is unnecessary
28
38
  entry);
29
39
  const workflowsService = strapi1.plugin('review-workflows').service('workflows');
30
40
  // Workflows service may not be available depending on the license
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../server/src/utils/index.ts"],"sourcesContent":["import { contentTypes as contentTypesUtils } from '@strapi/utils';\n\nimport type { UID, Data, Core } from '@strapi/types';\n\nimport type { SettingsService } from '../services/settings';\nimport type { ReleaseService } from '../services/release';\nimport type { ReleaseActionService } from '../services/release-action';\n\ntype Services = {\n release: ReleaseService;\n 'release-validation': any;\n scheduling: any;\n 'release-action': ReleaseActionService;\n 'event-manager': any;\n settings: SettingsService;\n};\n\ninterface Action {\n contentType: UID.ContentType;\n documentId?: Data.DocumentID;\n locale?: string;\n}\n\nexport const getService = <TName extends keyof Services>(\n name: TName,\n { strapi }: { strapi: Core.Strapi }\n): Services[TName] => {\n return strapi.plugin('content-releases').service(name);\n};\n\nexport const getDraftEntryValidStatus = async (\n { contentType, documentId, locale }: Action,\n { strapi }: { strapi: Core.Strapi }\n) => {\n const populateBuilderService = strapi.plugin('content-manager').service('populate-builder');\n // @ts-expect-error - populateBuilderService should be a function but is returning service\n const populate = await populateBuilderService(contentType).populateDeep(Infinity).build();\n\n const entry = await getEntry({ contentType, documentId, locale, populate }, { strapi });\n\n return isEntryValid(contentType, entry, { strapi });\n};\n\nexport const isEntryValid = async (\n contentTypeUid: string,\n entry: any,\n { strapi }: { strapi: Core.Strapi }\n) => {\n try {\n // @TODO: When documents service has validateEntityCreation method, use it instead\n await strapi.entityValidator.validateEntityCreation(\n strapi.getModel(contentTypeUid as UID.ContentType),\n entry,\n undefined,\n // @ts-expect-error - FIXME: entity here is unnecessary\n entry\n );\n\n const workflowsService = strapi.plugin('review-workflows').service('workflows');\n // Workflows service may not be available depending on the license\n const workflow = await workflowsService?.getAssignedWorkflow(contentTypeUid, {\n populate: 'stageRequiredToPublish',\n });\n\n if (workflow?.stageRequiredToPublish) {\n return entry.strapi_stage.id === workflow.stageRequiredToPublish.id;\n }\n\n return true;\n } catch {\n return false;\n }\n};\n\nexport const getEntry = async (\n {\n contentType,\n documentId,\n locale,\n populate,\n status = 'draft',\n }: Action & { status?: 'draft' | 'published'; populate: any },\n { strapi }: { strapi: Core.Strapi }\n) => {\n if (documentId) {\n // Try to get an existing draft or published document\n const entry = await strapi\n .documents(contentType)\n .findOne({ documentId, locale, populate, status });\n\n // The document isn't published yet, but the action is to publish it, fetch the draft\n if (status === 'published' && !entry) {\n return strapi\n .documents(contentType)\n .findOne({ documentId, locale, populate, status: 'draft' });\n }\n\n return entry;\n }\n\n return strapi.documents(contentType).findFirst({ locale, populate, status });\n};\n\nexport const getEntryStatus = async (contentType: UID.ContentType, entry: Data.ContentType) => {\n if (entry.publishedAt) {\n return 'published';\n }\n\n const publishedEntry = await strapi.documents(contentType).findOne({\n documentId: entry.documentId,\n locale: entry.locale,\n status: 'published',\n fields: ['updatedAt'],\n });\n\n if (!publishedEntry) {\n return 'draft';\n }\n\n const entryUpdatedAt = new Date(entry.updatedAt).getTime();\n const publishedEntryUpdatedAt = new Date(publishedEntry.updatedAt).getTime();\n\n if (entryUpdatedAt > publishedEntryUpdatedAt) {\n return 'modified';\n }\n\n return 'published';\n};\n\n/**\n * Recursively collects content type UIDs that a model (content type or component) has relations to.\n * Go through component and dynamic zone attributes to find nested relations.\n */\nconst collectRelationTargets = (\n modelUid: string,\n strapi: Core.Strapi,\n visited = new Set<string>()\n): Set<string> => {\n const targets = new Set<string>();\n if (visited.has(modelUid)) {\n return targets;\n }\n visited.add(modelUid);\n\n const model = strapi.getModel(modelUid as UID.Schema);\n if (!model?.attributes) {\n return targets;\n }\n\n for (const attribute of Object.values(model.attributes) as Array<{\n type?: string;\n target?: string;\n component?: string;\n components?: string[];\n }>) {\n if (attribute?.type === 'relation' && attribute.target) {\n targets.add(attribute.target);\n }\n if (attribute?.type === 'component' && attribute.component) {\n for (const t of collectRelationTargets(attribute.component, strapi, visited)) {\n targets.add(t);\n }\n }\n if (attribute?.type === 'dynamiczone' && attribute.components) {\n for (const compUid of attribute.components) {\n for (const t of collectRelationTargets(compUid, strapi, visited)) {\n targets.add(t);\n }\n }\n }\n }\n return targets;\n};\n\n/**\n * Returns content type UIDs sorted by relation dependency order for publishing.\n * When content type A has a relation to content type B (both with draft & publish),\n * B will appear before A in the result. This ensures that when publishing a release,\n * related entities are published first, so that relation IDs can be correctly\n * resolved (published target must exist when publishing source).\n *\n * Relations in components (nested or not) and dynamic zones are also considered.\n *\n * @param contentTypeUids - Content type UIDs that will be published in the release\n * @param strapi - Strapi instance\n * @returns Content type UIDs in publish order (dependencies first)\n */\nexport const getPublishOrderForContentTypes = (\n contentTypeUids: UID.ContentType[],\n { strapi }: { strapi: Core.Strapi }\n): UID.ContentType[] => {\n const uidSet = new Set(contentTypeUids);\n\n // Build dependency graph: source depends on target (source must be published after target)\n const dependencies = new Map<UID.ContentType, Set<UID.ContentType>>();\n\n for (const uid of contentTypeUids) {\n const model = strapi.getModel(uid);\n if (model && contentTypesUtils.hasDraftAndPublish(model)) {\n const relationTargets = collectRelationTargets(uid, strapi);\n\n for (const targetUid of relationTargets) {\n const targetContentTypeUid = targetUid as UID.ContentType;\n const isTargetInRelease =\n uidSet.has(targetContentTypeUid) && targetContentTypeUid in strapi.contentTypes;\n const targetModel = strapi.getModel(targetContentTypeUid);\n const targetHasDraftAndPublish =\n targetModel && contentTypesUtils.hasDraftAndPublish(targetModel);\n\n if (isTargetInRelease && targetHasDraftAndPublish) {\n let dependencySet = dependencies.get(uid);\n if (!dependencySet) {\n dependencySet = new Set();\n dependencies.set(uid, dependencySet);\n }\n dependencySet.add(targetContentTypeUid);\n }\n }\n }\n }\n\n // Topological sort: dependencies first\n const sorted: UID.ContentType[] = [];\n const visited = new Set<UID.ContentType>();\n const visiting = new Set<UID.ContentType>();\n\n const visit = (uid: UID.ContentType) => {\n if (visited.has(uid)) return;\n if (visiting.has(uid)) return; // No cycle in valid schemas\n\n visiting.add(uid);\n for (const dep of dependencies.get(uid) ?? []) {\n visit(dep);\n }\n visiting.delete(uid);\n visited.add(uid);\n sorted.push(uid);\n };\n\n for (const uid of contentTypeUids) {\n visit(uid);\n }\n\n return sorted;\n};\n"],"names":["getService","name","strapi","plugin","service","getDraftEntryValidStatus","contentType","documentId","locale","populateBuilderService","populate","populateDeep","Infinity","build","entry","getEntry","isEntryValid","contentTypeUid","entityValidator","validateEntityCreation","getModel","undefined","workflowsService","workflow","getAssignedWorkflow","stageRequiredToPublish","strapi_stage","id","status","documents","findOne","findFirst","getEntryStatus","publishedAt","publishedEntry","fields","entryUpdatedAt","Date","updatedAt","getTime","publishedEntryUpdatedAt","collectRelationTargets","modelUid","visited","Set","targets","has","add","model","attributes","attribute","Object","values","type","target","component","t","components","compUid","getPublishOrderForContentTypes","contentTypeUids","uidSet","dependencies","Map","uid","contentTypesUtils","hasDraftAndPublish","relationTargets","targetUid","targetContentTypeUid","isTargetInRelease","contentTypes","targetModel","targetHasDraftAndPublish","dependencySet","get","set","sorted","visiting","visit","dep","delete","push"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../server/src/utils/index.ts"],"sourcesContent":["import { contentTypes as contentTypesUtils } from '@strapi/utils';\n\nimport type { UID, Data, Core } from '@strapi/types';\n\nimport type { SettingsService } from '../services/settings';\nimport type { ReleaseService } from '../services/release';\nimport type { ReleaseActionService } from '../services/release-action';\n\ntype Services = {\n release: ReleaseService;\n 'release-validation': any;\n scheduling: any;\n 'release-action': ReleaseActionService;\n 'event-manager': any;\n settings: SettingsService;\n};\n\ninterface Action {\n contentType: UID.ContentType;\n documentId?: Data.DocumentID;\n locale?: string;\n}\n\nexport const getService = <TName extends keyof Services>(\n name: TName,\n { strapi }: { strapi: Core.Strapi }\n): Services[TName] => {\n return strapi.plugin('content-releases').service(name);\n};\n\nexport const getDraftEntryValidStatus = async (\n { contentType, documentId, locale }: Action,\n { strapi }: { strapi: Core.Strapi }\n) => {\n const populateBuilderService = strapi.plugin('content-manager').service('populate-builder');\n // @ts-expect-error - populateBuilderService should be a function but is returning service\n const populate = await populateBuilderService(contentType).populateDeep(Infinity).build();\n\n const entry = await getEntry({ contentType, documentId, locale, populate }, { strapi });\n\n return isEntryValid(contentType, entry, { strapi });\n};\n\nexport const isEntryValid = async (\n contentTypeUid: string,\n entry: any,\n { strapi }: { strapi: Core.Strapi }\n) => {\n try {\n // Mirror the document-service publish path: when `api.documents.strictRelations`\n // is on, required media/relations are enforced on non-draft writes. Reading the\n // flag here keeps the release \"valid\" badge consistent with what publish will\n // actually accept (otherwise the UI can mark an entry valid that publish rejects).\n const rawStrictRelations: unknown = strapi.config.get(\n 'api.documents.strictRelations',\n undefined\n );\n const strictRelations = rawStrictRelations === true;\n\n // @TODO: When documents service has validateEntityCreation method, use it instead\n await strapi.entityValidator.validateEntityCreation(\n strapi.getModel(contentTypeUid as UID.ContentType),\n entry,\n { isDraft: false, locale: entry?.locale, strictRelations },\n // @ts-expect-error - FIXME: entity here is unnecessary\n entry\n );\n\n const workflowsService = strapi.plugin('review-workflows').service('workflows');\n // Workflows service may not be available depending on the license\n const workflow = await workflowsService?.getAssignedWorkflow(contentTypeUid, {\n populate: 'stageRequiredToPublish',\n });\n\n if (workflow?.stageRequiredToPublish) {\n return entry.strapi_stage.id === workflow.stageRequiredToPublish.id;\n }\n\n return true;\n } catch {\n return false;\n }\n};\n\nexport const getEntry = async (\n {\n contentType,\n documentId,\n locale,\n populate,\n status = 'draft',\n }: Action & { status?: 'draft' | 'published'; populate: any },\n { strapi }: { strapi: Core.Strapi }\n) => {\n if (documentId) {\n // Try to get an existing draft or published document\n const entry = await strapi\n .documents(contentType)\n .findOne({ documentId, locale, populate, status });\n\n // The document isn't published yet, but the action is to publish it, fetch the draft\n if (status === 'published' && !entry) {\n return strapi\n .documents(contentType)\n .findOne({ documentId, locale, populate, status: 'draft' });\n }\n\n return entry;\n }\n\n return strapi.documents(contentType).findFirst({ locale, populate, status });\n};\n\nexport const getEntryStatus = async (contentType: UID.ContentType, entry: Data.ContentType) => {\n if (entry.publishedAt) {\n return 'published';\n }\n\n const publishedEntry = await strapi.documents(contentType).findOne({\n documentId: entry.documentId,\n locale: entry.locale,\n status: 'published',\n fields: ['updatedAt'],\n });\n\n if (!publishedEntry) {\n return 'draft';\n }\n\n const entryUpdatedAt = new Date(entry.updatedAt).getTime();\n const publishedEntryUpdatedAt = new Date(publishedEntry.updatedAt).getTime();\n\n if (entryUpdatedAt > publishedEntryUpdatedAt) {\n return 'modified';\n }\n\n return 'published';\n};\n\n/**\n * Recursively collects content type UIDs that a model (content type or component) has relations to.\n * Go through component and dynamic zone attributes to find nested relations.\n */\nconst collectRelationTargets = (\n modelUid: string,\n strapi: Core.Strapi,\n visited = new Set<string>()\n): Set<string> => {\n const targets = new Set<string>();\n if (visited.has(modelUid)) {\n return targets;\n }\n visited.add(modelUid);\n\n const model = strapi.getModel(modelUid as UID.Schema);\n if (!model?.attributes) {\n return targets;\n }\n\n for (const attribute of Object.values(model.attributes) as Array<{\n type?: string;\n target?: string;\n component?: string;\n components?: string[];\n }>) {\n if (attribute?.type === 'relation' && attribute.target) {\n targets.add(attribute.target);\n }\n if (attribute?.type === 'component' && attribute.component) {\n for (const t of collectRelationTargets(attribute.component, strapi, visited)) {\n targets.add(t);\n }\n }\n if (attribute?.type === 'dynamiczone' && attribute.components) {\n for (const compUid of attribute.components) {\n for (const t of collectRelationTargets(compUid, strapi, visited)) {\n targets.add(t);\n }\n }\n }\n }\n return targets;\n};\n\n/**\n * Returns content type UIDs sorted by relation dependency order for publishing.\n * When content type A has a relation to content type B (both with draft & publish),\n * B will appear before A in the result. This ensures that when publishing a release,\n * related entities are published first, so that relation IDs can be correctly\n * resolved (published target must exist when publishing source).\n *\n * Relations in components (nested or not) and dynamic zones are also considered.\n *\n * @param contentTypeUids - Content type UIDs that will be published in the release\n * @param strapi - Strapi instance\n * @returns Content type UIDs in publish order (dependencies first)\n */\nexport const getPublishOrderForContentTypes = (\n contentTypeUids: UID.ContentType[],\n { strapi }: { strapi: Core.Strapi }\n): UID.ContentType[] => {\n const uidSet = new Set(contentTypeUids);\n\n // Build dependency graph: source depends on target (source must be published after target)\n const dependencies = new Map<UID.ContentType, Set<UID.ContentType>>();\n\n for (const uid of contentTypeUids) {\n const model = strapi.getModel(uid);\n if (model && contentTypesUtils.hasDraftAndPublish(model)) {\n const relationTargets = collectRelationTargets(uid, strapi);\n\n for (const targetUid of relationTargets) {\n const targetContentTypeUid = targetUid as UID.ContentType;\n const isTargetInRelease =\n uidSet.has(targetContentTypeUid) && targetContentTypeUid in strapi.contentTypes;\n const targetModel = strapi.getModel(targetContentTypeUid);\n const targetHasDraftAndPublish =\n targetModel && contentTypesUtils.hasDraftAndPublish(targetModel);\n\n if (isTargetInRelease && targetHasDraftAndPublish) {\n let dependencySet = dependencies.get(uid);\n if (!dependencySet) {\n dependencySet = new Set();\n dependencies.set(uid, dependencySet);\n }\n dependencySet.add(targetContentTypeUid);\n }\n }\n }\n }\n\n // Topological sort: dependencies first\n const sorted: UID.ContentType[] = [];\n const visited = new Set<UID.ContentType>();\n const visiting = new Set<UID.ContentType>();\n\n const visit = (uid: UID.ContentType) => {\n if (visited.has(uid)) return;\n if (visiting.has(uid)) return; // No cycle in valid schemas\n\n visiting.add(uid);\n for (const dep of dependencies.get(uid) ?? []) {\n visit(dep);\n }\n visiting.delete(uid);\n visited.add(uid);\n sorted.push(uid);\n };\n\n for (const uid of contentTypeUids) {\n visit(uid);\n }\n\n return sorted;\n};\n"],"names":["getService","name","strapi","plugin","service","getDraftEntryValidStatus","contentType","documentId","locale","populateBuilderService","populate","populateDeep","Infinity","build","entry","getEntry","isEntryValid","contentTypeUid","rawStrictRelations","config","get","undefined","strictRelations","entityValidator","validateEntityCreation","getModel","isDraft","workflowsService","workflow","getAssignedWorkflow","stageRequiredToPublish","strapi_stage","id","status","documents","findOne","findFirst","getEntryStatus","publishedAt","publishedEntry","fields","entryUpdatedAt","Date","updatedAt","getTime","publishedEntryUpdatedAt","collectRelationTargets","modelUid","visited","Set","targets","has","add","model","attributes","attribute","Object","values","type","target","component","t","components","compUid","getPublishOrderForContentTypes","contentTypeUids","uidSet","dependencies","Map","uid","contentTypesUtils","hasDraftAndPublish","relationTargets","targetUid","targetContentTypeUid","isTargetInRelease","contentTypes","targetModel","targetHasDraftAndPublish","dependencySet","set","sorted","visiting","visit","dep","delete","push"],"mappings":"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"}
@@ -21,8 +21,18 @@ const getDraftEntryValidStatus = async ({ contentType, documentId, locale }, { s
21
21
  };
22
22
  const isEntryValid = async (contentTypeUid, entry, { strapi: strapi1 })=>{
23
23
  try {
24
+ // Mirror the document-service publish path: when `api.documents.strictRelations`
25
+ // is on, required media/relations are enforced on non-draft writes. Reading the
26
+ // flag here keeps the release "valid" badge consistent with what publish will
27
+ // actually accept (otherwise the UI can mark an entry valid that publish rejects).
28
+ const rawStrictRelations = strapi1.config.get('api.documents.strictRelations', undefined);
29
+ const strictRelations = rawStrictRelations === true;
24
30
  // @TODO: When documents service has validateEntityCreation method, use it instead
25
- await strapi1.entityValidator.validateEntityCreation(strapi1.getModel(contentTypeUid), entry, undefined, // @ts-expect-error - FIXME: entity here is unnecessary
31
+ await strapi1.entityValidator.validateEntityCreation(strapi1.getModel(contentTypeUid), entry, {
32
+ isDraft: false,
33
+ locale: entry?.locale,
34
+ strictRelations
35
+ }, // @ts-expect-error - FIXME: entity here is unnecessary
26
36
  entry);
27
37
  const workflowsService = strapi1.plugin('review-workflows').service('workflows');
28
38
  // Workflows service may not be available depending on the license
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../server/src/utils/index.ts"],"sourcesContent":["import { contentTypes as contentTypesUtils } from '@strapi/utils';\n\nimport type { UID, Data, Core } from '@strapi/types';\n\nimport type { SettingsService } from '../services/settings';\nimport type { ReleaseService } from '../services/release';\nimport type { ReleaseActionService } from '../services/release-action';\n\ntype Services = {\n release: ReleaseService;\n 'release-validation': any;\n scheduling: any;\n 'release-action': ReleaseActionService;\n 'event-manager': any;\n settings: SettingsService;\n};\n\ninterface Action {\n contentType: UID.ContentType;\n documentId?: Data.DocumentID;\n locale?: string;\n}\n\nexport const getService = <TName extends keyof Services>(\n name: TName,\n { strapi }: { strapi: Core.Strapi }\n): Services[TName] => {\n return strapi.plugin('content-releases').service(name);\n};\n\nexport const getDraftEntryValidStatus = async (\n { contentType, documentId, locale }: Action,\n { strapi }: { strapi: Core.Strapi }\n) => {\n const populateBuilderService = strapi.plugin('content-manager').service('populate-builder');\n // @ts-expect-error - populateBuilderService should be a function but is returning service\n const populate = await populateBuilderService(contentType).populateDeep(Infinity).build();\n\n const entry = await getEntry({ contentType, documentId, locale, populate }, { strapi });\n\n return isEntryValid(contentType, entry, { strapi });\n};\n\nexport const isEntryValid = async (\n contentTypeUid: string,\n entry: any,\n { strapi }: { strapi: Core.Strapi }\n) => {\n try {\n // @TODO: When documents service has validateEntityCreation method, use it instead\n await strapi.entityValidator.validateEntityCreation(\n strapi.getModel(contentTypeUid as UID.ContentType),\n entry,\n undefined,\n // @ts-expect-error - FIXME: entity here is unnecessary\n entry\n );\n\n const workflowsService = strapi.plugin('review-workflows').service('workflows');\n // Workflows service may not be available depending on the license\n const workflow = await workflowsService?.getAssignedWorkflow(contentTypeUid, {\n populate: 'stageRequiredToPublish',\n });\n\n if (workflow?.stageRequiredToPublish) {\n return entry.strapi_stage.id === workflow.stageRequiredToPublish.id;\n }\n\n return true;\n } catch {\n return false;\n }\n};\n\nexport const getEntry = async (\n {\n contentType,\n documentId,\n locale,\n populate,\n status = 'draft',\n }: Action & { status?: 'draft' | 'published'; populate: any },\n { strapi }: { strapi: Core.Strapi }\n) => {\n if (documentId) {\n // Try to get an existing draft or published document\n const entry = await strapi\n .documents(contentType)\n .findOne({ documentId, locale, populate, status });\n\n // The document isn't published yet, but the action is to publish it, fetch the draft\n if (status === 'published' && !entry) {\n return strapi\n .documents(contentType)\n .findOne({ documentId, locale, populate, status: 'draft' });\n }\n\n return entry;\n }\n\n return strapi.documents(contentType).findFirst({ locale, populate, status });\n};\n\nexport const getEntryStatus = async (contentType: UID.ContentType, entry: Data.ContentType) => {\n if (entry.publishedAt) {\n return 'published';\n }\n\n const publishedEntry = await strapi.documents(contentType).findOne({\n documentId: entry.documentId,\n locale: entry.locale,\n status: 'published',\n fields: ['updatedAt'],\n });\n\n if (!publishedEntry) {\n return 'draft';\n }\n\n const entryUpdatedAt = new Date(entry.updatedAt).getTime();\n const publishedEntryUpdatedAt = new Date(publishedEntry.updatedAt).getTime();\n\n if (entryUpdatedAt > publishedEntryUpdatedAt) {\n return 'modified';\n }\n\n return 'published';\n};\n\n/**\n * Recursively collects content type UIDs that a model (content type or component) has relations to.\n * Go through component and dynamic zone attributes to find nested relations.\n */\nconst collectRelationTargets = (\n modelUid: string,\n strapi: Core.Strapi,\n visited = new Set<string>()\n): Set<string> => {\n const targets = new Set<string>();\n if (visited.has(modelUid)) {\n return targets;\n }\n visited.add(modelUid);\n\n const model = strapi.getModel(modelUid as UID.Schema);\n if (!model?.attributes) {\n return targets;\n }\n\n for (const attribute of Object.values(model.attributes) as Array<{\n type?: string;\n target?: string;\n component?: string;\n components?: string[];\n }>) {\n if (attribute?.type === 'relation' && attribute.target) {\n targets.add(attribute.target);\n }\n if (attribute?.type === 'component' && attribute.component) {\n for (const t of collectRelationTargets(attribute.component, strapi, visited)) {\n targets.add(t);\n }\n }\n if (attribute?.type === 'dynamiczone' && attribute.components) {\n for (const compUid of attribute.components) {\n for (const t of collectRelationTargets(compUid, strapi, visited)) {\n targets.add(t);\n }\n }\n }\n }\n return targets;\n};\n\n/**\n * Returns content type UIDs sorted by relation dependency order for publishing.\n * When content type A has a relation to content type B (both with draft & publish),\n * B will appear before A in the result. This ensures that when publishing a release,\n * related entities are published first, so that relation IDs can be correctly\n * resolved (published target must exist when publishing source).\n *\n * Relations in components (nested or not) and dynamic zones are also considered.\n *\n * @param contentTypeUids - Content type UIDs that will be published in the release\n * @param strapi - Strapi instance\n * @returns Content type UIDs in publish order (dependencies first)\n */\nexport const getPublishOrderForContentTypes = (\n contentTypeUids: UID.ContentType[],\n { strapi }: { strapi: Core.Strapi }\n): UID.ContentType[] => {\n const uidSet = new Set(contentTypeUids);\n\n // Build dependency graph: source depends on target (source must be published after target)\n const dependencies = new Map<UID.ContentType, Set<UID.ContentType>>();\n\n for (const uid of contentTypeUids) {\n const model = strapi.getModel(uid);\n if (model && contentTypesUtils.hasDraftAndPublish(model)) {\n const relationTargets = collectRelationTargets(uid, strapi);\n\n for (const targetUid of relationTargets) {\n const targetContentTypeUid = targetUid as UID.ContentType;\n const isTargetInRelease =\n uidSet.has(targetContentTypeUid) && targetContentTypeUid in strapi.contentTypes;\n const targetModel = strapi.getModel(targetContentTypeUid);\n const targetHasDraftAndPublish =\n targetModel && contentTypesUtils.hasDraftAndPublish(targetModel);\n\n if (isTargetInRelease && targetHasDraftAndPublish) {\n let dependencySet = dependencies.get(uid);\n if (!dependencySet) {\n dependencySet = new Set();\n dependencies.set(uid, dependencySet);\n }\n dependencySet.add(targetContentTypeUid);\n }\n }\n }\n }\n\n // Topological sort: dependencies first\n const sorted: UID.ContentType[] = [];\n const visited = new Set<UID.ContentType>();\n const visiting = new Set<UID.ContentType>();\n\n const visit = (uid: UID.ContentType) => {\n if (visited.has(uid)) return;\n if (visiting.has(uid)) return; // No cycle in valid schemas\n\n visiting.add(uid);\n for (const dep of dependencies.get(uid) ?? []) {\n visit(dep);\n }\n visiting.delete(uid);\n visited.add(uid);\n sorted.push(uid);\n };\n\n for (const uid of contentTypeUids) {\n visit(uid);\n }\n\n return sorted;\n};\n"],"names":["getService","name","strapi","plugin","service","getDraftEntryValidStatus","contentType","documentId","locale","populateBuilderService","populate","populateDeep","Infinity","build","entry","getEntry","isEntryValid","contentTypeUid","entityValidator","validateEntityCreation","getModel","undefined","workflowsService","workflow","getAssignedWorkflow","stageRequiredToPublish","strapi_stage","id","status","documents","findOne","findFirst","getEntryStatus","publishedAt","publishedEntry","fields","entryUpdatedAt","Date","updatedAt","getTime","publishedEntryUpdatedAt","collectRelationTargets","modelUid","visited","Set","targets","has","add","model","attributes","attribute","Object","values","type","target","component","t","components","compUid","getPublishOrderForContentTypes","contentTypeUids","uidSet","dependencies","Map","uid","contentTypesUtils","hasDraftAndPublish","relationTargets","targetUid","targetContentTypeUid","isTargetInRelease","contentTypes","targetModel","targetHasDraftAndPublish","dependencySet","get","set","sorted","visiting","visit","dep","delete","push"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../server/src/utils/index.ts"],"sourcesContent":["import { contentTypes as contentTypesUtils } from '@strapi/utils';\n\nimport type { UID, Data, Core } from '@strapi/types';\n\nimport type { SettingsService } from '../services/settings';\nimport type { ReleaseService } from '../services/release';\nimport type { ReleaseActionService } from '../services/release-action';\n\ntype Services = {\n release: ReleaseService;\n 'release-validation': any;\n scheduling: any;\n 'release-action': ReleaseActionService;\n 'event-manager': any;\n settings: SettingsService;\n};\n\ninterface Action {\n contentType: UID.ContentType;\n documentId?: Data.DocumentID;\n locale?: string;\n}\n\nexport const getService = <TName extends keyof Services>(\n name: TName,\n { strapi }: { strapi: Core.Strapi }\n): Services[TName] => {\n return strapi.plugin('content-releases').service(name);\n};\n\nexport const getDraftEntryValidStatus = async (\n { contentType, documentId, locale }: Action,\n { strapi }: { strapi: Core.Strapi }\n) => {\n const populateBuilderService = strapi.plugin('content-manager').service('populate-builder');\n // @ts-expect-error - populateBuilderService should be a function but is returning service\n const populate = await populateBuilderService(contentType).populateDeep(Infinity).build();\n\n const entry = await getEntry({ contentType, documentId, locale, populate }, { strapi });\n\n return isEntryValid(contentType, entry, { strapi });\n};\n\nexport const isEntryValid = async (\n contentTypeUid: string,\n entry: any,\n { strapi }: { strapi: Core.Strapi }\n) => {\n try {\n // Mirror the document-service publish path: when `api.documents.strictRelations`\n // is on, required media/relations are enforced on non-draft writes. Reading the\n // flag here keeps the release \"valid\" badge consistent with what publish will\n // actually accept (otherwise the UI can mark an entry valid that publish rejects).\n const rawStrictRelations: unknown = strapi.config.get(\n 'api.documents.strictRelations',\n undefined\n );\n const strictRelations = rawStrictRelations === true;\n\n // @TODO: When documents service has validateEntityCreation method, use it instead\n await strapi.entityValidator.validateEntityCreation(\n strapi.getModel(contentTypeUid as UID.ContentType),\n entry,\n { isDraft: false, locale: entry?.locale, strictRelations },\n // @ts-expect-error - FIXME: entity here is unnecessary\n entry\n );\n\n const workflowsService = strapi.plugin('review-workflows').service('workflows');\n // Workflows service may not be available depending on the license\n const workflow = await workflowsService?.getAssignedWorkflow(contentTypeUid, {\n populate: 'stageRequiredToPublish',\n });\n\n if (workflow?.stageRequiredToPublish) {\n return entry.strapi_stage.id === workflow.stageRequiredToPublish.id;\n }\n\n return true;\n } catch {\n return false;\n }\n};\n\nexport const getEntry = async (\n {\n contentType,\n documentId,\n locale,\n populate,\n status = 'draft',\n }: Action & { status?: 'draft' | 'published'; populate: any },\n { strapi }: { strapi: Core.Strapi }\n) => {\n if (documentId) {\n // Try to get an existing draft or published document\n const entry = await strapi\n .documents(contentType)\n .findOne({ documentId, locale, populate, status });\n\n // The document isn't published yet, but the action is to publish it, fetch the draft\n if (status === 'published' && !entry) {\n return strapi\n .documents(contentType)\n .findOne({ documentId, locale, populate, status: 'draft' });\n }\n\n return entry;\n }\n\n return strapi.documents(contentType).findFirst({ locale, populate, status });\n};\n\nexport const getEntryStatus = async (contentType: UID.ContentType, entry: Data.ContentType) => {\n if (entry.publishedAt) {\n return 'published';\n }\n\n const publishedEntry = await strapi.documents(contentType).findOne({\n documentId: entry.documentId,\n locale: entry.locale,\n status: 'published',\n fields: ['updatedAt'],\n });\n\n if (!publishedEntry) {\n return 'draft';\n }\n\n const entryUpdatedAt = new Date(entry.updatedAt).getTime();\n const publishedEntryUpdatedAt = new Date(publishedEntry.updatedAt).getTime();\n\n if (entryUpdatedAt > publishedEntryUpdatedAt) {\n return 'modified';\n }\n\n return 'published';\n};\n\n/**\n * Recursively collects content type UIDs that a model (content type or component) has relations to.\n * Go through component and dynamic zone attributes to find nested relations.\n */\nconst collectRelationTargets = (\n modelUid: string,\n strapi: Core.Strapi,\n visited = new Set<string>()\n): Set<string> => {\n const targets = new Set<string>();\n if (visited.has(modelUid)) {\n return targets;\n }\n visited.add(modelUid);\n\n const model = strapi.getModel(modelUid as UID.Schema);\n if (!model?.attributes) {\n return targets;\n }\n\n for (const attribute of Object.values(model.attributes) as Array<{\n type?: string;\n target?: string;\n component?: string;\n components?: string[];\n }>) {\n if (attribute?.type === 'relation' && attribute.target) {\n targets.add(attribute.target);\n }\n if (attribute?.type === 'component' && attribute.component) {\n for (const t of collectRelationTargets(attribute.component, strapi, visited)) {\n targets.add(t);\n }\n }\n if (attribute?.type === 'dynamiczone' && attribute.components) {\n for (const compUid of attribute.components) {\n for (const t of collectRelationTargets(compUid, strapi, visited)) {\n targets.add(t);\n }\n }\n }\n }\n return targets;\n};\n\n/**\n * Returns content type UIDs sorted by relation dependency order for publishing.\n * When content type A has a relation to content type B (both with draft & publish),\n * B will appear before A in the result. This ensures that when publishing a release,\n * related entities are published first, so that relation IDs can be correctly\n * resolved (published target must exist when publishing source).\n *\n * Relations in components (nested or not) and dynamic zones are also considered.\n *\n * @param contentTypeUids - Content type UIDs that will be published in the release\n * @param strapi - Strapi instance\n * @returns Content type UIDs in publish order (dependencies first)\n */\nexport const getPublishOrderForContentTypes = (\n contentTypeUids: UID.ContentType[],\n { strapi }: { strapi: Core.Strapi }\n): UID.ContentType[] => {\n const uidSet = new Set(contentTypeUids);\n\n // Build dependency graph: source depends on target (source must be published after target)\n const dependencies = new Map<UID.ContentType, Set<UID.ContentType>>();\n\n for (const uid of contentTypeUids) {\n const model = strapi.getModel(uid);\n if (model && contentTypesUtils.hasDraftAndPublish(model)) {\n const relationTargets = collectRelationTargets(uid, strapi);\n\n for (const targetUid of relationTargets) {\n const targetContentTypeUid = targetUid as UID.ContentType;\n const isTargetInRelease =\n uidSet.has(targetContentTypeUid) && targetContentTypeUid in strapi.contentTypes;\n const targetModel = strapi.getModel(targetContentTypeUid);\n const targetHasDraftAndPublish =\n targetModel && contentTypesUtils.hasDraftAndPublish(targetModel);\n\n if (isTargetInRelease && targetHasDraftAndPublish) {\n let dependencySet = dependencies.get(uid);\n if (!dependencySet) {\n dependencySet = new Set();\n dependencies.set(uid, dependencySet);\n }\n dependencySet.add(targetContentTypeUid);\n }\n }\n }\n }\n\n // Topological sort: dependencies first\n const sorted: UID.ContentType[] = [];\n const visited = new Set<UID.ContentType>();\n const visiting = new Set<UID.ContentType>();\n\n const visit = (uid: UID.ContentType) => {\n if (visited.has(uid)) return;\n if (visiting.has(uid)) return; // No cycle in valid schemas\n\n visiting.add(uid);\n for (const dep of dependencies.get(uid) ?? []) {\n visit(dep);\n }\n visiting.delete(uid);\n visited.add(uid);\n sorted.push(uid);\n };\n\n for (const uid of contentTypeUids) {\n visit(uid);\n }\n\n return sorted;\n};\n"],"names":["getService","name","strapi","plugin","service","getDraftEntryValidStatus","contentType","documentId","locale","populateBuilderService","populate","populateDeep","Infinity","build","entry","getEntry","isEntryValid","contentTypeUid","rawStrictRelations","config","get","undefined","strictRelations","entityValidator","validateEntityCreation","getModel","isDraft","workflowsService","workflow","getAssignedWorkflow","stageRequiredToPublish","strapi_stage","id","status","documents","findOne","findFirst","getEntryStatus","publishedAt","publishedEntry","fields","entryUpdatedAt","Date","updatedAt","getTime","publishedEntryUpdatedAt","collectRelationTargets","modelUid","visited","Set","targets","has","add","model","attributes","attribute","Object","values","type","target","component","t","components","compUid","getPublishOrderForContentTypes","contentTypeUids","uidSet","dependencies","Map","uid","contentTypesUtils","hasDraftAndPublish","relationTargets","targetUid","targetContentTypeUid","isTargetInRelease","contentTypes","targetModel","targetHasDraftAndPublish","dependencySet","set","sorted","visiting","visit","dep","delete","push"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/content-releases",
3
- "version": "5.50.2",
3
+ "version": "5.51.1",
4
4
  "description": "Strapi plugin for organizing and releasing content",
5
5
  "homepage": "https://strapi.io",
6
6
  "bugs": {
@@ -64,11 +64,11 @@
64
64
  },
65
65
  "dependencies": {
66
66
  "@reduxjs/toolkit": "1.9.7",
67
- "@strapi/database": "5.50.2",
67
+ "@strapi/database": "5.51.1",
68
68
  "@strapi/design-system": "2.2.3",
69
69
  "@strapi/icons": "2.2.3",
70
- "@strapi/types": "5.50.2",
71
- "@strapi/utils": "5.50.2",
70
+ "@strapi/types": "5.51.1",
71
+ "@strapi/utils": "5.51.1",
72
72
  "date-fns": "2.30.0",
73
73
  "date-fns-tz": "2.0.1",
74
74
  "formik": "2.4.9",
@@ -79,9 +79,9 @@
79
79
  "yup": "0.32.9"
80
80
  },
81
81
  "devDependencies": {
82
- "@strapi/admin": "5.50.2",
83
- "@strapi/admin-test-utils": "5.50.2",
84
- "@strapi/content-manager": "5.50.2",
82
+ "@strapi/admin": "5.51.1",
83
+ "@strapi/admin-test-utils": "5.51.1",
84
+ "@strapi/content-manager": "5.51.1",
85
85
  "@testing-library/dom": "10.4.1",
86
86
  "@testing-library/jest-dom": "6.9.1",
87
87
  "@testing-library/react": "16.3.2",