@strapi/review-workflows 0.0.0-next.3fdd03038d558a8190aa7e17574020c5f65395e6 → 0.0.0-next.4119cc523a8fec549bb2f1869c6e789650f7f4de

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 (64) hide show
  1. package/dist/_chunks/{Layout-8i0EXRRs.js → Layout-B4fpKB9J.js} +3 -3
  2. package/dist/_chunks/Layout-B4fpKB9J.js.map +1 -0
  3. package/dist/_chunks/{Layout-C9m07iTY.mjs → Layout-Dko22Aly.mjs} +3 -3
  4. package/dist/_chunks/Layout-Dko22Aly.mjs.map +1 -0
  5. package/dist/_chunks/{en-xcewH2pC.js → en-CYgjfSep.js} +5 -2
  6. package/dist/_chunks/en-CYgjfSep.js.map +1 -0
  7. package/dist/_chunks/{en-D9ZrQAV6.mjs → en-D9dxziEb.mjs} +5 -2
  8. package/dist/_chunks/en-D9dxziEb.mjs.map +1 -0
  9. package/dist/_chunks/{id-CmtaTf1x.js → id-BKq7JAqZ.js} +73 -13
  10. package/dist/_chunks/id-BKq7JAqZ.js.map +1 -0
  11. package/dist/_chunks/{id-DV0Ndeav.mjs → id-DINFSsrh.mjs} +73 -13
  12. package/dist/_chunks/id-DINFSsrh.mjs.map +1 -0
  13. package/dist/_chunks/{index-B8WmHbCU.js → index-BpIILEs0.js} +3 -3
  14. package/dist/_chunks/{index-B8WmHbCU.js.map → index-BpIILEs0.js.map} +1 -1
  15. package/dist/_chunks/{index-BCUO98DV.js → index-BpL7C1EG.js} +3 -3
  16. package/dist/_chunks/{index-BCUO98DV.js.map → index-BpL7C1EG.js.map} +1 -1
  17. package/dist/_chunks/{index-CqYVkW3E.mjs → index-DAcEdoqJ.mjs} +3 -3
  18. package/dist/_chunks/{index-CqYVkW3E.mjs.map → index-DAcEdoqJ.mjs.map} +1 -1
  19. package/dist/_chunks/{index-CA5Axcoc.mjs → index-ZcZKwmTD.mjs} +3 -3
  20. package/dist/_chunks/{index-CA5Axcoc.mjs.map → index-ZcZKwmTD.mjs.map} +1 -1
  21. package/dist/_chunks/{router-Jdt6SbIA.mjs → router-BPH_u176.mjs} +3 -3
  22. package/dist/_chunks/{router-Jdt6SbIA.mjs.map → router-BPH_u176.mjs.map} +1 -1
  23. package/dist/_chunks/{router-BOXlNnrU.js → router-DeEgX8Ao.js} +3 -3
  24. package/dist/_chunks/{router-BOXlNnrU.js.map → router-DeEgX8Ao.js.map} +1 -1
  25. package/dist/admin/index.js +1 -1
  26. package/dist/admin/index.mjs +1 -1
  27. package/dist/admin/src/services/settings.d.ts +7 -3
  28. package/dist/server/index.js +107 -48
  29. package/dist/server/index.js.map +1 -1
  30. package/dist/server/index.mjs +107 -48
  31. package/dist/server/index.mjs.map +1 -1
  32. package/dist/server/src/bootstrap.d.ts.map +1 -1
  33. package/dist/server/src/constants/workflows.d.ts +1 -0
  34. package/dist/server/src/constants/workflows.d.ts.map +1 -1
  35. package/dist/server/src/content-types/index.d.ts +6 -0
  36. package/dist/server/src/content-types/index.d.ts.map +1 -1
  37. package/dist/server/src/content-types/workflow/index.d.ts +6 -0
  38. package/dist/server/src/content-types/workflow/index.d.ts.map +1 -1
  39. package/dist/server/src/controllers/assignees.d.ts.map +1 -1
  40. package/dist/server/src/controllers/stages.d.ts.map +1 -1
  41. package/dist/server/src/index.d.ts +28 -6
  42. package/dist/server/src/index.d.ts.map +1 -1
  43. package/dist/server/src/services/assignees.d.ts +8 -4
  44. package/dist/server/src/services/assignees.d.ts.map +1 -1
  45. package/dist/server/src/services/document-service-middleware.d.ts +1 -0
  46. package/dist/server/src/services/document-service-middleware.d.ts.map +1 -1
  47. package/dist/server/src/services/index.d.ts +16 -6
  48. package/dist/server/src/services/index.d.ts.map +1 -1
  49. package/dist/server/src/services/metrics/index.d.ts +4 -4
  50. package/dist/server/src/services/metrics/index.d.ts.map +1 -1
  51. package/dist/server/src/services/stages.d.ts +6 -1
  52. package/dist/server/src/services/stages.d.ts.map +1 -1
  53. package/dist/server/src/services/workflows.d.ts.map +1 -1
  54. package/dist/server/src/validation/review-workflows.d.ts +4 -0
  55. package/dist/server/src/validation/review-workflows.d.ts.map +1 -1
  56. package/dist/shared/contracts/review-workflows.d.ts +8 -3
  57. package/dist/shared/contracts/review-workflows.d.ts.map +1 -1
  58. package/package.json +8 -8
  59. package/dist/_chunks/Layout-8i0EXRRs.js.map +0 -1
  60. package/dist/_chunks/Layout-C9m07iTY.mjs.map +0 -1
  61. package/dist/_chunks/en-D9ZrQAV6.mjs.map +0 -1
  62. package/dist/_chunks/en-xcewH2pC.js.map +0 -1
  63. package/dist/_chunks/id-CmtaTf1x.js.map +0 -1
  64. package/dist/_chunks/id-DV0Ndeav.mjs.map +0 -1
@@ -6386,7 +6386,8 @@ const WORKFLOW_POPULATE = {
6386
6386
  }
6387
6387
  }
6388
6388
  }
6389
- }
6389
+ },
6390
+ stageRequiredToPublish: true
6390
6391
  };
6391
6392
  function checkVersionThreshold(startVersion, currentVersion, thresholdVersion) {
6392
6393
  return semver$1.gte(currentVersion, thresholdVersion) && semver$1.lt(startVersion, thresholdVersion);
@@ -6639,6 +6640,12 @@ const workflow = {
6639
6640
  relation: "oneToMany",
6640
6641
  mappedBy: "workflow"
6641
6642
  },
6643
+ stageRequiredToPublish: {
6644
+ type: "relation",
6645
+ target: "plugin::review-workflows.workflow-stage",
6646
+ relation: "oneToOne",
6647
+ required: false
6648
+ },
6642
6649
  contentTypes: {
6643
6650
  type: "json",
6644
6651
  required: true,
@@ -6788,6 +6795,7 @@ const bootstrap = async (args) => {
6788
6795
  const docsMiddlewares = getService("document-service-middlewares");
6789
6796
  strapi.documents.use(docsMiddlewares.assignStageOnCreate);
6790
6797
  strapi.documents.use(docsMiddlewares.handleStageOnUpdate);
6798
+ strapi.documents.use(docsMiddlewares.checkStageBeforePublish);
6791
6799
  };
6792
6800
  const destroy = async ({ strapi: strapi2 }) => {
6793
6801
  };
@@ -7020,9 +7028,9 @@ const processFilters = ({ strapi: strapi2 }, filters = {}) => {
7020
7028
  };
7021
7029
  const processPopulate = (populate) => {
7022
7030
  if (!populate) {
7023
- return populate;
7031
+ return WORKFLOW_POPULATE;
7024
7032
  }
7025
- return WORKFLOW_POPULATE;
7033
+ return populate;
7026
7034
  };
7027
7035
  const workflows$1 = ({ strapi: strapi2 }) => {
7028
7036
  const workflowsContentTypes = workflowsContentTypesFactory({ strapi: strapi2 });
@@ -7073,14 +7081,27 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7073
7081
  const stages2 = await getService("stages", { strapi: strapi2 }).createMany(opts.data.stages);
7074
7082
  const mapIds = fp.map(fp.get("id"));
7075
7083
  createOpts = fp.set("data.stages", mapIds(stages2), createOpts);
7084
+ if (opts.data.stageRequiredToPublishName) {
7085
+ const stageRequiredToPublish = stages2.find(
7086
+ (stage) => stage.name === opts.data.stageRequiredToPublishName
7087
+ );
7088
+ if (!stageRequiredToPublish) {
7089
+ throw new errors.ApplicationError("Stage required to publish does not exist");
7090
+ }
7091
+ createOpts = fp.set("data.stageRequiredToPublish", stageRequiredToPublish.id, createOpts);
7092
+ }
7076
7093
  if (opts.data.contentTypes) {
7077
7094
  await workflowsContentTypes.migrate({
7078
7095
  destContentTypes: opts.data.contentTypes,
7079
7096
  stageId: stages2[0].id
7080
7097
  });
7081
7098
  }
7082
- metrics.sendDidCreateWorkflow();
7083
- return strapi2.db.query(WORKFLOW_MODEL_UID).create(strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, createOpts));
7099
+ const createdWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).create(strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, createOpts));
7100
+ metrics.sendDidCreateWorkflow(createdWorkflow.id, !!opts.data.stageRequiredToPublishName);
7101
+ if (opts.data.stageRequiredToPublishName) {
7102
+ await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes(opts.data.contentTypes);
7103
+ }
7104
+ return createdWorkflow;
7084
7105
  });
7085
7106
  },
7086
7107
  /**
@@ -7093,6 +7114,7 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7093
7114
  async update(workflow2, opts) {
7094
7115
  const stageService = getService("stages", { strapi: strapi2 });
7095
7116
  let updateOpts = { ...opts, populate: { ...WORKFLOW_POPULATE } };
7117
+ let updatedStages = [];
7096
7118
  let updatedStageIds;
7097
7119
  await workflowValidator.validateWorkflowCount();
7098
7120
  return strapi2.db.transaction(async () => {
@@ -7101,9 +7123,28 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7101
7123
  opts.data.stages.forEach(
7102
7124
  (stage) => this.assertStageBelongsToWorkflow(stage.id, workflow2)
7103
7125
  );
7104
- updatedStageIds = await stageService.replaceStages(workflow2.stages, opts.data.stages, workflow2.contentTypes).then((stages2) => stages2.map((stage) => stage.id));
7126
+ updatedStages = await stageService.replaceStages(
7127
+ workflow2.stages,
7128
+ opts.data.stages,
7129
+ workflow2.contentTypes
7130
+ );
7131
+ updatedStageIds = updatedStages.map((stage) => stage.id);
7105
7132
  updateOpts = fp.set("data.stages", updatedStageIds, updateOpts);
7106
7133
  }
7134
+ if (opts.data.stageRequiredToPublishName !== void 0) {
7135
+ const stages2 = updatedStages ?? workflow2.stages;
7136
+ if (opts.data.stageRequiredToPublishName === null) {
7137
+ updateOpts = fp.set("data.stageRequiredToPublish", null, updateOpts);
7138
+ } else {
7139
+ const stageRequiredToPublish = stages2.find(
7140
+ (stage) => stage.name === opts.data.stageRequiredToPublishName
7141
+ );
7142
+ if (!stageRequiredToPublish) {
7143
+ throw new errors.ApplicationError("Stage required to publish does not exist");
7144
+ }
7145
+ updateOpts = fp.set("data.stageRequiredToPublish", stageRequiredToPublish.id, updateOpts);
7146
+ }
7147
+ }
7107
7148
  if (opts.data.contentTypes) {
7108
7149
  await workflowsContentTypes.migrate({
7109
7150
  srcContentTypes: workflow2.contentTypes,
@@ -7111,12 +7152,17 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7111
7152
  stageId: updatedStageIds ? updatedStageIds[0] : workflow2.stages[0].id
7112
7153
  });
7113
7154
  }
7114
- metrics.sendDidEditWorkflow();
7155
+ metrics.sendDidEditWorkflow(workflow2.id, !!opts.data.stageRequiredToPublishName);
7115
7156
  const query = strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, updateOpts);
7116
- return strapi2.db.query(WORKFLOW_MODEL_UID).update({
7157
+ const updatedWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).update({
7117
7158
  ...query,
7118
7159
  where: { id: workflow2.id }
7119
7160
  });
7161
+ await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes([
7162
+ ...workflow2.contentTypes,
7163
+ ...opts.data.contentTypes || []
7164
+ ]);
7165
+ return updatedWorkflow;
7120
7166
  });
7121
7167
  },
7122
7168
  /**
@@ -7139,10 +7185,12 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7139
7185
  destContentTypes: []
7140
7186
  });
7141
7187
  const query = strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, opts);
7142
- return strapi2.db.query(WORKFLOW_MODEL_UID).delete({
7188
+ const deletedWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).delete({
7143
7189
  ...query,
7144
7190
  where: { id: workflow2.id }
7145
7191
  });
7192
+ await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes(workflow2.contentTypes);
7193
+ return deletedWorkflow;
7146
7194
  });
7147
7195
  },
7148
7196
  /**
@@ -7354,8 +7402,9 @@ const stages$1 = ({ strapi: strapi2 }) => {
7354
7402
  /**
7355
7403
  * Update the stage of an entity
7356
7404
  */
7357
- async updateEntity(documentId, locale, model, stageId) {
7405
+ async updateEntity(entityToUpdate, model, stageId) {
7358
7406
  const stage = await this.findById(stageId);
7407
+ const { documentId, locale } = entityToUpdate;
7359
7408
  await workflowValidator.validateWorkflowCount();
7360
7409
  if (!stage) {
7361
7410
  throw new ApplicationError$2(`Selected stage does not exist`);
@@ -7368,6 +7417,10 @@ const stages$1 = ({ strapi: strapi2 }) => {
7368
7417
  data: { [ENTITY_STAGE_ATTRIBUTE]: fp.pick(["id"], stage) },
7369
7418
  populate: [ENTITY_STAGE_ATTRIBUTE]
7370
7419
  });
7420
+ const { tableName } = strapi2.db.metadata.get(model);
7421
+ await strapi2.db.connection(tableName).where({ id: entityToUpdate.id }).update({
7422
+ updated_at: new Date(entityToUpdate.updatedAt)
7423
+ });
7371
7424
  metrics.sendDidChangeEntryStage();
7372
7425
  return entity;
7373
7426
  },
@@ -7514,32 +7567,28 @@ const assignees$1 = ({ strapi: strapi2 }) => {
7514
7567
  /**
7515
7568
  * Update the assignee of an entity
7516
7569
  */
7517
- async updateEntityAssignee(documentId, locale, model, assigneeId) {
7518
- if (fp.isNil(assigneeId)) {
7519
- return this.deleteEntityAssignee(documentId, locale, model);
7520
- }
7521
- const userExists = await getAdminService("user", { strapi: strapi2 }).exists({ id: assigneeId });
7522
- if (!userExists) {
7523
- throw new ApplicationError(`Selected user does not exist`);
7570
+ async updateEntityAssignee(entityToUpdate, model, assigneeId) {
7571
+ const { documentId, locale } = entityToUpdate;
7572
+ if (!fp.isNil(assigneeId)) {
7573
+ const userExists = await getAdminService("user", { strapi: strapi2 }).exists({ id: assigneeId });
7574
+ if (!userExists) {
7575
+ throw new ApplicationError(`Selected user does not exist`);
7576
+ }
7524
7577
  }
7525
- metrics.sendDidEditAssignee(await this.findEntityAssigneeId(documentId, model), assigneeId);
7526
- return strapi2.documents(model).update({
7578
+ const oldAssigneeId = await this.findEntityAssigneeId(entityToUpdate.id, model);
7579
+ metrics.sendDidEditAssignee(oldAssigneeId, assigneeId || null);
7580
+ const entity = await strapi2.documents(model).update({
7527
7581
  documentId,
7528
7582
  locale,
7529
- data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: assigneeId },
7583
+ data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: assigneeId || null },
7530
7584
  populate: [ENTITY_ASSIGNEE_ATTRIBUTE],
7531
7585
  fields: []
7532
7586
  });
7533
- },
7534
- async deleteEntityAssignee(documentId, locale, model) {
7535
- metrics.sendDidEditAssignee(await this.findEntityAssigneeId(documentId, model), null);
7536
- return strapi2.documents(model).update({
7537
- documentId,
7538
- locale,
7539
- data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: null },
7540
- populate: [ENTITY_ASSIGNEE_ATTRIBUTE],
7541
- fields: []
7587
+ const { tableName } = strapi2.db.metadata.get(model);
7588
+ await strapi2.db.connection(tableName).where({ id: entityToUpdate.id }).update({
7589
+ updated_at: new Date(entityToUpdate.updatedAt)
7542
7590
  });
7591
+ return entity;
7543
7592
  }
7544
7593
  };
7545
7594
  };
@@ -7612,11 +7661,11 @@ const sendDidDeleteStage = async () => {
7612
7661
  const sendDidChangeEntryStage = async () => {
7613
7662
  strapi.telemetry.send("didChangeEntryStage", {});
7614
7663
  };
7615
- const sendDidCreateWorkflow = async () => {
7616
- strapi.telemetry.send("didCreateWorkflow", {});
7664
+ const sendDidCreateWorkflow = async (workflowId, hasRequiredStageToPublish) => {
7665
+ strapi.telemetry.send("didCreateWorkflow", { workflowId, hasRequiredStageToPublish });
7617
7666
  };
7618
- const sendDidEditWorkflow = async () => {
7619
- strapi.telemetry.send("didEditWorkflow", {});
7667
+ const sendDidEditWorkflow = async (workflowId, hasRequiredStageToPublish) => {
7668
+ strapi.telemetry.send("didEditWorkflow", { workflowId, hasRequiredStageToPublish });
7620
7669
  };
7621
7670
  const sendDidEditAssignee = async (fromId, toId) => {
7622
7671
  strapi.telemetry.send("didEditAssignee", { from: fromId, to: toId });
@@ -7869,9 +7918,27 @@ const handleStageOnUpdate = async (ctx, next) => {
7869
7918
  }
7870
7919
  return next();
7871
7920
  };
7921
+ const checkStageBeforePublish = async (ctx, next) => {
7922
+ if (ctx.action !== "publish") {
7923
+ return next();
7924
+ }
7925
+ const workflow2 = await getService("workflows").getAssignedWorkflow(ctx.contentType.uid, {
7926
+ populate: "stageRequiredToPublish"
7927
+ });
7928
+ if (!workflow2 || !workflow2.stageRequiredToPublish) {
7929
+ return next();
7930
+ }
7931
+ const { documentId } = ctx.params;
7932
+ const entryStage = await getEntityStage(ctx.contentType.uid, documentId, ctx.params);
7933
+ if (entryStage.id !== workflow2.stageRequiredToPublish.id) {
7934
+ throw new errors.ValidationError("Entry is not at the required stage to publish");
7935
+ }
7936
+ return next();
7937
+ };
7872
7938
  const documentServiceMiddleware = () => ({
7873
7939
  assignStageOnCreate,
7874
- handleStageOnUpdate
7940
+ handleStageOnUpdate,
7941
+ checkStageBeforePublish
7875
7942
  });
7876
7943
  const services = {
7877
7944
  workflows: workflows$1,
@@ -7921,12 +7988,14 @@ const validateContentTypes = yup.array().of(
7921
7988
  const validateWorkflowCreateSchema = yup.object().shape({
7922
7989
  name: yup.string().max(255).min(1, "Workflow name can not be empty").required(),
7923
7990
  stages: yup.array().of(stageObject).uniqueProperty("name", "Stage name must be unique").min(1, "Can not create a workflow without stages").max(200, "Can not have more than 200 stages").required("Can not create a workflow without stages"),
7924
- contentTypes: validateContentTypes
7991
+ contentTypes: validateContentTypes,
7992
+ stageRequiredToPublishName: yup.string().min(1).nullable()
7925
7993
  });
7926
7994
  const validateWorkflowUpdateSchema = yup.object().shape({
7927
7995
  name: yup.string().max(255).min(1, "Workflow name can not be empty"),
7928
7996
  stages: yup.array().of(stageObject).uniqueProperty("name", "Stage name must be unique").min(1, "Can not update a workflow without stages").max(200, "Can not have more than 200 stages"),
7929
- contentTypes: validateContentTypes
7997
+ contentTypes: validateContentTypes,
7998
+ stageRequiredToPublishName: yup.string().min(1).nullable()
7930
7999
  });
7931
8000
  const validateUpdateAssigneeOnEntitySchema = yup.object().shape({
7932
8001
  id: yup.number().integer().min(1).nullable()
@@ -8129,12 +8198,7 @@ const stages = {
8129
8198
  );
8130
8199
  const workflow2 = await workflowService.assertContentTypeBelongsToWorkflow(modelUID);
8131
8200
  workflowService.assertStageBelongsToWorkflow(stageId, workflow2);
8132
- const updatedEntity = await stagesService.updateEntity(
8133
- entity.documentId,
8134
- entity.locale,
8135
- modelUID,
8136
- stageId
8137
- );
8201
+ const updatedEntity = await stagesService.updateEntity(entity, modelUID, stageId);
8138
8202
  ctx.body = { data: await sanitizeOutput(updatedEntity) };
8139
8203
  },
8140
8204
  /**
@@ -8231,12 +8295,7 @@ const assignees = {
8231
8295
  "You should pass a valid id to the body of the put request."
8232
8296
  );
8233
8297
  await workflowService.assertContentTypeBelongsToWorkflow(model);
8234
- const updatedEntity = await assigneeService.updateEntityAssignee(
8235
- documentId,
8236
- locale || null,
8237
- model,
8238
- assigneeId
8239
- );
8298
+ const updatedEntity = await assigneeService.updateEntityAssignee(entity, model, assigneeId);
8240
8299
  ctx.body = { data: await sanitizeOutput(updatedEntity) };
8241
8300
  }
8242
8301
  };