@strapi/data-transfer
Version:
Data transfer capabilities for Strapi
1 lines • 23.6 kB
Source Map (JSON)
{"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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"}