{"version":3,"file":"components.mjs","sources":["../../../src/services/entity-service/components.ts"],"sourcesContent":["import _ from 'lodash';\nimport { has, omit, pipe, assign } from 'lodash/fp';\nimport type { Attribute, Common, Schema, Utils, EntityService } from '@strapi/types';\nimport { contentTypes as contentTypesUtils, mapAsync, errors } from '@strapi/utils';\n\ntype LoadedComponents<TUID extends Common.UID.Schema> = Attribute.GetValues<\n  TUID,\n  Attribute.GetKeysByType<TUID, 'component' | 'dynamiczone'>\n>;\n\ntype ComponentValue = Attribute.GetValue<\n  Attribute.Component<Common.UID.Component, false> | Attribute.Component<Common.UID.Component, true>\n>;\n\ntype ComponentBody = {\n  [key: string]: Attribute.GetValue<\n    | Attribute.Component<Common.UID.Component, false>\n    | Attribute.Component<Common.UID.Component, true>\n    | Attribute.DynamicZone\n  >;\n};\n\nconst isDialectMySQL = () => strapi.db?.dialect.client === 'mysql';\n\nfunction omitComponentData(\n  contentType: Schema.ContentType,\n  data: EntityService.Params.Data.Input<Schema.ContentType['uid']>\n): Partial<EntityService.Params.Data.Input<Schema.ContentType['uid']>>;\nfunction omitComponentData(\n  contentType: Schema.Component,\n  data: EntityService.Params.Data.Input<Schema.Component['uid']>\n): Partial<EntityService.Params.Data.Input<Schema.Component['uid']>>;\nfunction omitComponentData(\n  contentType: Schema.ContentType | Schema.Component,\n  data: EntityService.Params.Data.Input<Schema.ContentType['uid'] | Schema.Component['uid']>\n): Partial<EntityService.Params.Data.Input<Schema.ContentType['uid'] | Schema.Component['uid']>> {\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 Common.UID.Schema,\n  TData extends 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 mapAsync(\n          componentValue,\n          (value: any) => createComponent(componentUID, value),\n          { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }\n        )) as Attribute.GetValue<Attribute.Component<Common.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 EntityService.Params.Data.Input<Common.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 EntityService.Params.Attribute.GetValue<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 mapAsync(\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 Common.UID.Schema>(\n  uid: TUID,\n  entity: { id: 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.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 Common.UID.Schema,\n  TData extends Partial<EntityService.Params.Data.Input<TUID>>\n>(\n  uid: TUID,\n  entityToUpdate: { id: 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 Attribute.GetValue<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 mapAsync(\n          componentValue,\n          (value: any) => updateOrCreateComponent(componentUID, value),\n          { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }\n        )) as Attribute.GetValue<Attribute.Component<Common.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 Attribute.GetValue<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 mapAsync(\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: EntityService.Params.Attribute.ID;\n}): 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 Common.UID.Schema>(\n  uid: TUID,\n  componentUID: Common.UID.Component,\n  entityToUpdate: { id: EntityService.Params.Attribute.ID },\n  attributeName: string,\n  componentValue: Attribute.GetValue<Attribute.Component>\n) => {\n  const previousValue = (await strapi\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 Common.UID.Schema>(\n  uid: TUID,\n  entityToUpdate: { id: EntityService.Params.Attribute.ID },\n  attributeName: string,\n  dynamiczoneValues: Attribute.GetValue<Attribute.DynamicZone>\n) => {\n  const previousValue = (await strapi\n    .query(uid)\n    .load(entityToUpdate, attributeName)) as Attribute.GetValue<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 = Attribute.GetValue<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 <\n  TUID extends Common.UID.Schema,\n  TEntity extends Attribute.GetValues<TUID>\n>(\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.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 mapAsync(\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 mapAsync(\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\nconst cloneComponents = async <TUID extends Common.UID.Schema>(\n  uid: TUID,\n  entityToClone: { id: EntityService.Params.Attribute.ID },\n  data: EntityService.Params.Data.Input<TUID>\n) => {\n  const { attributes = {} } = strapi.getModel(uid);\n\n  const componentBody: ComponentBody = {};\n  const componentData = await getComponents(uid, entityToClone);\n\n  for (const attributeName of Object.keys(attributes)) {\n    const attribute = attributes[attributeName];\n\n    // If the attribute is not set or on the component to clone, skip it\n    if (!has(attributeName, data) && !has(attributeName, componentData)) {\n      continue;\n    }\n\n    if (attribute.type === 'component') {\n      const { component: componentUID, repeatable = false } = attribute;\n\n      const componentValue = (\n        attributeName in data\n          ? data[attributeName as keyof typeof data]\n          : componentData[attributeName as keyof typeof componentData]\n      ) as ComponentValue;\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 mapAsync(\n          componentValue,\n          (value: any) => cloneComponent(componentUID, value),\n          { concurrency: isDialectMySQL() ? 1 : Infinity }\n        )) as Attribute.GetValue<Attribute.Component<Common.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 cloneComponent(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 = has(attributeName, data)\n        ? data[attributeName as keyof typeof data]\n        : componentData[attributeName as keyof typeof componentData];\n\n      if (!Array.isArray(dynamiczoneValues)) {\n        throw new Error('Expected an array to create repeatable component');\n      }\n      // MySQL/MariaDB can cause deadlocks here if concurrency higher than 1\n      componentBody[attributeName] = await mapAsync(\n        dynamiczoneValues,\n        async (value: any) => {\n          const { id } = await cloneComponent(value.__component, value);\n          return {\n            id,\n            __component: value.__component,\n            __pivot: {\n              field: attributeName,\n            },\n          };\n        },\n        { concurrency: isDialectMySQL() ? 1 : Infinity }\n      );\n      continue;\n    }\n  }\n\n  return componentBody;\n};\n/** *************************\n    Component queries\n************************** */\n\n// components can have nested compos so this must be recursive\nconst createComponent = async <TUID extends Common.UID.Component>(\n  uid: TUID,\n  data: EntityService.Params.Data.Input<TUID>\n) => {\n  const model = strapi.getModel(uid);\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.query(uid).create({ data: transform(data) });\n};\n\n// components can have nested compos so this must be recursive\nconst updateComponent = async <TUID extends Common.UID.Component>(\n  uid: TUID,\n  componentToUpdate: { id: EntityService.Params.Attribute.ID },\n  data: EntityService.Params.Data.Input<TUID>\n) => {\n  const model = strapi.getModel(uid);\n\n  const componentData = await updateComponents(uid, componentToUpdate, data);\n\n  return strapi.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 Common.UID.Component>(\n  componentUID: TUID,\n  value: 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 Common.UID.Component>(\n  uid: TUID,\n  componentToDelete: Attribute.GetValues<TUID>\n) => {\n  await deleteComponents(uid, componentToDelete);\n  await strapi.query(uid).delete({ where: { id: componentToDelete.id } });\n};\n\nconst cloneComponent = async <TUID extends Common.UID.Component>(\n  uid: TUID,\n  data: EntityService.Params.Data.Input<TUID>\n) => {\n  const model = strapi.getModel(uid);\n\n  if (!('id' in data) || typeof data.id === 'undefined') {\n    return createComponent(uid, data);\n  }\n\n  const componentData = await cloneComponents(uid, { id: data.id }, 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.query(uid).clone(data.id, { data: transform(data) });\n};\n\nexport {\n  omitComponentData,\n  getComponents,\n  createComponents,\n  updateComponents,\n  deleteComponents,\n  deleteComponent,\n  cloneComponents,\n};\n"],"names":["contentTypesUtils"],"mappings":"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"}