{"version":3,"file":"document-service-middleware.mjs","sources":["../../../server/src/services/document-service-middleware.ts"],"sourcesContent":["import type { Modules } from '@strapi/types';\nimport { errors } from '@strapi/utils';\n\nimport { isNil } from 'lodash/fp';\nimport { ENTITY_STAGE_ATTRIBUTE } from '../constants/workflows';\nimport { WORKFLOW_UPDATE_STAGE } from '../constants/webhook-events';\nimport { getService } from '../utils';\n\ntype Middleware = Modules.Documents.Middleware.Middleware;\n\n/**\n * Get the stage information of an entity\n * @param {String} uid\n * @param {Number} id\n * @returns {Object}\n */\nconst getEntityStage = async (uid: any, id: any, params: any) => {\n  const entity = await strapi.documents(uid).findOne({\n    ...params,\n    documentId: id,\n    status: 'draft',\n    populate: {\n      [ENTITY_STAGE_ATTRIBUTE]: {\n        populate: {\n          workflow: true,\n        },\n      },\n    },\n  });\n\n  return entity?.[ENTITY_STAGE_ATTRIBUTE] ?? {};\n};\n\n/**\n * Ensures the entity is assigned to the default workflow stage\n */\nconst assignStageOnCreate: Middleware = async (ctx, next) => {\n  if (ctx.action !== 'create' && ctx.action !== 'clone') {\n    return next();\n  }\n\n  /**\n   * Content types can have assigned workflows,\n   * if the CT has one, assign a default value to the stage attribute if it's not present\n   */\n  const workflow = await getService('workflows').getAssignedWorkflow(ctx.contentType.uid, {\n    populate: 'stages',\n  });\n\n  if (!workflow) {\n    return next();\n  }\n\n  const data = ctx.params.data as Record<string, any>;\n\n  // Assign the default stage if the entity doesn't have one\n  if (ctx.params?.data && isNil(data[ENTITY_STAGE_ATTRIBUTE])) {\n    data[ENTITY_STAGE_ATTRIBUTE] = { id: workflow.stages[0].id };\n  }\n\n  return next();\n};\n\nconst handleStageOnUpdate: Middleware = async (ctx, next) => {\n  if (ctx.action !== 'update') {\n    return next();\n  }\n\n  const { documentId } = ctx.params;\n  const data = ctx.params.data as any;\n\n  if (isNil(data?.[ENTITY_STAGE_ATTRIBUTE])) {\n    delete data?.[ENTITY_STAGE_ATTRIBUTE];\n    return next();\n  }\n\n  /**\n   * Get last stage of the entity\n   */\n  const previousStage = await getEntityStage(ctx.contentType.uid, documentId, ctx.params);\n\n  const result = await next();\n\n  if (!result) {\n    return result;\n  }\n\n  // @ts-expect-error\n  const updatedStage = result?.[ENTITY_STAGE_ATTRIBUTE];\n\n  // Stage might be null if field is not populated\n  if (updatedStage && previousStage?.id && previousStage.id !== updatedStage.id) {\n    const model = strapi.getModel(ctx.contentType.uid);\n\n    strapi.eventHub.emit(WORKFLOW_UPDATE_STAGE, {\n      model: model.modelName,\n      uid: model.uid,\n      // TODO v6: Rename to \"entry\", which is what is used for regular CRUD updates\n      entity: {\n        // @ts-expect-error\n        id: result?.id,\n        documentId,\n        // @ts-expect-error\n        locale: result?.locale,\n        status: 'draft',\n      },\n      workflow: {\n        id: previousStage.workflow.id,\n        stages: {\n          from: {\n            id: previousStage.id,\n            name: previousStage.name,\n          },\n          to: {\n            id: updatedStage.id,\n            name: updatedStage.name,\n          },\n        },\n      },\n    });\n  }\n\n  return next();\n};\n\n/**\n * Check if the entity is at the required stage before publish\n */\nconst checkStageBeforePublish: Middleware = async (ctx, next) => {\n  if (ctx.action !== 'publish') {\n    return next();\n  }\n\n  const workflow = await getService('workflows').getAssignedWorkflow(ctx.contentType.uid, {\n    populate: 'stageRequiredToPublish',\n  });\n\n  if (!workflow || !workflow.stageRequiredToPublish) {\n    return next();\n  }\n\n  const { documentId } = ctx.params;\n  const entryStage = await getEntityStage(ctx.contentType.uid, documentId, ctx.params);\n\n  if (entryStage.id !== workflow.stageRequiredToPublish.id) {\n    throw new errors.ValidationError('Entry is not at the required stage to publish');\n  }\n\n  return next();\n};\n\nexport default () => ({\n  assignStageOnCreate,\n  handleStageOnUpdate,\n  checkStageBeforePublish,\n});\n"],"names":["getEntityStage","uid","id","params","entity","strapi","documents","findOne","documentId","status","populate","ENTITY_STAGE_ATTRIBUTE","workflow","assignStageOnCreate","ctx","next","action","getService","getAssignedWorkflow","contentType","data","isNil","stages","handleStageOnUpdate","previousStage","result","updatedStage","model","getModel","eventHub","emit","WORKFLOW_UPDATE_STAGE","modelName","locale","from","name","to","checkStageBeforePublish","stageRequiredToPublish","entryStage","errors","ValidationError"],"mappings":"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"}