{"version":3,"file":"components.mjs","sources":["../../src/utils/components.ts"],"sourcesContent":["import _ from 'lodash';\nimport { get, has, omit, pipe, assign } from 'lodash/fp';\n\nimport { contentTypes as contentTypesUtils, async, errors } from '@strapi/utils';\nimport type { Modules, UID, Data, Utils, Schema, Core } from '@strapi/types';\n\ntype LoadedComponents<TUID extends UID.Schema> = Data.Entity<\n  TUID,\n  Schema.AttributeNamesByType<TUID, 'component' | 'dynamiczone'>\n>;\n\ntype ComponentValue = Schema.Attribute.Value<\n  Schema.Attribute.Component<UID.Component, false> | Schema.Attribute.Component<UID.Component, true>\n>;\n\ntype ComponentBody = {\n  [key: string]: Schema.Attribute.Value<\n    | Schema.Attribute.Component<UID.Component, false>\n    | Schema.Attribute.Component<UID.Component, true>\n    | Schema.Attribute.DynamicZone\n  >;\n};\n\nconst isDialectMySQL = () => strapi.db?.dialect.client === 'mysql';\n\nfunction omitComponentData(\n  contentType: Schema.ContentType,\n  data: Modules.EntityService.Params.Data.Input<Schema.ContentType['uid']>\n): Partial<Modules.EntityService.Params.Data.Input<Schema.ContentType['uid']>>;\nfunction omitComponentData(\n  contentType: Schema.Component,\n  data: Modules.EntityService.Params.Data.Input<Schema.Component['uid']>\n): Partial<Modules.EntityService.Params.Data.Input<Schema.Component['uid']>>;\nfunction omitComponentData(\n  contentType: Schema.ContentType | Schema.Component,\n  data: Modules.EntityService.Params.Data.Input<Schema.ContentType['uid'] | Schema.Component['uid']>\n): Partial<\n  Modules.EntityService.Params.Data.Input<Schema.ContentType['uid'] | Schema.Component['uid']>\n> {\n  const { attributes } = contentType;\n  const componentAttributes = Object.keys(attributes).filter((attributeName) =>\n    contentTypesUtils.isComponentAttribute(attributes[attributeName])\n  );\n\n  return omit(componentAttributes, data);\n}\n\n// NOTE: we could generalize the logic to allow CRUD of relation directly in the DB layer\nconst createComponents = async <\n  TUID extends UID.Schema,\n  TData extends Modules.EntityService.Params.Data.Input<TUID>,\n>(\n  uid: TUID,\n  data: TData\n) => {\n  const { attributes = {} } = strapi.getModel(uid);\n\n  const componentBody: ComponentBody = {};\n\n  const attributeNames = Object.keys(attributes);\n\n  for (const attributeName of attributeNames) {\n    const attribute = attributes[attributeName];\n\n    if (!has(attributeName, data) || !contentTypesUtils.isComponentAttribute(attribute)) {\n      continue;\n    }\n\n    if (attribute.type === 'component') {\n      const { component: componentUID, repeatable = false } = attribute;\n\n      const componentValue = data[attributeName as keyof TData];\n\n      if (componentValue === null) {\n        continue;\n      }\n\n      if (repeatable === true) {\n        if (!Array.isArray(componentValue)) {\n          throw new Error('Expected an array to create repeatable component');\n        }\n\n        // MySQL/MariaDB can cause deadlocks here if concurrency higher than 1\n        const components = (await async.map(\n          componentValue,\n          (value: any) => createComponent(componentUID, value),\n          { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }\n        )) as Schema.Attribute.Value<Schema.Attribute.Component<UID.Component, true>>;\n\n        componentBody[attributeName] = components.map(({ id }) => {\n          return {\n            id,\n            __pivot: {\n              field: attributeName,\n              component_type: componentUID,\n            },\n          };\n        });\n      } else {\n        const component = await createComponent(\n          componentUID,\n          componentValue as Modules.EntityService.Params.Data.Input<UID.Component>\n        );\n        componentBody[attributeName] = {\n          id: component.id,\n          __pivot: {\n            field: attributeName,\n            component_type: componentUID,\n          },\n        };\n      }\n\n      continue;\n    }\n\n    if (attribute.type === 'dynamiczone') {\n      const dynamiczoneValues = data[\n        attributeName as keyof TData\n      ] as Modules.EntityService.Params.Attribute.GetValue<Schema.Attribute.DynamicZone>;\n\n      if (!Array.isArray(dynamiczoneValues)) {\n        throw new Error('Expected an array to create repeatable component');\n      }\n\n      const createDynamicZoneComponents = async (\n        value: Utils.Array.Values<typeof dynamiczoneValues>\n      ) => {\n        const { id } = await createComponent(value.__component, value);\n        return {\n          id,\n          __component: value.__component,\n          __pivot: {\n            field: attributeName,\n          },\n        };\n      };\n\n      // MySQL/MariaDB can cause deadlocks here if concurrency higher than 1\n      componentBody[attributeName] = await async.map(\n        dynamiczoneValues,\n        createDynamicZoneComponents,\n        { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }\n      );\n\n      continue;\n    }\n  }\n\n  return componentBody;\n};\n\nconst getComponents = async <TUID extends UID.Schema>(\n  uid: TUID,\n  entity: { id: Modules.EntityService.Params.Attribute.ID }\n): Promise<LoadedComponents<TUID>> => {\n  const componentAttributes = contentTypesUtils.getComponentAttributes(strapi.getModel(uid));\n\n  if (_.isEmpty(componentAttributes)) {\n    return {} as LoadedComponents<TUID>;\n  }\n\n  return strapi.db.query(uid).load(entity, componentAttributes) as Promise<LoadedComponents<TUID>>;\n};\n\n/*\n  delete old components\n  create or update\n*/\nconst updateComponents = async <\n  TUID extends UID.Schema,\n  TData extends Partial<Modules.EntityService.Params.Data.Input<TUID>>,\n>(\n  uid: TUID,\n  entityToUpdate: { id: Modules.EntityService.Params.Attribute.ID },\n  data: TData\n) => {\n  const { attributes = {} } = strapi.getModel(uid);\n\n  const componentBody: ComponentBody = {};\n\n  for (const attributeName of Object.keys(attributes)) {\n    const attribute = attributes[attributeName];\n\n    if (!has(attributeName, data)) {\n      continue;\n    }\n\n    if (attribute.type === 'component') {\n      const { component: componentUID, repeatable = false } = attribute;\n\n      const componentValue = data[\n        attributeName as keyof TData\n      ] as Schema.Attribute.Value<Schema.Attribute.Component>;\n\n      await deleteOldComponents(uid, componentUID, entityToUpdate, attributeName, componentValue);\n\n      if (repeatable === true) {\n        if (!Array.isArray(componentValue)) {\n          throw new Error('Expected an array to create repeatable component');\n        }\n\n        // MySQL/MariaDB can cause deadlocks here if concurrency higher than 1\n        const components = (await async.map(\n          componentValue,\n          (value: any) => updateOrCreateComponent(componentUID, value),\n          { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }\n        )) as Schema.Attribute.Value<Schema.Attribute.Component<UID.Component, true>>;\n\n        componentBody[attributeName] = components.filter(_.negate(_.isNil)).map(({ id }) => {\n          return {\n            id,\n            __pivot: {\n              field: attributeName,\n              component_type: componentUID,\n            },\n          };\n        });\n      } else {\n        const component = await updateOrCreateComponent(componentUID, componentValue);\n        componentBody[attributeName] = component && {\n          id: component.id,\n          __pivot: {\n            field: attributeName,\n            component_type: componentUID,\n          },\n        };\n      }\n\n      continue;\n    }\n\n    if (attribute.type === 'dynamiczone') {\n      const dynamiczoneValues = data[\n        attributeName as keyof TData\n      ] as Schema.Attribute.Value<Schema.Attribute.DynamicZone>;\n\n      await deleteOldDZComponents(uid, entityToUpdate, attributeName, dynamiczoneValues);\n\n      if (!Array.isArray(dynamiczoneValues)) {\n        throw new Error('Expected an array to create repeatable component');\n      }\n\n      // MySQL/MariaDB can cause deadlocks here if concurrency higher than 1\n      componentBody[attributeName] = await async.map(\n        dynamiczoneValues,\n        async (value: any) => {\n          const { id } = await updateOrCreateComponent(value.__component, value);\n\n          return {\n            id,\n            __component: value.__component,\n            __pivot: {\n              field: attributeName,\n            },\n          };\n        },\n        { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }\n      );\n\n      continue;\n    }\n  }\n\n  return componentBody;\n};\n\nconst pickStringifiedId = ({\n  id,\n}: {\n  id: Modules.EntityService.Params.Attribute.ID;\n}): Modules.EntityService.Params.Attribute.ID & string => {\n  if (typeof id === 'string') {\n    return id;\n  }\n\n  return `${id}`;\n};\n\nconst deleteOldComponents = async <TUID extends UID.Schema>(\n  uid: TUID,\n  componentUID: UID.Component,\n  entityToUpdate: { id: Modules.EntityService.Params.Attribute.ID },\n  attributeName: string,\n  componentValue: Schema.Attribute.Value<Schema.Attribute.Component>\n) => {\n  const previousValue = (await strapi.db\n    .query(uid)\n    .load(entityToUpdate, attributeName)) as ComponentValue;\n\n  const idsToKeep = _.castArray(componentValue).filter(has('id')).map(pickStringifiedId);\n  const allIds = _.castArray(previousValue).filter(has('id')).map(pickStringifiedId);\n\n  idsToKeep.forEach((id) => {\n    if (!allIds.includes(id)) {\n      throw new errors.ApplicationError(\n        `Some of the provided components in ${attributeName} are not related to the entity`\n      );\n    }\n  });\n\n  const idsToDelete = _.difference(allIds, idsToKeep);\n\n  if (idsToDelete.length > 0) {\n    for (const idToDelete of idsToDelete) {\n      await deleteComponent(componentUID, { id: idToDelete });\n    }\n  }\n};\n\nconst deleteOldDZComponents = async <TUID extends UID.Schema>(\n  uid: TUID,\n  entityToUpdate: { id: Modules.EntityService.Params.Attribute.ID },\n  attributeName: string,\n  dynamiczoneValues: Schema.Attribute.Value<Schema.Attribute.DynamicZone>\n) => {\n  const previousValue = (await strapi.db\n    .query(uid)\n    .load(entityToUpdate, attributeName)) as Schema.Attribute.Value<Schema.Attribute.DynamicZone>;\n\n  const idsToKeep = _.castArray(dynamiczoneValues)\n    .filter(has('id'))\n    .map((v) => ({\n      id: pickStringifiedId(v),\n      __component: v.__component,\n    }));\n\n  const allIds = _.castArray(previousValue)\n    .filter(has('id'))\n    .map((v) => ({\n      id: pickStringifiedId(v),\n      __component: v.__component,\n    }));\n\n  idsToKeep.forEach(({ id, __component }) => {\n    if (!allIds.find((el) => el.id === id && el.__component === __component)) {\n      const err = new Error(\n        `Some of the provided components in ${attributeName} are not related to the entity`\n      );\n\n      Object.assign(err, { status: 400 });\n      throw err;\n    }\n  });\n\n  type IdsToDelete = Schema.Attribute.Value<Schema.Attribute.DynamicZone>;\n\n  const idsToDelete = allIds.reduce((acc, { id, __component }) => {\n    if (!idsToKeep.find((el) => el.id === id && el.__component === __component)) {\n      acc.push({ id, __component });\n    }\n\n    return acc;\n  }, [] as IdsToDelete);\n\n  if (idsToDelete.length > 0) {\n    for (const idToDelete of idsToDelete) {\n      const { id, __component } = idToDelete;\n      await deleteComponent(__component, { id });\n    }\n  }\n};\n\nconst deleteComponents = async <TUID extends UID.Schema, TEntity extends Data.Entity<TUID>>(\n  uid: TUID,\n  entityToDelete: TEntity,\n  { loadComponents = true } = {}\n) => {\n  const { attributes = {} } = strapi.getModel(uid);\n\n  const attributeNames = Object.keys(attributes);\n\n  for (const attributeName of attributeNames) {\n    const attribute = attributes[attributeName];\n\n    if (attribute.type === 'component' || attribute.type === 'dynamiczone') {\n      let value;\n      if (loadComponents) {\n        value = await strapi.db.query(uid).load(entityToDelete, attributeName);\n      } else {\n        value = entityToDelete[attributeName as keyof TEntity];\n      }\n\n      if (!value) {\n        continue;\n      }\n\n      if (attribute.type === 'component') {\n        const { component: componentUID } = attribute;\n        // MySQL/MariaDB can cause deadlocks here if concurrency higher than 1\n        await async.map(\n          _.castArray(value),\n          (subValue: any) => deleteComponent(componentUID, subValue),\n          {\n            concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity,\n          }\n        );\n      } else {\n        // delete dynamic zone components\n        // MySQL/MariaDB can cause deadlocks here if concurrency higher than 1\n        await async.map(\n          _.castArray(value),\n          (subValue: any) => deleteComponent(subValue.__component, subValue),\n          { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }\n        );\n      }\n\n      continue;\n    }\n  }\n};\n\n/** *************************\n    Component queries\n************************** */\n\n// components can have nested compos so this must be recursive\nconst createComponent = async <TUID extends UID.Component = UID.Component>(\n  uid: TUID,\n  data: Modules.EntityService.Params.Data.Input<TUID>\n) => {\n  const model = strapi.getModel(uid) as Schema.Component;\n\n  const componentData = await createComponents(uid, data);\n  const transform = pipe(\n    // Make sure we don't save the component with a pre-defined ID\n    omit('id'),\n    // Remove the component data from the original data object ...\n    (payload) => omitComponentData(model, payload),\n    // ... and assign the newly created component instead\n    assign(componentData)\n  );\n\n  return strapi.db.query(uid).create({ data: transform(data) });\n};\n\n// components can have nested compos so this must be recursive\nconst updateComponent = async <TUID extends UID.Component>(\n  uid: TUID,\n  componentToUpdate: { id: Modules.EntityService.Params.Attribute.ID },\n  data: Modules.EntityService.Params.Data.Input<TUID>\n) => {\n  const model = strapi.getModel(uid) as Schema.Component;\n\n  const componentData = await updateComponents(uid, componentToUpdate, data);\n\n  return strapi.db.query(uid).update({\n    where: {\n      id: componentToUpdate.id,\n    },\n    data: Object.assign(omitComponentData(model, data), componentData),\n  });\n};\n\nconst updateOrCreateComponent = <TUID extends UID.Component>(\n  componentUID: TUID,\n  value: Modules.EntityService.Params.Data.Input<TUID>\n) => {\n  if (value === null) {\n    return null;\n  }\n\n  // update\n  if ('id' in value && typeof value.id !== 'undefined') {\n    // TODO: verify the compo is associated with the entity\n    return updateComponent(componentUID, { id: value.id }, value);\n  }\n\n  // create\n  return createComponent(componentUID, value);\n};\n\nconst deleteComponent = async <TUID extends UID.Component>(\n  uid: TUID,\n  componentToDelete: Data.Component<TUID>\n) => {\n  await deleteComponents(uid, componentToDelete);\n  await strapi.db.query(uid).delete({ where: { id: componentToDelete.id } });\n};\n\n/**\n * Resolve the component UID of an entity's attribute based\n * on a given path (components & dynamic zones only)\n */\nconst resolveComponentUID = ({\n  paths,\n  strapi,\n  data,\n  contentType,\n}: {\n  paths: string[];\n  strapi: Core.Strapi;\n  data: any;\n  contentType: Schema.ContentType;\n}): UID.Schema | undefined => {\n  let value: unknown = data;\n  let cType:\n    | Schema.ContentType\n    | Schema.Component\n    | ((...opts: any[]) => Schema.ContentType | Schema.Component) = contentType;\n  for (const path of paths) {\n    value = get(path, value);\n\n    // Needed when the value of cType should be computed\n    // based on the next value (eg: dynamic zones)\n    if (typeof cType === 'function') {\n      cType = cType(value);\n    }\n\n    if (path in cType.attributes) {\n      const attribute: Schema.Attribute.AnyAttribute = cType.attributes[path];\n\n      if (attribute.type === 'component') {\n        cType = strapi.getModel(attribute.component);\n      }\n\n      if (attribute.type === 'dynamiczone') {\n        cType = ({ __component }: { __component: UID.Component }) => strapi.getModel(__component);\n      }\n    }\n  }\n\n  if ('uid' in cType) {\n    return cType.uid;\n  }\n\n  return undefined;\n};\n\nexport {\n  omitComponentData,\n  getComponents,\n  createComponents,\n  updateComponents,\n  deleteComponents,\n  deleteComponent,\n  resolveComponentUID,\n};\n"],"names":["isDialectMySQL","strapi","db","dialect","client","omitComponentData","contentType","data","attributes","componentAttributes","Object","keys","filter","attributeName","contentTypesUtils","isComponentAttribute","omit","createComponents","uid","getModel","componentBody","attributeNames","attribute","has","type","component","componentUID","repeatable","componentValue","Array","isArray","Error","components","async","map","value","createComponent","concurrency","inTransaction","Infinity","id","__pivot","field","component_type","dynamiczoneValues","createDynamicZoneComponents","__component","getComponents","entity","getComponentAttributes","_","isEmpty","query","load","deleteComponents","entityToDelete","loadComponents","castArray","subValue","deleteComponent","model","componentData","transform","pipe","payload","assign","create","componentToDelete","delete","where","resolveComponentUID","paths","cType","path","get","undefined"],"mappings":"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"}