{"version":3,"file":"draft-and-publish.mjs","sources":["../../../src/services/document-service/draft-and-publish.ts"],"sourcesContent":["import { assoc, curry } from 'lodash/fp';\n\nimport type { Modules, Struct, UID } from '@strapi/types';\nimport { contentTypes, errors } from '@strapi/utils';\n\ntype ParamsTransform = (params: Modules.Documents.Params.All) => Modules.Documents.Params.All;\n\ntype TransformWithContentType = (\n  contentType: Struct.SingleTypeSchema | Struct.CollectionTypeSchema,\n  params: Modules.Documents.Params.All\n) => Modules.Documents.Params.All;\n\n/**\n * DP enabled -> set status to draft\n * DP disabled -> Used mostly for parsing relations, so there is not a need for a default.\n */\nconst setStatusToDraft: TransformWithContentType = (contentType, params) => {\n  if (!contentTypes.hasDraftAndPublish(contentType) && params.status) {\n    return params;\n  }\n\n  return assoc('status', 'draft', params);\n};\n\n/**\n * Adds a default status of `draft` to the params\n */\nconst defaultToDraft: ParamsTransform = (params) => {\n  // Default to draft if no status is provided or it's invalid\n  if (!params.status || params.status !== 'published') {\n    return assoc('status', 'draft', params);\n  }\n\n  return params;\n};\n\n/**\n * DP disabled -> ignore status\n * DP enabled -> set status to draft if no status is provided or it's invalid\n */\nconst defaultStatus: TransformWithContentType = (contentType, params) => {\n  if (!contentTypes.hasDraftAndPublish(contentType)) {\n    return params;\n  }\n\n  // Default to draft if no status is provided or it's invalid\n  if (!params.status || params.status !== 'published') {\n    return defaultToDraft(params);\n  }\n\n  return params;\n};\n\n/**\n * In mutating actions we don't want user to set the publishedAt attribute.\n */\nconst filterDataPublishedAt: ParamsTransform = (params) => {\n  if (params?.data?.publishedAt) {\n    return assoc(['data', 'publishedAt'], null, params);\n  }\n\n  return params;\n};\n\n/**\n * Add status lookup query to the params\n */\nconst statusToLookup: TransformWithContentType = (contentType, params) => {\n  if (!contentTypes.hasDraftAndPublish(contentType)) {\n    return params;\n  }\n\n  const lookup = params.lookup || {};\n\n  switch (params?.status) {\n    case 'published':\n      return assoc(['lookup', 'publishedAt'], { $notNull: true }, params);\n    case 'draft':\n      return assoc(['lookup', 'publishedAt'], { $null: true }, params);\n    default:\n      break;\n  }\n\n  return assoc('lookup', lookup, params);\n};\n\n/**\n * Translate publication status parameter into the data that will be saved\n */\nconst statusToData: TransformWithContentType = (contentType, params) => {\n  if (!contentTypes.hasDraftAndPublish(contentType)) {\n    return assoc(['data', 'publishedAt'], new Date(), params);\n  }\n\n  switch (params?.status) {\n    case 'published':\n      return assoc(['data', 'publishedAt'], new Date(), params);\n    case 'draft':\n      return assoc(['data', 'publishedAt'], null, params);\n    default:\n      break;\n  }\n\n  return params;\n};\n\n/**\n * Parses and sanitizes the hasPublishedVersion parameter.\n * Returns normalized boolean value or undefined if not provided.\n * Throws ValidationError for invalid input (400 response).\n */\nconst parseHasPublishedVersion = (value: unknown): boolean | undefined => {\n  if (value === undefined || value === null) {\n    return undefined;\n  }\n\n  if (value === true || value === 'true') {\n    return true;\n  }\n\n  if (value === false || value === 'false') {\n    return false;\n  }\n\n  throw new errors.ValidationError(\n    \"Invalid value for 'hasPublishedVersion'. Expected boolean or 'true'/'false' string.\"\n  );\n};\n\n/**\n * Synchronous helper that returns the \"has published version\" condition for a given model.\n * Returns the documentId subquery condition, or null if the model doesn't use draft & publish.\n *\n * This is used by the filters function in transform/query.ts so that the condition\n * is applied to both root and nested (populate) queries.\n */\nconst getHasPublishedVersionCondition = (\n  uid: UID.Schema,\n  hasPublishedVersion: boolean\n): Record<string, any> | null => {\n  const model = strapi.getModel(uid);\n\n  // Ignore if target model has disabled DP or doesn't exist (e.g., components)\n  if (!model || !contentTypes.hasDraftAndPublish(model)) {\n    return null;\n  }\n\n  // Get table and column names from metadata\n  const meta = strapi.db.metadata.get(uid);\n  const tableName = meta.tableName;\n  const documentIdAttr = meta.attributes.documentId;\n  const publishedAtAttr = meta.attributes.publishedAt;\n  const documentIdColumn =\n    ('columnName' in documentIdAttr && documentIdAttr.columnName) || 'document_id';\n  const publishedAtColumn =\n    ('columnName' in publishedAtAttr && publishedAtAttr.columnName) || 'published_at';\n\n  // Create a Knex subquery that selects document IDs with published entries\n  const knex = strapi.db.connection;\n  const subquery = knex(tableName).distinct(documentIdColumn).whereNotNull(publishedAtColumn);\n\n  if (hasPublishedVersion) {\n    return { documentId: { $in: subquery } };\n  }\n\n  return { documentId: { $notIn: subquery } };\n};\n\nconst setStatusToDraftCurry = curry(setStatusToDraft);\nconst defaultToDraftCurry = curry(defaultToDraft);\nconst defaultStatusCurry = curry(defaultStatus);\nconst filterDataPublishedAtCurry = curry(filterDataPublishedAt);\nconst statusToLookupCurry = curry(statusToLookup);\nconst statusToDataCurry = curry(statusToData);\n\nexport {\n  setStatusToDraftCurry as setStatusToDraft,\n  defaultToDraftCurry as defaultToDraft,\n  defaultStatusCurry as defaultStatus,\n  filterDataPublishedAtCurry as filterDataPublishedAt,\n  statusToLookupCurry as statusToLookup,\n  statusToDataCurry as statusToData,\n  parseHasPublishedVersion,\n  getHasPublishedVersionCondition,\n};\n"],"names":["setStatusToDraft","contentType","params","contentTypes","hasDraftAndPublish","status","assoc","defaultToDraft","defaultStatus","filterDataPublishedAt","data","publishedAt","statusToLookup","lookup","$notNull","$null","statusToData","Date","parseHasPublishedVersion","value","undefined","errors","ValidationError","getHasPublishedVersionCondition","uid","hasPublishedVersion","model","strapi","getModel","meta","db","metadata","get","tableName","documentIdAttr","attributes","documentId","publishedAtAttr","documentIdColumn","columnName","publishedAtColumn","knex","connection","subquery","distinct","whereNotNull","$in","$notIn","setStatusToDraftCurry","curry","defaultToDraftCurry","defaultStatusCurry","filterDataPublishedAtCurry","statusToLookupCurry","statusToDataCurry"],"mappings":"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"}