@strapi/strapi 4.25.2 → 4.25.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Strapi.js +3 -3
- package/dist/Strapi.js.map +1 -1
- package/dist/commands/actions/routes/list/action.js +2 -2
- package/dist/commands/actions/routes/list/action.js.map +1 -1
- package/dist/commands/utils/helpers.js +2 -2
- package/dist/commands/utils/helpers.js.map +1 -1
- package/dist/core/app-configuration/index.js +2 -2
- package/dist/core/app-configuration/index.js.map +1 -1
- package/dist/core/domain/content-type/index.js +4 -4
- package/dist/core/domain/content-type/index.js.map +1 -1
- package/dist/core/loaders/apis.js +2 -2
- package/dist/core/loaders/apis.js.map +1 -1
- package/dist/core/loaders/plugins/get-enabled-plugins.js +8 -8
- package/dist/core/loaders/plugins/get-enabled-plugins.js.map +1 -1
- package/dist/core/loaders/plugins/get-user-plugins-config.js +2 -2
- package/dist/core/loaders/plugins/get-user-plugins-config.js.map +1 -1
- package/dist/core/loaders/plugins/index.js +6 -6
- package/dist/core/loaders/plugins/index.js.map +1 -1
- package/dist/core/registries/apis.js +2 -2
- package/dist/core/registries/apis.js.map +1 -1
- package/dist/core/registries/content-types.js +3 -3
- package/dist/core/registries/content-types.js.map +1 -1
- package/dist/core/registries/controllers.js +3 -3
- package/dist/core/registries/controllers.js.map +1 -1
- package/dist/core/registries/custom-fields.js +4 -4
- package/dist/core/registries/custom-fields.js.map +1 -1
- package/dist/core/registries/hooks.js +2 -2
- package/dist/core/registries/hooks.js.map +1 -1
- package/dist/core/registries/middlewares.js +3 -3
- package/dist/core/registries/middlewares.js.map +1 -1
- package/dist/core/registries/modules.js +3 -3
- package/dist/core/registries/modules.js.map +1 -1
- package/dist/core/registries/plugins.js +2 -2
- package/dist/core/registries/plugins.js.map +1 -1
- package/dist/core/registries/policies.js +3 -3
- package/dist/core/registries/policies.js.map +1 -1
- package/dist/core/registries/services.js +3 -3
- package/dist/core/registries/services.js.map +1 -1
- package/dist/core-api/controller/collection-type.js +3 -3
- package/dist/core-api/controller/collection-type.js.map +1 -1
- package/dist/core-api/controller/index.js +2 -2
- package/dist/core-api/controller/index.js.map +1 -1
- package/dist/core-api/controller/single-type.js +2 -2
- package/dist/core-api/controller/single-type.js.map +1 -1
- package/dist/core-api/controller/transform.js +7 -7
- package/dist/core-api/controller/transform.js.map +1 -1
- package/dist/core-api/service/collection-type.js +2 -2
- package/dist/core-api/service/collection-type.js.map +1 -1
- package/dist/core-api/service/pagination.js +10 -10
- package/dist/core-api/service/pagination.js.map +1 -1
- package/dist/core-api/service/single-type.js +2 -2
- package/dist/core-api/service/single-type.js.map +1 -1
- package/dist/ee/index.js +3 -3
- package/dist/ee/index.js.map +1 -1
- package/dist/factories.js +4 -4
- package/dist/factories.js.map +1 -1
- package/dist/load/filepath-to-prop-path.d.ts +1 -1
- package/dist/load/filepath-to-prop-path.d.ts.map +1 -1
- package/dist/load/filepath-to-prop-path.js +27 -6
- package/dist/load/filepath-to-prop-path.js.map +1 -1
- package/dist/load/filepath-to-prop-path.mjs +25 -5
- package/dist/load/filepath-to-prop-path.mjs.map +1 -1
- package/dist/load/load-files.js +2 -2
- package/dist/load/load-files.js.map +1 -1
- package/dist/load/load-files.mjs +2 -2
- package/dist/load/load-files.mjs.map +1 -1
- package/dist/middlewares/body.js +2 -2
- package/dist/middlewares/body.js.map +1 -1
- package/dist/middlewares/public/index.js +4 -4
- package/dist/middlewares/public/index.js.map +1 -1
- package/dist/middlewares/responses.js +2 -2
- package/dist/middlewares/responses.js.map +1 -1
- package/dist/middlewares/security.js +3 -3
- package/dist/middlewares/security.js.map +1 -1
- package/dist/middlewares/session.js +2 -2
- package/dist/middlewares/session.js.map +1 -1
- package/dist/services/auth/index.js +3 -3
- package/dist/services/auth/index.js.map +1 -1
- package/dist/services/core-store.js +3 -3
- package/dist/services/core-store.js.map +1 -1
- package/dist/services/cron.js +3 -3
- package/dist/services/cron.js.map +1 -1
- package/dist/services/entity-service/attributes/transforms.js +3 -3
- package/dist/services/entity-service/attributes/transforms.js.map +1 -1
- package/dist/services/entity-service/components.js +18 -18
- package/dist/services/entity-service/components.js.map +1 -1
- package/dist/services/entity-service/params.js +2 -2
- package/dist/services/entity-service/params.js.map +1 -1
- package/dist/services/entity-validator/index.js +19 -19
- package/dist/services/entity-validator/index.js.map +1 -1
- package/dist/services/server/compose-endpoint.js +7 -7
- package/dist/services/server/compose-endpoint.js.map +1 -1
- package/dist/services/server/koa.js +3 -3
- package/dist/services/server/koa.js.map +1 -1
- package/dist/services/server/middleware.js +3 -3
- package/dist/services/server/middleware.js.map +1 -1
- package/dist/services/server/routing.js +2 -2
- package/dist/services/server/routing.js.map +1 -1
- package/dist/services/utils/dynamic-zones.js +5 -5
- package/dist/services/utils/dynamic-zones.js.map +1 -1
- package/dist/utils/cron.js +3 -3
- package/dist/utils/cron.js.map +1 -1
- package/dist/utils/is-initialized.js +3 -3
- package/dist/utils/is-initialized.js.map +1 -1
- package/dist/utils/startup-logger.js +4 -4
- package/dist/utils/startup-logger.js.map +1 -1
- package/dist/utils/startup-logger.mjs +3 -3
- package/dist/utils/startup-logger.mjs.map +1 -1
- package/package.json +21 -21
- package/dist/load/glob.d.ts +0 -7
- package/dist/load/glob.d.ts.map +0 -1
- package/dist/load/glob.js +0 -15
- package/dist/load/glob.js.map +0 -1
- package/dist/load/glob.mjs +0 -14
- package/dist/load/glob.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.js","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","omit","has","mapAsync","_","errors","pipe","assign"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"components.js","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","omit","has","mapAsync","_","errors","pipe","assign"],"mappings":";;;;;;;AAsBA,MAAM,iBAAiB,MAAM,OAAO,IAAI,QAAQ,WAAW;AAU3D,SAAS,kBACP,aACA,MAC+F;AACzF,QAAA,EAAE,WAAe,IAAA;AACvB,QAAM,sBAAsB,OAAO,KAAK,UAAU,EAAE;AAAA,IAAO,CAAC,kBAC1DA,YAAA,aAAkB,qBAAqB,WAAW,aAAa,CAAC;AAAA,EAAA;AAG3D,SAAAC,GAAA,KAAK,qBAAqB,IAAI;AACvC;AAGM,MAAA,mBAAmB,OAIvB,KACA,SACG;AACH,QAAM,EAAE,aAAa,OAAO,OAAO,SAAS,GAAG;AAE/C,QAAM,gBAA+B,CAAA;AAE/B,QAAA,iBAAiB,OAAO,KAAK,UAAU;AAE7C,aAAW,iBAAiB,gBAAgB;AACpC,UAAA,YAAY,WAAW,aAAa;AAEtC,QAAA,CAACC,GAAAA,IAAI,eAAe,IAAI,KAAK,CAACF,yBAAkB,qBAAqB,SAAS,GAAG;AACnF;AAAA,IACF;AAEI,QAAA,UAAU,SAAS,aAAa;AAClC,YAAM,EAAE,WAAW,cAAc,aAAa,UAAU;AAElD,YAAA,iBAAiB,KAAK,aAA4B;AAExD,UAAI,mBAAmB,MAAM;AAC3B;AAAA,MACF;AAEA,UAAI,eAAe,MAAM;AACvB,YAAI,CAAC,MAAM,QAAQ,cAAc,GAAG;AAC5B,gBAAA,IAAI,MAAM,kDAAkD;AAAA,QACpE;AAGA,cAAM,aAAc,MAAMG,YAAA;AAAA,UACxB;AAAA,UACA,CAAC,UAAe,gBAAgB,cAAc,KAAK;AAAA,UACnD,EAAE,aAAa,eAAA,KAAoB,CAAC,OAAO,IAAI,cAAA,IAAkB,IAAI,SAAS;AAAA,QAAA;AAGhF,sBAAc,aAAa,IAAI,WAAW,IAAI,CAAC,EAAE,SAAS;AACjD,iBAAA;AAAA,YACL;AAAA,YACA,SAAS;AAAA,cACP,OAAO;AAAA,cACP,gBAAgB;AAAA,YAClB;AAAA,UAAA;AAAA,QACF,CACD;AAAA,MAAA,OACI;AACL,cAAM,YAAY,MAAM;AAAA,UACtB;AAAA,UACA;AAAA,QAAA;AAEF,sBAAc,aAAa,IAAI;AAAA,UAC7B,IAAI,UAAU;AAAA,UACd,SAAS;AAAA,YACP,OAAO;AAAA,YACP,gBAAgB;AAAA,UAClB;AAAA,QAAA;AAAA,MAEJ;AAEA;AAAA,IACF;AAEI,QAAA,UAAU,SAAS,eAAe;AAC9B,YAAA,oBAAoB,KACxB,aACF;AAEA,UAAI,CAAC,MAAM,QAAQ,iBAAiB,GAAG;AAC/B,cAAA,IAAI,MAAM,kDAAkD;AAAA,MACpE;AAEM,YAAA,8BAA8B,OAClC,UACG;AACH,cAAM,EAAE,GAAG,IAAI,MAAM,gBAAgB,MAAM,aAAa,KAAK;AACtD,eAAA;AAAA,UACL;AAAA,UACA,aAAa,MAAM;AAAA,UACnB,SAAS;AAAA,YACP,OAAO;AAAA,UACT;AAAA,QAAA;AAAA,MACF;AAIY,oBAAA,aAAa,IAAI,MAAMA,YAAA;AAAA,QACnC;AAAA,QACA;AAAA,QACA,EAAE,aAAa,eAAA,KAAoB,CAAC,OAAO,IAAI,cAAA,IAAkB,IAAI,SAAS;AAAA,MAAA;AAGhF;AAAA,IACF;AAAA,EACF;AAEO,SAAA;AACT;AAEM,MAAA,gBAAgB,OACpB,KACA,WACoC;AACpC,QAAM,sBAAsBH,YAAAA,aAAkB,uBAAuB,OAAO,SAAS,GAAG,CAAC;AAErF,MAAAI,WAAA,QAAE,QAAQ,mBAAmB,GAAG;AAClC,WAAO;EACT;AAEA,SAAO,OAAO,MAAM,GAAG,EAAE,KAAK,QAAQ,mBAAmB;AAC3D;AAMA,MAAM,mBAAmB,OAIvB,KACA,gBACA,SACG;AACH,QAAM,EAAE,aAAa,OAAO,OAAO,SAAS,GAAG;AAE/C,QAAM,gBAA+B,CAAA;AAErC,aAAW,iBAAiB,OAAO,KAAK,UAAU,GAAG;AAC7C,UAAA,YAAY,WAAW,aAAa;AAE1C,QAAI,CAACF,GAAA,IAAI,eAAe,IAAI,GAAG;AAC7B;AAAA,IACF;AAEI,QAAA,UAAU,SAAS,aAAa;AAClC,YAAM,EAAE,WAAW,cAAc,aAAa,UAAU;AAElD,YAAA,iBAAiB,KACrB,aACF;AAEA,YAAM,oBAAoB,KAAK,cAAc,gBAAgB,eAAe,cAAc;AAE1F,UAAI,eAAe,MAAM;AACvB,YAAI,CAAC,MAAM,QAAQ,cAAc,GAAG;AAC5B,gBAAA,IAAI,MAAM,kDAAkD;AAAA,QACpE;AAGA,cAAM,aAAc,MAAMC,YAAA;AAAA,UACxB;AAAA,UACA,CAAC,UAAe,wBAAwB,cAAc,KAAK;AAAA,UAC3D,EAAE,aAAa,eAAA,KAAoB,CAAC,OAAO,IAAI,cAAA,IAAkB,IAAI,SAAS;AAAA,QAAA;AAGhF,sBAAc,aAAa,IAAI,WAAW,OAAOC,WAAAA,QAAE,OAAOA,WAAA,QAAE,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAC3E,iBAAA;AAAA,YACL;AAAA,YACA,SAAS;AAAA,cACP,OAAO;AAAA,cACP,gBAAgB;AAAA,YAClB;AAAA,UAAA;AAAA,QACF,CACD;AAAA,MAAA,OACI;AACL,cAAM,YAAY,MAAM,wBAAwB,cAAc,cAAc;AAC9D,sBAAA,aAAa,IAAI,aAAa;AAAA,UAC1C,IAAI,UAAU;AAAA,UACd,SAAS;AAAA,YACP,OAAO;AAAA,YACP,gBAAgB;AAAA,UAClB;AAAA,QAAA;AAAA,MAEJ;AAEA;AAAA,IACF;AAEI,QAAA,UAAU,SAAS,eAAe;AAC9B,YAAA,oBAAoB,KACxB,aACF;AAEA,YAAM,sBAAsB,KAAK,gBAAgB,eAAe,iBAAiB;AAEjF,UAAI,CAAC,MAAM,QAAQ,iBAAiB,GAAG;AAC/B,cAAA,IAAI,MAAM,kDAAkD;AAAA,MACpE;AAGc,oBAAA,aAAa,IAAI,MAAMD,YAAA;AAAA,QACnC;AAAA,QACA,OAAO,UAAe;AACpB,gBAAM,EAAE,GAAG,IAAI,MAAM,wBAAwB,MAAM,aAAa,KAAK;AAE9D,iBAAA;AAAA,YACL;AAAA,YACA,aAAa,MAAM;AAAA,YACnB,SAAS;AAAA,cACP,OAAO;AAAA,YACT;AAAA,UAAA;AAAA,QAEJ;AAAA,QACA,EAAE,aAAa,eAAA,KAAoB,CAAC,OAAO,IAAI,cAAA,IAAkB,IAAI,SAAS;AAAA,MAAA;AAGhF;AAAA,IACF;AAAA,EACF;AAEO,SAAA;AACT;AAEA,MAAM,oBAAoB,CAAC;AAAA,EACzB;AACF,MAEkD;AAC5C,MAAA,OAAO,OAAO,UAAU;AACnB,WAAA;AAAA,EACT;AAEA,SAAO,GAAG,EAAE;AACd;AAEA,MAAM,sBAAsB,OAC1B,KACA,cACA,gBACA,eACA,mBACG;AACG,QAAA,gBAAiB,MAAM,OAC1B,MAAM,GAAG,EACT,KAAK,gBAAgB,aAAa;AAE/B,QAAA,YAAYC,WAAAA,QAAE,UAAU,cAAc,EAAE,OAAOF,GAAA,IAAI,IAAI,CAAC,EAAE,IAAI,iBAAiB;AAC/E,QAAA,SAASE,WAAAA,QAAE,UAAU,aAAa,EAAE,OAAOF,GAAA,IAAI,IAAI,CAAC,EAAE,IAAI,iBAAiB;AAEvE,YAAA,QAAQ,CAAC,OAAO;AACxB,QAAI,CAAC,OAAO,SAAS,EAAE,GAAG;AACxB,YAAM,IAAIG,YAAO,OAAA;AAAA,QACf,sCAAsC,aAAa;AAAA,MAAA;AAAA,IAEvD;AAAA,EAAA,CACD;AAED,QAAM,cAAcD,WAAA,QAAE,WAAW,QAAQ,SAAS;AAE9C,MAAA,YAAY,SAAS,GAAG;AAC1B,eAAW,cAAc,aAAa;AACpC,YAAM,gBAAgB,cAAc,EAAE,IAAI,WAAY,CAAA;AAAA,IACxD;AAAA,EACF;AACF;AAEA,MAAM,wBAAwB,OAC5B,KACA,gBACA,eACA,sBACG;AACG,QAAA,gBAAiB,MAAM,OAC1B,MAAM,GAAG,EACT,KAAK,gBAAgB,aAAa;AAErC,QAAM,YAAYA,WAAAA,QAAE,UAAU,iBAAiB,EAC5C,OAAOF,GAAI,IAAA,IAAI,CAAC,EAChB,IAAI,CAAC,OAAO;AAAA,IACX,IAAI,kBAAkB,CAAC;AAAA,IACvB,aAAa,EAAE;AAAA,EACf,EAAA;AAEJ,QAAM,SAASE,WAAAA,QAAE,UAAU,aAAa,EACrC,OAAOF,GAAI,IAAA,IAAI,CAAC,EAChB,IAAI,CAAC,OAAO;AAAA,IACX,IAAI,kBAAkB,CAAC;AAAA,IACvB,aAAa,EAAE;AAAA,EACf,EAAA;AAEJ,YAAU,QAAQ,CAAC,EAAE,IAAI,kBAAkB;AACrC,QAAA,CAAC,OAAO,KAAK,CAAC,OAAO,GAAG,OAAO,MAAM,GAAG,gBAAgB,WAAW,GAAG;AACxE,YAAM,MAAM,IAAI;AAAA,QACd,sCAAsC,aAAa;AAAA,MAAA;AAGrD,aAAO,OAAO,KAAK,EAAE,QAAQ,IAAK,CAAA;AAC5B,YAAA;AAAA,IACR;AAAA,EAAA,CACD;AAIK,QAAA,cAAc,OAAO,OAAO,CAAC,KAAK,EAAE,IAAI,kBAAkB;AAC1D,QAAA,CAAC,UAAU,KAAK,CAAC,OAAO,GAAG,OAAO,MAAM,GAAG,gBAAgB,WAAW,GAAG;AAC3E,UAAI,KAAK,EAAE,IAAI,YAAa,CAAA;AAAA,IAC9B;AAEO,WAAA;AAAA,EACT,GAAG,CAAiB,CAAA;AAEhB,MAAA,YAAY,SAAS,GAAG;AAC1B,eAAW,cAAc,aAAa;AAC9B,YAAA,EAAE,IAAI,YAAgB,IAAA;AAC5B,YAAM,gBAAgB,aAAa,EAAE,GAAI,CAAA;AAAA,IAC3C;AAAA,EACF;AACF;AAEM,MAAA,mBAAmB,OAIvB,KACA,gBACA,EAAE,iBAAiB,KAAS,IAAA,OACzB;AACH,QAAM,EAAE,aAAa,OAAO,OAAO,SAAS,GAAG;AAEzC,QAAA,iBAAiB,OAAO,KAAK,UAAU;AAE7C,aAAW,iBAAiB,gBAAgB;AACpC,UAAA,YAAY,WAAW,aAAa;AAE1C,QAAI,UAAU,SAAS,eAAe,UAAU,SAAS,eAAe;AAClE,UAAA;AACJ,UAAI,gBAAgB;AAClB,gBAAQ,MAAM,OAAO,MAAM,GAAG,EAAE,KAAK,gBAAgB,aAAa;AAAA,MAAA,OAC7D;AACL,gBAAQ,eAAe,aAA8B;AAAA,MACvD;AAEA,UAAI,CAAC,OAAO;AACV;AAAA,MACF;AAEI,UAAA,UAAU,SAAS,aAAa;AAC5B,cAAA,EAAE,WAAW,aAAiB,IAAA;AAE9B,cAAAC,YAAA;AAAA,UACJC,WAAA,QAAE,UAAU,KAAK;AAAA,UACjB,CAAC,aAAkB,gBAAgB,cAAc,QAAQ;AAAA,UACzD;AAAA,YACE,aAAa,oBAAoB,CAAC,OAAO,IAAI,cAAA,IAAkB,IAAI;AAAA,UACrE;AAAA,QAAA;AAAA,MACF,OACK;AAGC,cAAAD,YAAA;AAAA,UACJC,WAAA,QAAE,UAAU,KAAK;AAAA,UACjB,CAAC,aAAkB,gBAAgB,SAAS,aAAa,QAAQ;AAAA,UACjE,EAAE,aAAa,eAAA,KAAoB,CAAC,OAAO,IAAI,cAAA,IAAkB,IAAI,SAAS;AAAA,QAAA;AAAA,MAElF;AAEA;AAAA,IACF;AAAA,EACF;AACF;AAEA,MAAM,kBAAkB,OACtB,KACA,eACA,SACG;AACH,QAAM,EAAE,aAAa,OAAO,OAAO,SAAS,GAAG;AAE/C,QAAM,gBAA+B,CAAA;AACrC,QAAM,gBAAgB,MAAM,cAAc,KAAK,aAAa;AAE5D,aAAW,iBAAiB,OAAO,KAAK,UAAU,GAAG;AAC7C,UAAA,YAAY,WAAW,aAAa;AAGtC,QAAA,CAACF,GAAAA,IAAI,eAAe,IAAI,KAAK,CAACA,OAAI,eAAe,aAAa,GAAG;AACnE;AAAA,IACF;AAEI,QAAA,UAAU,SAAS,aAAa;AAClC,YAAM,EAAE,WAAW,cAAc,aAAa,UAAU;AAExD,YAAM,iBACJ,iBAAiB,OACb,KAAK,aAAkC,IACvC,cAAc,aAA2C;AAG/D,UAAI,mBAAmB,MAAM;AAC3B;AAAA,MACF;AAEA,UAAI,eAAe,MAAM;AACvB,YAAI,CAAC,MAAM,QAAQ,cAAc,GAAG;AAC5B,gBAAA,IAAI,MAAM,kDAAkD;AAAA,QACpE;AAGA,cAAM,aAAc,MAAMC,YAAA;AAAA,UACxB;AAAA,UACA,CAAC,UAAe,eAAe,cAAc,KAAK;AAAA,UAClD,EAAE,aAAa,mBAAmB,IAAI,SAAS;AAAA,QAAA;AAGjD,sBAAc,aAAa,IAAI,WAAW,OAAOC,WAAAA,QAAE,OAAOA,WAAA,QAAE,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAC3E,iBAAA;AAAA,YACL;AAAA,YACA,SAAS;AAAA,cACP,OAAO;AAAA,cACP,gBAAgB;AAAA,YAClB;AAAA,UAAA;AAAA,QACF,CACD;AAAA,MAAA,OACI;AACL,cAAM,YAAY,MAAM,eAAe,cAAc,cAAc;AACrD,sBAAA,aAAa,IAAI,aAAa;AAAA,UAC1C,IAAI,UAAU;AAAA,UACd,SAAS;AAAA,YACP,OAAO;AAAA,YACP,gBAAgB;AAAA,UAClB;AAAA,QAAA;AAAA,MAEJ;AAEA;AAAA,IACF;AAEI,QAAA,UAAU,SAAS,eAAe;AAC9B,YAAA,oBAAoBF,OAAI,eAAe,IAAI,IAC7C,KAAK,aAAkC,IACvC,cAAc,aAA2C;AAE7D,UAAI,CAAC,MAAM,QAAQ,iBAAiB,GAAG;AAC/B,cAAA,IAAI,MAAM,kDAAkD;AAAA,MACpE;AAEc,oBAAA,aAAa,IAAI,MAAMC,YAAA;AAAA,QACnC;AAAA,QACA,OAAO,UAAe;AACpB,gBAAM,EAAE,GAAG,IAAI,MAAM,eAAe,MAAM,aAAa,KAAK;AACrD,iBAAA;AAAA,YACL;AAAA,YACA,aAAa,MAAM;AAAA,YACnB,SAAS;AAAA,cACP,OAAO;AAAA,YACT;AAAA,UAAA;AAAA,QAEJ;AAAA,QACA,EAAE,aAAa,mBAAmB,IAAI,SAAS;AAAA,MAAA;AAEjD;AAAA,IACF;AAAA,EACF;AAEO,SAAA;AACT;AAMA,MAAM,kBAAkB,OACtB,KACA,SACG;AACG,QAAA,QAAQ,OAAO,SAAS,GAAG;AAEjC,QAAM,gBAAgB,MAAM,iBAAiB,KAAK,IAAI;AACtD,QAAM,YAAYG,GAAA;AAAA;AAAA,IAEhBL,GAAAA,KAAK,IAAI;AAAA;AAAA,IAET,CAAC,YAAY,kBAAkB,OAAO,OAAO;AAAA;AAAA,IAE7CM,GAAAA,OAAO,aAAa;AAAA,EAAA;AAGf,SAAA,OAAO,MAAM,GAAG,EAAE,OAAO,EAAE,MAAM,UAAU,IAAI,EAAA,CAAG;AAC3D;AAGA,MAAM,kBAAkB,OACtB,KACA,mBACA,SACG;AACG,QAAA,QAAQ,OAAO,SAAS,GAAG;AAEjC,QAAM,gBAAgB,MAAM,iBAAiB,KAAK,mBAAmB,IAAI;AAEzE,SAAO,OAAO,MAAM,GAAG,EAAE,OAAO;AAAA,IAC9B,OAAO;AAAA,MACL,IAAI,kBAAkB;AAAA,IACxB;AAAA,IACA,MAAM,OAAO,OAAO,kBAAkB,OAAO,IAAI,GAAG,aAAa;AAAA,EAAA,CAClE;AACH;AAEA,MAAM,0BAA0B,CAC9B,cACA,UACG;AACH,MAAI,UAAU,MAAM;AACX,WAAA;AAAA,EACT;AAGA,MAAI,QAAQ,SAAS,OAAO,MAAM,OAAO,aAAa;AAEpD,WAAO,gBAAgB,cAAc,EAAE,IAAI,MAAM,GAAA,GAAM,KAAK;AAAA,EAC9D;AAGO,SAAA,gBAAgB,cAAc,KAAK;AAC5C;AAEM,MAAA,kBAAkB,OACtB,KACA,sBACG;AACG,QAAA,iBAAiB,KAAK,iBAAiB;AAC7C,QAAM,OAAO,MAAM,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,kBAAkB,GAAG,EAAG,CAAA;AACxE;AAEA,MAAM,iBAAiB,OACrB,KACA,SACG;AACG,QAAA,QAAQ,OAAO,SAAS,GAAG;AAEjC,MAAI,EAAE,QAAQ,SAAS,OAAO,KAAK,OAAO,aAAa;AAC9C,WAAA,gBAAgB,KAAK,IAAI;AAAA,EAClC;AAEM,QAAA,gBAAgB,MAAM,gBAAgB,KAAK,EAAE,IAAI,KAAK,MAAM,IAAI;AACtE,QAAM,YAAYD,GAAA;AAAA;AAAA,IAEhBL,GAAAA,KAAK,IAAI;AAAA;AAAA,IAET,CAAC,YAAY,kBAAkB,OAAO,OAAO;AAAA;AAAA,IAE7CM,GAAAA,OAAO,aAAa;AAAA,EAAA;AAGtB,SAAO,OAAO,MAAM,GAAG,EAAE,MAAM,KAAK,IAAI,EAAE,MAAM,UAAU,IAAI,EAAG,CAAA;AACnE;;;;;;;;"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
3
|
+
const fp = require("lodash/fp");
|
|
4
4
|
const pickSelectionParams = (data) => {
|
|
5
|
-
return
|
|
5
|
+
return fp.pick(["fields", "populate"], data);
|
|
6
6
|
};
|
|
7
7
|
exports.pickSelectionParams = pickSelectionParams;
|
|
8
8
|
//# sourceMappingURL=params.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"params.js","sources":["../../../src/services/entity-service/params.ts"],"sourcesContent":["import { pick } from 'lodash/fp';\nimport type { Common, EntityService } from '@strapi/types';\n\nconst pickSelectionParams = <TUID extends Common.UID.ContentType>(\n data: unknown\n): EntityService.Params.Pick<TUID, 'fields' | 'populate'> => {\n return pick(['fields', 'populate'], data);\n};\n\nexport { pickSelectionParams };\n"],"names":["pick"],"mappings":";;;AAGM,MAAA,sBAAsB,CAC1B,SAC2D;AAC3D,SAAOA,
|
|
1
|
+
{"version":3,"file":"params.js","sources":["../../../src/services/entity-service/params.ts"],"sourcesContent":["import { pick } from 'lodash/fp';\nimport type { Common, EntityService } from '@strapi/types';\n\nconst pickSelectionParams = <TUID extends Common.UID.ContentType>(\n data: unknown\n): EntityService.Params.Pick<TUID, 'fields' | 'populate'> => {\n return pick(['fields', 'populate'], data);\n};\n\nexport { pickSelectionParams };\n"],"names":["pick"],"mappings":";;;AAGM,MAAA,sBAAsB,CAC1B,SAC2D;AAC3D,SAAOA,GAAK,KAAA,CAAC,UAAU,UAAU,GAAG,IAAI;AAC1C;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const _
|
|
3
|
-
const
|
|
2
|
+
const _ = require("lodash");
|
|
3
|
+
const fp = require("lodash/fp");
|
|
4
4
|
const strapiUtils = require("@strapi/utils");
|
|
5
5
|
const validators = require("./validators.js");
|
|
6
6
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
@@ -82,7 +82,7 @@ const createDzValidator = (createOrUpdate) => ({ attr, updatedAttribute }, { isD
|
|
|
82
82
|
let validator;
|
|
83
83
|
validator = yup.array().of(
|
|
84
84
|
yup.lazy((item) => {
|
|
85
|
-
const model = strapi.getModel(
|
|
85
|
+
const model = strapi.getModel(fp.prop("__component", item));
|
|
86
86
|
const schema = yup.object().shape({
|
|
87
87
|
__component: yup.string().required().oneOf(Object.keys(strapi.components))
|
|
88
88
|
}).notNull();
|
|
@@ -112,7 +112,7 @@ const createRelationValidator = (createOrUpdate) => ({ attr, updatedAttribute },
|
|
|
112
112
|
};
|
|
113
113
|
const createScalarAttributeValidator = (createOrUpdate) => (metas, options) => {
|
|
114
114
|
let validator;
|
|
115
|
-
if (
|
|
115
|
+
if (fp.has(metas.attr.type, validators)) {
|
|
116
116
|
validator = validators[metas.attr.type](metas, options);
|
|
117
117
|
} else {
|
|
118
118
|
validator = yup.mixed();
|
|
@@ -156,7 +156,7 @@ const createModelValidator = (createOrUpdate) => ({ model, data, entity }, optio
|
|
|
156
156
|
const schema = writableAttributes.reduce((validators2, attributeName) => {
|
|
157
157
|
const metas = {
|
|
158
158
|
attr: model.attributes[attributeName],
|
|
159
|
-
updatedAttribute: { name: attributeName, value:
|
|
159
|
+
updatedAttribute: { name: attributeName, value: fp.prop(attributeName, data) },
|
|
160
160
|
model,
|
|
161
161
|
entity
|
|
162
162
|
};
|
|
@@ -168,7 +168,7 @@ const createModelValidator = (createOrUpdate) => ({ model, data, entity }, optio
|
|
|
168
168
|
};
|
|
169
169
|
const createValidateEntity = (createOrUpdate) => {
|
|
170
170
|
return async (model, data, options, entity) => {
|
|
171
|
-
if (!
|
|
171
|
+
if (!fp.isObject(data)) {
|
|
172
172
|
const { displayName } = model.info;
|
|
173
173
|
throw new ValidationError(
|
|
174
174
|
`Invalid payload submitted for the ${createOrUpdate} of an entity of type ${displayName}. Expected an object, but got ${typeof data}`
|
|
@@ -201,14 +201,14 @@ const buildRelationsStore = ({
|
|
|
201
201
|
if (!uid) {
|
|
202
202
|
throw new ValidationError(`Cannot build relations store: "uid" is undefined`);
|
|
203
203
|
}
|
|
204
|
-
if (
|
|
204
|
+
if (fp.isEmpty(data)) {
|
|
205
205
|
return {};
|
|
206
206
|
}
|
|
207
207
|
const currentModel = strapi.getModel(uid);
|
|
208
208
|
return Object.keys(currentModel.attributes).reduce((result, attributeName) => {
|
|
209
209
|
const attribute = currentModel.attributes[attributeName];
|
|
210
210
|
const value = data[attributeName];
|
|
211
|
-
if (_
|
|
211
|
+
if (_.isNil(value)) {
|
|
212
212
|
return result;
|
|
213
213
|
}
|
|
214
214
|
switch (attribute.type) {
|
|
@@ -224,16 +224,16 @@ const buildRelationsStore = ({
|
|
|
224
224
|
let source;
|
|
225
225
|
if (Array.isArray(value)) {
|
|
226
226
|
source = value;
|
|
227
|
-
} else if (
|
|
228
|
-
if ("connect" in value && !_
|
|
227
|
+
} else if (fp.isObject(value)) {
|
|
228
|
+
if ("connect" in value && !_.isNil(value.connect)) {
|
|
229
229
|
source = value.connect;
|
|
230
|
-
} else if ("set" in value && !_
|
|
230
|
+
} else if ("set" in value && !_.isNil(value.set)) {
|
|
231
231
|
source = value.set;
|
|
232
232
|
} else {
|
|
233
233
|
source = [];
|
|
234
234
|
}
|
|
235
235
|
} else {
|
|
236
|
-
source = _
|
|
236
|
+
source = _.castArray(value);
|
|
237
237
|
}
|
|
238
238
|
const idArray = source.map((v) => ({
|
|
239
239
|
id: typeof v === "object" ? v.id : v
|
|
@@ -243,20 +243,20 @@ const buildRelationsStore = ({
|
|
|
243
243
|
break;
|
|
244
244
|
}
|
|
245
245
|
case "component": {
|
|
246
|
-
return _
|
|
246
|
+
return _.castArray(value).reduce((relationsStore, componentValue) => {
|
|
247
247
|
if (!attribute.component) {
|
|
248
248
|
throw new ValidationError(
|
|
249
249
|
`Cannot build relations store from component, component identifier is undefined`
|
|
250
250
|
);
|
|
251
251
|
}
|
|
252
|
-
return _
|
|
252
|
+
return _.mergeWith(
|
|
253
253
|
relationsStore,
|
|
254
254
|
buildRelationsStore({
|
|
255
255
|
uid: attribute.component,
|
|
256
256
|
data: componentValue
|
|
257
257
|
}),
|
|
258
258
|
(objValue, srcValue) => {
|
|
259
|
-
if (_
|
|
259
|
+
if (_.isArray(objValue)) {
|
|
260
260
|
return objValue.concat(srcValue);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
@@ -264,21 +264,21 @@ const buildRelationsStore = ({
|
|
|
264
264
|
}, result);
|
|
265
265
|
}
|
|
266
266
|
case "dynamiczone": {
|
|
267
|
-
return _
|
|
267
|
+
return _.castArray(value).reduce((relationsStore, dzValue) => {
|
|
268
268
|
const value2 = dzValue;
|
|
269
269
|
if (!value2.__component) {
|
|
270
270
|
throw new ValidationError(
|
|
271
271
|
`Cannot build relations store from dynamiczone, component identifier is undefined`
|
|
272
272
|
);
|
|
273
273
|
}
|
|
274
|
-
return _
|
|
274
|
+
return _.mergeWith(
|
|
275
275
|
relationsStore,
|
|
276
276
|
buildRelationsStore({
|
|
277
277
|
uid: value2.__component,
|
|
278
278
|
data: value2
|
|
279
279
|
}),
|
|
280
280
|
(objValue, srcValue) => {
|
|
281
|
-
if (_
|
|
281
|
+
if (_.isArray(objValue)) {
|
|
282
282
|
return objValue.concat(srcValue);
|
|
283
283
|
}
|
|
284
284
|
}
|
|
@@ -293,7 +293,7 @@ const checkRelationsExist = async (relationsStore = {}) => {
|
|
|
293
293
|
const promises = [];
|
|
294
294
|
for (const [key, value] of Object.entries(relationsStore)) {
|
|
295
295
|
const evaluate = async () => {
|
|
296
|
-
const uniqueValues = _
|
|
296
|
+
const uniqueValues = _.uniqBy(value, `id`);
|
|
297
297
|
const count = await strapi.query(key).count({
|
|
298
298
|
where: {
|
|
299
299
|
id: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/services/entity-validator/index.ts"],"sourcesContent":["/**\n * Entity validator\n * Module that will validate input data for entity creation or edition\n */\n\nimport { uniqBy, castArray, isNil, isArray, mergeWith } from 'lodash';\nimport { has, prop, isObject, isEmpty } from 'lodash/fp';\nimport strapiUtils from '@strapi/utils';\nimport { EntityValidator, Common, Schema, Attribute, Shared, EntityService } from '@strapi/types';\nimport validators from './validators';\n\ntype CreateOrUpdate = 'creation' | 'update';\n\nconst { yup, validateYupSchema } = strapiUtils;\nconst { isMediaAttribute, isScalarAttribute, getWritableAttributes } = strapiUtils.contentTypes;\nconst { ValidationError } = strapiUtils.errors;\n\ntype Entity = {\n id: ID;\n [key: string]: unknown;\n} | null;\n\ntype ID = { id: string | number };\n\ntype RelationSource = string | number | ID;\n\ninterface ValidatorMeta<TAttribute = Attribute.Any> {\n attr: TAttribute;\n updatedAttribute: { name: string; value: any };\n}\n\ninterface ValidatorContext {\n isDraft: boolean;\n}\n\ninterface AttributeValidatorMetas {\n attr: Attribute.Any;\n updatedAttribute: { name: string; value: unknown };\n model: Schema.ContentType | Schema.Component;\n entity?: Entity;\n}\n\ninterface ModelValidatorMetas {\n model: Schema.ContentType | Schema.Component;\n data: Record<string, unknown>;\n entity?: Entity;\n}\n\nconst isInteger = (value: unknown): value is number => Number.isInteger(value);\n\nconst addMinMax = <\n T extends {\n min(value: number): T;\n max(value: number): T;\n }\n>(\n validator: T,\n { attr, updatedAttribute }: ValidatorMeta<Attribute.Any & Attribute.MinMaxOption<string | number>>\n): T => {\n let nextValidator: T = validator;\n\n if (\n isInteger(attr.min) &&\n (('required' in attr && attr.required) ||\n (Array.isArray(updatedAttribute.value) && updatedAttribute.value.length > 0))\n ) {\n nextValidator = nextValidator.min(attr.min);\n }\n if (isInteger(attr.max)) {\n nextValidator = nextValidator.max(attr.max);\n }\n return nextValidator;\n};\n\nconst addRequiredValidation = (createOrUpdate: CreateOrUpdate) => {\n return <T extends strapiUtils.yup.AnySchema>(\n validator: T,\n { attr: { required } }: ValidatorMeta<Partial<Attribute.Any & Attribute.RequiredOption>>\n ): T => {\n let nextValidator = validator;\n\n if (required) {\n if (createOrUpdate === 'creation') {\n nextValidator = nextValidator.notNil();\n } else if (createOrUpdate === 'update') {\n nextValidator = nextValidator.notNull();\n }\n } else {\n nextValidator = nextValidator.nullable();\n }\n return nextValidator;\n };\n};\n\nconst addDefault = (createOrUpdate: CreateOrUpdate) => {\n return (\n validator: strapiUtils.yup.BaseSchema,\n { attr }: ValidatorMeta<Attribute.Any & Attribute.DefaultOption<unknown>>\n ) => {\n let nextValidator = validator;\n\n if (createOrUpdate === 'creation') {\n if (\n ((attr.type === 'component' && attr.repeatable) || attr.type === 'dynamiczone') &&\n !attr.required\n ) {\n nextValidator = nextValidator.default([]);\n } else {\n nextValidator = nextValidator.default(attr.default);\n }\n } else {\n nextValidator = nextValidator.default(undefined);\n }\n\n return nextValidator;\n };\n};\n\nconst preventCast = (validator: strapiUtils.yup.AnySchema) =>\n validator.transform((val, originalVal) => originalVal);\n\nconst createComponentValidator =\n (createOrUpdate: CreateOrUpdate) =>\n (\n { attr, updatedAttribute }: ValidatorMeta<Attribute.Component<Common.UID.Component, boolean>>,\n { isDraft }: ValidatorContext\n ) => {\n const model = strapi.getModel(attr.component);\n if (!model) {\n throw new Error('Validation failed: Model not found');\n }\n\n if (attr?.repeatable) {\n // FIXME: yup v1\n\n let validator = yup\n .array()\n .of(\n yup.lazy((item) =>\n createModelValidator(createOrUpdate)({ model, data: item }, { isDraft }).notNull()\n ) as any\n );\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: true },\n updatedAttribute,\n });\n\n validator = addMinMax(validator, { attr, updatedAttribute });\n\n return validator;\n }\n\n // FIXME: v4 was broken\n let validator = createModelValidator(createOrUpdate)(\n { model, data: updatedAttribute.value },\n { isDraft }\n );\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: !isDraft && attr.required },\n updatedAttribute,\n });\n\n return validator;\n };\n\nconst createDzValidator =\n (createOrUpdate: CreateOrUpdate) =>\n ({ attr, updatedAttribute }: ValidatorMeta, { isDraft }: ValidatorContext) => {\n let validator;\n\n validator = yup.array().of(\n yup.lazy((item) => {\n const model = strapi.getModel(prop('__component', item));\n const schema = yup\n .object()\n .shape({\n __component: yup.string().required().oneOf(Object.keys(strapi.components)),\n })\n .notNull();\n\n return model\n ? schema.concat(createModelValidator(createOrUpdate)({ model, data: item }, { isDraft }))\n : schema;\n }) as any // FIXME: yup v1\n );\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: true },\n updatedAttribute,\n });\n\n validator = addMinMax(validator, { attr, updatedAttribute });\n\n return validator;\n };\n\nconst createRelationValidator =\n (createOrUpdate: CreateOrUpdate) =>\n (\n { attr, updatedAttribute }: ValidatorMeta<Attribute.Relation>,\n { isDraft }: ValidatorContext\n ) => {\n let validator;\n\n if (Array.isArray(updatedAttribute.value)) {\n validator = yup.array().of(yup.mixed());\n } else {\n validator = yup.mixed();\n }\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: !isDraft && attr.required },\n updatedAttribute,\n });\n\n return validator;\n };\n\nconst createScalarAttributeValidator =\n (createOrUpdate: CreateOrUpdate) => (metas: ValidatorMeta, options: ValidatorContext) => {\n let validator;\n\n if (has(metas.attr.type, validators)) {\n validator = (validators as any)[metas.attr.type](metas, options);\n } else {\n // No validators specified - fall back to mixed\n validator = yup.mixed();\n }\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: !options.isDraft && metas.attr.required },\n updatedAttribute: metas.updatedAttribute,\n });\n\n return validator;\n };\n\nconst createAttributeValidator =\n (createOrUpdate: CreateOrUpdate) =>\n (metas: AttributeValidatorMetas, options: ValidatorContext) => {\n let validator = yup.mixed();\n\n if (isMediaAttribute(metas.attr)) {\n validator = yup.mixed();\n } else if (isScalarAttribute(metas.attr)) {\n validator = createScalarAttributeValidator(createOrUpdate)(metas, options);\n } else {\n if (metas.attr.type === 'component') {\n validator = createComponentValidator(createOrUpdate)(\n { attr: metas.attr, updatedAttribute: metas.updatedAttribute },\n options\n );\n } else if (metas.attr.type === 'dynamiczone') {\n validator = createDzValidator(createOrUpdate)(metas, options);\n } else if (metas.attr.type === 'relation') {\n validator = createRelationValidator(createOrUpdate)(\n {\n attr: metas.attr,\n updatedAttribute: metas.updatedAttribute,\n },\n options\n );\n }\n\n validator = preventCast(validator);\n }\n\n validator = addDefault(createOrUpdate)(validator, metas);\n\n return validator;\n };\n\nconst createModelValidator =\n (createOrUpdate: CreateOrUpdate) =>\n ({ model, data, entity }: ModelValidatorMetas, options: ValidatorContext) => {\n const writableAttributes = model ? getWritableAttributes(model as any) : [];\n\n const schema = writableAttributes.reduce((validators, attributeName) => {\n const metas = {\n attr: model.attributes[attributeName],\n updatedAttribute: { name: attributeName, value: prop(attributeName, data) },\n model,\n entity,\n };\n\n const validator = createAttributeValidator(createOrUpdate)(metas, options);\n\n validators[attributeName] = validator;\n\n return validators;\n }, {} as Record<string, strapiUtils.yup.BaseSchema>);\n\n return yup.object().shape(schema);\n };\n\nconst createValidateEntity = (createOrUpdate: CreateOrUpdate) => {\n return async <\n TUID extends Common.UID.ContentType,\n TData extends EntityService.Params.Data.Input<TUID>\n >(\n model: Shared.ContentTypes[TUID],\n data: TData | Partial<TData> | undefined,\n options?: { isDraft?: boolean },\n entity?: Entity\n ): Promise<TData> => {\n if (!isObject(data)) {\n const { displayName } = model.info;\n\n throw new ValidationError(\n `Invalid payload submitted for the ${createOrUpdate} of an entity of type ${displayName}. Expected an object, but got ${typeof data}`\n );\n }\n\n const validator = createModelValidator(createOrUpdate)(\n { model, data, entity },\n { isDraft: options?.isDraft ?? false }\n )\n .test('relations-test', 'check that all relations exist', async function (data) {\n try {\n await checkRelationsExist(buildRelationsStore({ uid: model.uid, data }));\n } catch (e) {\n return this.createError({\n path: this.path,\n message: (e instanceof ValidationError && e.message) || 'Invalid relations',\n });\n }\n return true;\n })\n .required();\n\n return validateYupSchema(validator, {\n strict: false,\n abortEarly: false,\n })(data);\n };\n};\n\n/**\n * Builds an object containing all the media and relations being associated with an entity\n */\nconst buildRelationsStore = <TUID extends Common.UID.ContentType | Common.UID.Component>({\n uid,\n data,\n}: {\n uid: TUID;\n data: Record<string, unknown> | null;\n}): Record<string, ID[]> => {\n if (!uid) {\n throw new ValidationError(`Cannot build relations store: \"uid\" is undefined`);\n }\n\n if (isEmpty(data)) {\n return {};\n }\n\n const currentModel = strapi.getModel(uid);\n\n return Object.keys(currentModel.attributes).reduce((result, attributeName: string) => {\n const attribute = currentModel.attributes[attributeName];\n const value = data[attributeName];\n\n if (isNil(value)) {\n return result;\n }\n\n switch (attribute.type) {\n case 'relation':\n case 'media': {\n if (\n attribute.type === 'relation' &&\n (attribute.relation === 'morphToMany' || attribute.relation === 'morphToOne')\n ) {\n // TODO: handle polymorphic relations\n break;\n }\n\n const target =\n // eslint-disable-next-line no-nested-ternary\n attribute.type === 'media' ? 'plugin::upload.file' : attribute.target;\n // As there are multiple formats supported for associating relations\n // with an entity, the value here can be an: array, object or number.\n let source: RelationSource[];\n if (Array.isArray(value)) {\n source = value;\n } else if (isObject(value)) {\n if ('connect' in value && !isNil(value.connect)) {\n source = value.connect as RelationSource[];\n } else if ('set' in value && !isNil(value.set)) {\n source = value.set as RelationSource[];\n } else {\n source = [];\n }\n } else {\n source = castArray(value as RelationSource);\n }\n const idArray = source.map((v) => ({\n id: typeof v === 'object' ? v.id : v,\n }));\n\n // Update the relationStore to keep track of all associations being made\n // with relations and media.\n result[target] = result[target] || [];\n result[target].push(...idArray);\n break;\n }\n case 'component': {\n return castArray(value).reduce((relationsStore, componentValue) => {\n if (!attribute.component) {\n throw new ValidationError(\n `Cannot build relations store from component, component identifier is undefined`\n );\n }\n\n return mergeWith(\n relationsStore,\n buildRelationsStore({\n uid: attribute.component,\n data: componentValue as Record<string, unknown>,\n }),\n (objValue, srcValue) => {\n if (isArray(objValue)) {\n return objValue.concat(srcValue);\n }\n }\n );\n }, result) as Record<string, ID[]>;\n }\n case 'dynamiczone': {\n return castArray(value).reduce((relationsStore, dzValue) => {\n const value = dzValue as Record<string, unknown>;\n if (!value.__component) {\n throw new ValidationError(\n `Cannot build relations store from dynamiczone, component identifier is undefined`\n );\n }\n\n return mergeWith(\n relationsStore,\n buildRelationsStore({\n uid: value.__component as Common.UID.Component,\n data: value,\n }),\n (objValue, srcValue) => {\n if (isArray(objValue)) {\n return objValue.concat(srcValue);\n }\n }\n );\n }, result) as Record<string, ID[]>;\n }\n default:\n break;\n }\n\n return result;\n }, {} as Record<string, ID[]>);\n};\n\n/**\n * Iterate through the relations store and validates that every relation or media\n * mentioned exists\n */\nconst checkRelationsExist = async (relationsStore: Record<string, ID[]> = {}) => {\n const promises = [];\n\n for (const [key, value] of Object.entries(relationsStore)) {\n const evaluate = async () => {\n const uniqueValues = uniqBy(value, `id`);\n const count = await strapi.query(key as Common.UID.Schema).count({\n where: {\n id: {\n $in: uniqueValues.map((v) => v.id),\n },\n },\n });\n\n if (count !== uniqueValues.length) {\n throw new ValidationError(\n `${\n uniqueValues.length - count\n } relation(s) of type ${key} associated with this entity do not exist`\n );\n }\n };\n promises.push(evaluate());\n }\n\n return Promise.all(promises);\n};\n\nconst entityValidator: EntityValidator = {\n validateEntityCreation: createValidateEntity('creation'),\n validateEntityUpdate: createValidateEntity('update'),\n};\n\nexport default entityValidator;\n"],"names":["strapiUtils","validator","prop","has","validators","isObject","data","isEmpty","isNil","castArray","mergeWith","isArray","value","uniqBy"],"mappings":";;;;;;;AAaA,MAAM,EAAE,KAAK,kBAAsB,IAAAA;AACnC,MAAM,EAAE,kBAAkB,mBAAmB,sBAAA,IAA0BA,qBAAAA,QAAY;AACnF,MAAM,EAAE,gBAAgB,IAAIA,qBAAY,QAAA;AAiCxC,MAAM,YAAY,CAAC,UAAoC,OAAO,UAAU,KAAK;AAE7E,MAAM,YAAY,CAMhB,WACA,EAAE,MAAM,uBACF;AACN,MAAI,gBAAmB;AAEvB,MACE,UAAU,KAAK,GAAG,MAChB,cAAc,QAAQ,KAAK,YAC1B,MAAM,QAAQ,iBAAiB,KAAK,KAAK,iBAAiB,MAAM,SAAS,IAC5E;AACgB,oBAAA,cAAc,IAAI,KAAK,GAAG;AAAA,EAC5C;AACI,MAAA,UAAU,KAAK,GAAG,GAAG;AACP,oBAAA,cAAc,IAAI,KAAK,GAAG;AAAA,EAC5C;AACO,SAAA;AACT;AAEA,MAAM,wBAAwB,CAAC,mBAAmC;AAChE,SAAO,CACL,WACA,EAAE,MAAM,EAAE,iBACJ;AACN,QAAI,gBAAgB;AAEpB,QAAI,UAAU;AACZ,UAAI,mBAAmB,YAAY;AACjC,wBAAgB,cAAc;MAAO,WAC5B,mBAAmB,UAAU;AACtC,wBAAgB,cAAc;MAChC;AAAA,IAAA,OACK;AACL,sBAAgB,cAAc;IAChC;AACO,WAAA;AAAA,EAAA;AAEX;AAEA,MAAM,aAAa,CAAC,mBAAmC;AACrD,SAAO,CACL,WACA,EAAE,WACC;AACH,QAAI,gBAAgB;AAEpB,QAAI,mBAAmB,YAAY;AAE7B,WAAA,KAAK,SAAS,eAAe,KAAK,cAAe,KAAK,SAAS,kBACjE,CAAC,KAAK,UACN;AACgB,wBAAA,cAAc,QAAQ,CAAA,CAAE;AAAA,MAAA,OACnC;AACW,wBAAA,cAAc,QAAQ,KAAK,OAAO;AAAA,MACpD;AAAA,IAAA,OACK;AACW,sBAAA,cAAc,QAAQ,MAAS;AAAA,IACjD;AAEO,WAAA;AAAA,EAAA;AAEX;AAEA,MAAM,cAAc,CAAC,cACnB,UAAU,UAAU,CAAC,KAAK,gBAAgB,WAAW;AAEvD,MAAM,2BACJ,CAAC,mBACD,CACE,EAAE,MAAM,iBAAiB,GACzB,EAAE,cACC;AACH,QAAM,QAAQ,OAAO,SAAS,KAAK,SAAS;AAC5C,MAAI,CAAC,OAAO;AACJ,UAAA,IAAI,MAAM,oCAAoC;AAAA,EACtD;AAEA,MAAI,MAAM,YAAY;AAGhBC,QAAAA,aAAY,IACb,MAAA,EACA;AAAA,MACC,IAAI;AAAA,QAAK,CAAC,SACR,qBAAqB,cAAc,EAAE,EAAE,OAAO,MAAM,QAAQ,EAAE,QAAS,CAAA,EAAE,QAAQ;AAAA,MACnF;AAAA,IAAA;AAGJA,iBAAY,sBAAsB,cAAc,EAAEA,YAAW;AAAA,MAC3D,MAAM,EAAE,UAAU,KAAK;AAAA,MACvB;AAAA,IAAA,CACD;AAEDA,iBAAY,UAAUA,YAAW,EAAE,MAAM,iBAAkB,CAAA;AAEpDA,WAAAA;AAAAA,EACT;AAGI,MAAA,YAAY,qBAAqB,cAAc;AAAA,IACjD,EAAE,OAAO,MAAM,iBAAiB,MAAM;AAAA,IACtC,EAAE,QAAQ;AAAA,EAAA;AAGA,cAAA,sBAAsB,cAAc,EAAE,WAAW;AAAA,IAC3D,MAAM,EAAE,UAAU,CAAC,WAAW,KAAK,SAAS;AAAA,IAC5C;AAAA,EAAA,CACD;AAEM,SAAA;AACT;AAEF,MAAM,oBACJ,CAAC,mBACD,CAAC,EAAE,MAAM,iBAAiB,GAAkB,EAAE,cAAgC;AACxE,MAAA;AAEQ,cAAA,IAAI,QAAQ;AAAA,IACtB,IAAI,KAAK,CAAC,SAAS;AACjB,YAAM,QAAQ,OAAO,SAASC,EAAK,KAAA,eAAe,IAAI,CAAC;AACvD,YAAM,SAAS,IACZ,OAAO,EACP,MAAM;AAAA,QACL,aAAa,IAAI,OAAS,EAAA,SAAW,EAAA,MAAM,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,MAAA,CAC1E,EACA,QAAQ;AAEX,aAAO,QACH,OAAO,OAAO,qBAAqB,cAAc,EAAE,EAAE,OAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,CAAC,IACtF;AAAA,IAAA,CACL;AAAA;AAAA,EAAA;AAGS,cAAA,sBAAsB,cAAc,EAAE,WAAW;AAAA,IAC3D,MAAM,EAAE,UAAU,KAAK;AAAA,IACvB;AAAA,EAAA,CACD;AAED,cAAY,UAAU,WAAW,EAAE,MAAM,iBAAkB,CAAA;AAEpD,SAAA;AACT;AAEF,MAAM,0BACJ,CAAC,mBACD,CACE,EAAE,MAAM,iBAAiB,GACzB,EAAE,cACC;AACC,MAAA;AAEJ,MAAI,MAAM,QAAQ,iBAAiB,KAAK,GAAG;AACzC,gBAAY,IAAI,MAAM,EAAE,GAAG,IAAI,OAAO;AAAA,EAAA,OACjC;AACL,gBAAY,IAAI;EAClB;AAEY,cAAA,sBAAsB,cAAc,EAAE,WAAW;AAAA,IAC3D,MAAM,EAAE,UAAU,CAAC,WAAW,KAAK,SAAS;AAAA,IAC5C;AAAA,EAAA,CACD;AAEM,SAAA;AACT;AAEF,MAAM,iCACJ,CAAC,mBAAmC,CAAC,OAAsB,YAA8B;AACnF,MAAA;AAEJ,MAAIC,EAAI,IAAA,MAAM,KAAK,MAAM,UAAU,GAAG;AACpC,gBAAa,WAAmB,MAAM,KAAK,IAAI,EAAE,OAAO,OAAO;AAAA,EAAA,OAC1D;AAEL,gBAAY,IAAI;EAClB;AAEY,cAAA,sBAAsB,cAAc,EAAE,WAAW;AAAA,IAC3D,MAAM,EAAE,UAAU,CAAC,QAAQ,WAAW,MAAM,KAAK,SAAS;AAAA,IAC1D,kBAAkB,MAAM;AAAA,EAAA,CACzB;AAEM,SAAA;AACT;AAEF,MAAM,2BACJ,CAAC,mBACD,CAAC,OAAgC,YAA8B;AACzD,MAAA,YAAY,IAAI;AAEhB,MAAA,iBAAiB,MAAM,IAAI,GAAG;AAChC,gBAAY,IAAI;EACP,WAAA,kBAAkB,MAAM,IAAI,GAAG;AACxC,gBAAY,+BAA+B,cAAc,EAAE,OAAO,OAAO;AAAA,EAAA,OACpE;AACD,QAAA,MAAM,KAAK,SAAS,aAAa;AACnC,kBAAY,yBAAyB,cAAc;AAAA,QACjD,EAAE,MAAM,MAAM,MAAM,kBAAkB,MAAM,iBAAiB;AAAA,QAC7D;AAAA,MAAA;AAAA,IAEO,WAAA,MAAM,KAAK,SAAS,eAAe;AAC5C,kBAAY,kBAAkB,cAAc,EAAE,OAAO,OAAO;AAAA,IACnD,WAAA,MAAM,KAAK,SAAS,YAAY;AACzC,kBAAY,wBAAwB,cAAc;AAAA,QAChD;AAAA,UACE,MAAM,MAAM;AAAA,UACZ,kBAAkB,MAAM;AAAA,QAC1B;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAEA,gBAAY,YAAY,SAAS;AAAA,EACnC;AAEA,cAAY,WAAW,cAAc,EAAE,WAAW,KAAK;AAEhD,SAAA;AACT;AAEF,MAAM,uBACJ,CAAC,mBACD,CAAC,EAAE,OAAO,MAAM,OAAO,GAAwB,YAA8B;AAC3E,QAAM,qBAAqB,QAAQ,sBAAsB,KAAY,IAAI,CAAA;AAEzE,QAAM,SAAS,mBAAmB,OAAO,CAACC,aAAY,kBAAkB;AACtE,UAAM,QAAQ;AAAA,MACZ,MAAM,MAAM,WAAW,aAAa;AAAA,MACpC,kBAAkB,EAAE,MAAM,eAAe,OAAOF,OAAK,eAAe,IAAI,EAAE;AAAA,MAC1E;AAAA,MACA;AAAA,IAAA;AAGF,UAAM,YAAY,yBAAyB,cAAc,EAAE,OAAO,OAAO;AAEzEE,gBAAW,aAAa,IAAI;AAErBA,WAAAA;AAAAA,EACT,GAAG,CAAgD,CAAA;AAEnD,SAAO,IAAI,OAAA,EAAS,MAAM,MAAM;AAClC;AAEF,MAAM,uBAAuB,CAAC,mBAAmC;AAC/D,SAAO,OAIL,OACA,MACA,SACA,WACmB;AACf,QAAA,CAACC,EAAAA,SAAS,IAAI,GAAG;AACb,YAAA,EAAE,YAAY,IAAI,MAAM;AAE9B,YAAM,IAAI;AAAA,QACR,qCAAqC,cAAc,yBAAyB,WAAW,iCAAiC,OAAO,IAAI;AAAA,MAAA;AAAA,IAEvI;AAEM,UAAA,YAAY,qBAAqB,cAAc;AAAA,MACnD,EAAE,OAAO,MAAM,OAAO;AAAA,MACtB,EAAE,SAAS,SAAS,WAAW,MAAM;AAAA,IAEpC,EAAA,KAAK,kBAAkB,kCAAkC,eAAgBC,OAAM;AAC1E,UAAA;AACI,cAAA,oBAAoB,oBAAoB,EAAE,KAAK,MAAM,KAAK,MAAAA,MAAM,CAAA,CAAC;AAAA,eAChE,GAAG;AACV,eAAO,KAAK,YAAY;AAAA,UACtB,MAAM,KAAK;AAAA,UACX,SAAU,aAAa,mBAAmB,EAAE,WAAY;AAAA,QAAA,CACzD;AAAA,MACH;AACO,aAAA;AAAA,IAAA,CACR,EACA,SAAS;AAEZ,WAAO,kBAAkB,WAAW;AAAA,MAClC,QAAQ;AAAA,MACR,YAAY;AAAA,IAAA,CACb,EAAE,IAAI;AAAA,EAAA;AAEX;AAKA,MAAM,sBAAsB,CAA6D;AAAA,EACvF;AAAA,EACA;AACF,MAG4B;AAC1B,MAAI,CAAC,KAAK;AACF,UAAA,IAAI,gBAAgB,kDAAkD;AAAA,EAC9E;AAEI,MAAAC,EAAAA,QAAQ,IAAI,GAAG;AACjB,WAAO;EACT;AAEM,QAAA,eAAe,OAAO,SAAS,GAAG;AAEjC,SAAA,OAAO,KAAK,aAAa,UAAU,EAAE,OAAO,CAAC,QAAQ,kBAA0B;AAC9E,UAAA,YAAY,aAAa,WAAW,aAAa;AACjD,UAAA,QAAQ,KAAK,aAAa;AAE5B,QAAAC,IAAAA,MAAM,KAAK,GAAG;AACT,aAAA;AAAA,IACT;AAEA,YAAQ,UAAU,MAAM;AAAA,MACtB,KAAK;AAAA,MACL,KAAK,SAAS;AAEV,YAAA,UAAU,SAAS,eAClB,UAAU,aAAa,iBAAiB,UAAU,aAAa,eAChE;AAEA;AAAA,QACF;AAEM,cAAA;AAAA;AAAA,UAEJ,UAAU,SAAS,UAAU,wBAAwB,UAAU;AAAA;AAG7D,YAAA;AACA,YAAA,MAAM,QAAQ,KAAK,GAAG;AACf,mBAAA;AAAA,QAAA,WACAH,EAAAA,SAAS,KAAK,GAAG;AAC1B,cAAI,aAAa,SAAS,CAACG,IAAM,MAAA,MAAM,OAAO,GAAG;AAC/C,qBAAS,MAAM;AAAA,UAAA,WACN,SAAS,SAAS,CAACA,IAAAA,MAAM,MAAM,GAAG,GAAG;AAC9C,qBAAS,MAAM;AAAA,UAAA,OACV;AACL,qBAAS,CAAA;AAAA,UACX;AAAA,QAAA,OACK;AACL,mBAASC,IAAAA,UAAU,KAAuB;AAAA,QAC5C;AACA,cAAM,UAAU,OAAO,IAAI,CAAC,OAAO;AAAA,UACjC,IAAI,OAAO,MAAM,WAAW,EAAE,KAAK;AAAA,QACnC,EAAA;AAIF,eAAO,MAAM,IAAI,OAAO,MAAM,KAAK,CAAA;AACnC,eAAO,MAAM,EAAE,KAAK,GAAG,OAAO;AAC9B;AAAA,MACF;AAAA,MACA,KAAK,aAAa;AAChB,eAAOA,IAAAA,UAAU,KAAK,EAAE,OAAO,CAAC,gBAAgB,mBAAmB;AAC7D,cAAA,CAAC,UAAU,WAAW;AACxB,kBAAM,IAAI;AAAA,cACR;AAAA,YAAA;AAAA,UAEJ;AAEO,iBAAAC,IAAA;AAAA,YACL;AAAA,YACA,oBAAoB;AAAA,cAClB,KAAK,UAAU;AAAA,cACf,MAAM;AAAA,YAAA,CACP;AAAA,YACD,CAAC,UAAU,aAAa;AAClB,kBAAAC,IAAAA,QAAQ,QAAQ,GAAG;AACd,uBAAA,SAAS,OAAO,QAAQ;AAAA,cACjC;AAAA,YACF;AAAA,UAAA;AAAA,WAED,MAAM;AAAA,MACX;AAAA,MACA,KAAK,eAAe;AAClB,eAAOF,IAAAA,UAAU,KAAK,EAAE,OAAO,CAAC,gBAAgB,YAAY;AAC1D,gBAAMG,SAAQ;AACV,cAAA,CAACA,OAAM,aAAa;AACtB,kBAAM,IAAI;AAAA,cACR;AAAA,YAAA;AAAA,UAEJ;AAEO,iBAAAF,IAAA;AAAA,YACL;AAAA,YACA,oBAAoB;AAAA,cAClB,KAAKE,OAAM;AAAA,cACX,MAAMA;AAAAA,YAAA,CACP;AAAA,YACD,CAAC,UAAU,aAAa;AAClB,kBAAAD,IAAAA,QAAQ,QAAQ,GAAG;AACd,uBAAA,SAAS,OAAO,QAAQ;AAAA,cACjC;AAAA,YACF;AAAA,UAAA;AAAA,WAED,MAAM;AAAA,MACX;AAAA,IAGF;AAEO,WAAA;AAAA,EACT,GAAG,CAA0B,CAAA;AAC/B;AAMA,MAAM,sBAAsB,OAAO,iBAAuC,OAAO;AAC/E,QAAM,WAAW,CAAA;AAEjB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,cAAc,GAAG;AACzD,UAAM,WAAW,YAAY;AACrB,YAAA,eAAeE,IAAO,OAAA,OAAO,IAAI;AACvC,YAAM,QAAQ,MAAM,OAAO,MAAM,GAAwB,EAAE,MAAM;AAAA,QAC/D,OAAO;AAAA,UACL,IAAI;AAAA,YACF,KAAK,aAAa,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,UACnC;AAAA,QACF;AAAA,MAAA,CACD;AAEG,UAAA,UAAU,aAAa,QAAQ;AACjC,cAAM,IAAI;AAAA,UACR,GACE,aAAa,SAAS,KACxB,wBAAwB,GAAG;AAAA,QAAA;AAAA,MAE/B;AAAA,IAAA;AAEO,aAAA,KAAK,UAAU;AAAA,EAC1B;AAEO,SAAA,QAAQ,IAAI,QAAQ;AAC7B;AAEA,MAAM,kBAAmC;AAAA,EACvC,wBAAwB,qBAAqB,UAAU;AAAA,EACvD,sBAAsB,qBAAqB,QAAQ;AACrD;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/services/entity-validator/index.ts"],"sourcesContent":["/**\n * Entity validator\n * Module that will validate input data for entity creation or edition\n */\n\nimport { uniqBy, castArray, isNil, isArray, mergeWith } from 'lodash';\nimport { has, prop, isObject, isEmpty } from 'lodash/fp';\nimport strapiUtils from '@strapi/utils';\nimport { EntityValidator, Common, Schema, Attribute, Shared, EntityService } from '@strapi/types';\nimport validators from './validators';\n\ntype CreateOrUpdate = 'creation' | 'update';\n\nconst { yup, validateYupSchema } = strapiUtils;\nconst { isMediaAttribute, isScalarAttribute, getWritableAttributes } = strapiUtils.contentTypes;\nconst { ValidationError } = strapiUtils.errors;\n\ntype Entity = {\n id: ID;\n [key: string]: unknown;\n} | null;\n\ntype ID = { id: string | number };\n\ntype RelationSource = string | number | ID;\n\ninterface ValidatorMeta<TAttribute = Attribute.Any> {\n attr: TAttribute;\n updatedAttribute: { name: string; value: any };\n}\n\ninterface ValidatorContext {\n isDraft: boolean;\n}\n\ninterface AttributeValidatorMetas {\n attr: Attribute.Any;\n updatedAttribute: { name: string; value: unknown };\n model: Schema.ContentType | Schema.Component;\n entity?: Entity;\n}\n\ninterface ModelValidatorMetas {\n model: Schema.ContentType | Schema.Component;\n data: Record<string, unknown>;\n entity?: Entity;\n}\n\nconst isInteger = (value: unknown): value is number => Number.isInteger(value);\n\nconst addMinMax = <\n T extends {\n min(value: number): T;\n max(value: number): T;\n }\n>(\n validator: T,\n { attr, updatedAttribute }: ValidatorMeta<Attribute.Any & Attribute.MinMaxOption<string | number>>\n): T => {\n let nextValidator: T = validator;\n\n if (\n isInteger(attr.min) &&\n (('required' in attr && attr.required) ||\n (Array.isArray(updatedAttribute.value) && updatedAttribute.value.length > 0))\n ) {\n nextValidator = nextValidator.min(attr.min);\n }\n if (isInteger(attr.max)) {\n nextValidator = nextValidator.max(attr.max);\n }\n return nextValidator;\n};\n\nconst addRequiredValidation = (createOrUpdate: CreateOrUpdate) => {\n return <T extends strapiUtils.yup.AnySchema>(\n validator: T,\n { attr: { required } }: ValidatorMeta<Partial<Attribute.Any & Attribute.RequiredOption>>\n ): T => {\n let nextValidator = validator;\n\n if (required) {\n if (createOrUpdate === 'creation') {\n nextValidator = nextValidator.notNil();\n } else if (createOrUpdate === 'update') {\n nextValidator = nextValidator.notNull();\n }\n } else {\n nextValidator = nextValidator.nullable();\n }\n return nextValidator;\n };\n};\n\nconst addDefault = (createOrUpdate: CreateOrUpdate) => {\n return (\n validator: strapiUtils.yup.BaseSchema,\n { attr }: ValidatorMeta<Attribute.Any & Attribute.DefaultOption<unknown>>\n ) => {\n let nextValidator = validator;\n\n if (createOrUpdate === 'creation') {\n if (\n ((attr.type === 'component' && attr.repeatable) || attr.type === 'dynamiczone') &&\n !attr.required\n ) {\n nextValidator = nextValidator.default([]);\n } else {\n nextValidator = nextValidator.default(attr.default);\n }\n } else {\n nextValidator = nextValidator.default(undefined);\n }\n\n return nextValidator;\n };\n};\n\nconst preventCast = (validator: strapiUtils.yup.AnySchema) =>\n validator.transform((val, originalVal) => originalVal);\n\nconst createComponentValidator =\n (createOrUpdate: CreateOrUpdate) =>\n (\n { attr, updatedAttribute }: ValidatorMeta<Attribute.Component<Common.UID.Component, boolean>>,\n { isDraft }: ValidatorContext\n ) => {\n const model = strapi.getModel(attr.component);\n if (!model) {\n throw new Error('Validation failed: Model not found');\n }\n\n if (attr?.repeatable) {\n // FIXME: yup v1\n\n let validator = yup\n .array()\n .of(\n yup.lazy((item) =>\n createModelValidator(createOrUpdate)({ model, data: item }, { isDraft }).notNull()\n ) as any\n );\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: true },\n updatedAttribute,\n });\n\n validator = addMinMax(validator, { attr, updatedAttribute });\n\n return validator;\n }\n\n // FIXME: v4 was broken\n let validator = createModelValidator(createOrUpdate)(\n { model, data: updatedAttribute.value },\n { isDraft }\n );\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: !isDraft && attr.required },\n updatedAttribute,\n });\n\n return validator;\n };\n\nconst createDzValidator =\n (createOrUpdate: CreateOrUpdate) =>\n ({ attr, updatedAttribute }: ValidatorMeta, { isDraft }: ValidatorContext) => {\n let validator;\n\n validator = yup.array().of(\n yup.lazy((item) => {\n const model = strapi.getModel(prop('__component', item));\n const schema = yup\n .object()\n .shape({\n __component: yup.string().required().oneOf(Object.keys(strapi.components)),\n })\n .notNull();\n\n return model\n ? schema.concat(createModelValidator(createOrUpdate)({ model, data: item }, { isDraft }))\n : schema;\n }) as any // FIXME: yup v1\n );\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: true },\n updatedAttribute,\n });\n\n validator = addMinMax(validator, { attr, updatedAttribute });\n\n return validator;\n };\n\nconst createRelationValidator =\n (createOrUpdate: CreateOrUpdate) =>\n (\n { attr, updatedAttribute }: ValidatorMeta<Attribute.Relation>,\n { isDraft }: ValidatorContext\n ) => {\n let validator;\n\n if (Array.isArray(updatedAttribute.value)) {\n validator = yup.array().of(yup.mixed());\n } else {\n validator = yup.mixed();\n }\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: !isDraft && attr.required },\n updatedAttribute,\n });\n\n return validator;\n };\n\nconst createScalarAttributeValidator =\n (createOrUpdate: CreateOrUpdate) => (metas: ValidatorMeta, options: ValidatorContext) => {\n let validator;\n\n if (has(metas.attr.type, validators)) {\n validator = (validators as any)[metas.attr.type](metas, options);\n } else {\n // No validators specified - fall back to mixed\n validator = yup.mixed();\n }\n\n validator = addRequiredValidation(createOrUpdate)(validator, {\n attr: { required: !options.isDraft && metas.attr.required },\n updatedAttribute: metas.updatedAttribute,\n });\n\n return validator;\n };\n\nconst createAttributeValidator =\n (createOrUpdate: CreateOrUpdate) =>\n (metas: AttributeValidatorMetas, options: ValidatorContext) => {\n let validator = yup.mixed();\n\n if (isMediaAttribute(metas.attr)) {\n validator = yup.mixed();\n } else if (isScalarAttribute(metas.attr)) {\n validator = createScalarAttributeValidator(createOrUpdate)(metas, options);\n } else {\n if (metas.attr.type === 'component') {\n validator = createComponentValidator(createOrUpdate)(\n { attr: metas.attr, updatedAttribute: metas.updatedAttribute },\n options\n );\n } else if (metas.attr.type === 'dynamiczone') {\n validator = createDzValidator(createOrUpdate)(metas, options);\n } else if (metas.attr.type === 'relation') {\n validator = createRelationValidator(createOrUpdate)(\n {\n attr: metas.attr,\n updatedAttribute: metas.updatedAttribute,\n },\n options\n );\n }\n\n validator = preventCast(validator);\n }\n\n validator = addDefault(createOrUpdate)(validator, metas);\n\n return validator;\n };\n\nconst createModelValidator =\n (createOrUpdate: CreateOrUpdate) =>\n ({ model, data, entity }: ModelValidatorMetas, options: ValidatorContext) => {\n const writableAttributes = model ? getWritableAttributes(model as any) : [];\n\n const schema = writableAttributes.reduce((validators, attributeName) => {\n const metas = {\n attr: model.attributes[attributeName],\n updatedAttribute: { name: attributeName, value: prop(attributeName, data) },\n model,\n entity,\n };\n\n const validator = createAttributeValidator(createOrUpdate)(metas, options);\n\n validators[attributeName] = validator;\n\n return validators;\n }, {} as Record<string, strapiUtils.yup.BaseSchema>);\n\n return yup.object().shape(schema);\n };\n\nconst createValidateEntity = (createOrUpdate: CreateOrUpdate) => {\n return async <\n TUID extends Common.UID.ContentType,\n TData extends EntityService.Params.Data.Input<TUID>\n >(\n model: Shared.ContentTypes[TUID],\n data: TData | Partial<TData> | undefined,\n options?: { isDraft?: boolean },\n entity?: Entity\n ): Promise<TData> => {\n if (!isObject(data)) {\n const { displayName } = model.info;\n\n throw new ValidationError(\n `Invalid payload submitted for the ${createOrUpdate} of an entity of type ${displayName}. Expected an object, but got ${typeof data}`\n );\n }\n\n const validator = createModelValidator(createOrUpdate)(\n { model, data, entity },\n { isDraft: options?.isDraft ?? false }\n )\n .test('relations-test', 'check that all relations exist', async function (data) {\n try {\n await checkRelationsExist(buildRelationsStore({ uid: model.uid, data }));\n } catch (e) {\n return this.createError({\n path: this.path,\n message: (e instanceof ValidationError && e.message) || 'Invalid relations',\n });\n }\n return true;\n })\n .required();\n\n return validateYupSchema(validator, {\n strict: false,\n abortEarly: false,\n })(data);\n };\n};\n\n/**\n * Builds an object containing all the media and relations being associated with an entity\n */\nconst buildRelationsStore = <TUID extends Common.UID.ContentType | Common.UID.Component>({\n uid,\n data,\n}: {\n uid: TUID;\n data: Record<string, unknown> | null;\n}): Record<string, ID[]> => {\n if (!uid) {\n throw new ValidationError(`Cannot build relations store: \"uid\" is undefined`);\n }\n\n if (isEmpty(data)) {\n return {};\n }\n\n const currentModel = strapi.getModel(uid);\n\n return Object.keys(currentModel.attributes).reduce((result, attributeName: string) => {\n const attribute = currentModel.attributes[attributeName];\n const value = data[attributeName];\n\n if (isNil(value)) {\n return result;\n }\n\n switch (attribute.type) {\n case 'relation':\n case 'media': {\n if (\n attribute.type === 'relation' &&\n (attribute.relation === 'morphToMany' || attribute.relation === 'morphToOne')\n ) {\n // TODO: handle polymorphic relations\n break;\n }\n\n const target =\n // eslint-disable-next-line no-nested-ternary\n attribute.type === 'media' ? 'plugin::upload.file' : attribute.target;\n // As there are multiple formats supported for associating relations\n // with an entity, the value here can be an: array, object or number.\n let source: RelationSource[];\n if (Array.isArray(value)) {\n source = value;\n } else if (isObject(value)) {\n if ('connect' in value && !isNil(value.connect)) {\n source = value.connect as RelationSource[];\n } else if ('set' in value && !isNil(value.set)) {\n source = value.set as RelationSource[];\n } else {\n source = [];\n }\n } else {\n source = castArray(value as RelationSource);\n }\n const idArray = source.map((v) => ({\n id: typeof v === 'object' ? v.id : v,\n }));\n\n // Update the relationStore to keep track of all associations being made\n // with relations and media.\n result[target] = result[target] || [];\n result[target].push(...idArray);\n break;\n }\n case 'component': {\n return castArray(value).reduce((relationsStore, componentValue) => {\n if (!attribute.component) {\n throw new ValidationError(\n `Cannot build relations store from component, component identifier is undefined`\n );\n }\n\n return mergeWith(\n relationsStore,\n buildRelationsStore({\n uid: attribute.component,\n data: componentValue as Record<string, unknown>,\n }),\n (objValue, srcValue) => {\n if (isArray(objValue)) {\n return objValue.concat(srcValue);\n }\n }\n );\n }, result) as Record<string, ID[]>;\n }\n case 'dynamiczone': {\n return castArray(value).reduce((relationsStore, dzValue) => {\n const value = dzValue as Record<string, unknown>;\n if (!value.__component) {\n throw new ValidationError(\n `Cannot build relations store from dynamiczone, component identifier is undefined`\n );\n }\n\n return mergeWith(\n relationsStore,\n buildRelationsStore({\n uid: value.__component as Common.UID.Component,\n data: value,\n }),\n (objValue, srcValue) => {\n if (isArray(objValue)) {\n return objValue.concat(srcValue);\n }\n }\n );\n }, result) as Record<string, ID[]>;\n }\n default:\n break;\n }\n\n return result;\n }, {} as Record<string, ID[]>);\n};\n\n/**\n * Iterate through the relations store and validates that every relation or media\n * mentioned exists\n */\nconst checkRelationsExist = async (relationsStore: Record<string, ID[]> = {}) => {\n const promises = [];\n\n for (const [key, value] of Object.entries(relationsStore)) {\n const evaluate = async () => {\n const uniqueValues = uniqBy(value, `id`);\n const count = await strapi.query(key as Common.UID.Schema).count({\n where: {\n id: {\n $in: uniqueValues.map((v) => v.id),\n },\n },\n });\n\n if (count !== uniqueValues.length) {\n throw new ValidationError(\n `${\n uniqueValues.length - count\n } relation(s) of type ${key} associated with this entity do not exist`\n );\n }\n };\n promises.push(evaluate());\n }\n\n return Promise.all(promises);\n};\n\nconst entityValidator: EntityValidator = {\n validateEntityCreation: createValidateEntity('creation'),\n validateEntityUpdate: createValidateEntity('update'),\n};\n\nexport default entityValidator;\n"],"names":["strapiUtils","validator","prop","has","validators","isObject","data","isEmpty","isNil","castArray","mergeWith","isArray","value","uniqBy"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
2
|
+
const fp = require("lodash/fp");
|
|
3
3
|
const strapiUtils = require("@strapi/utils");
|
|
4
4
|
const compose = require("koa-compose");
|
|
5
5
|
const middleware = require("./middleware.js");
|
|
@@ -7,9 +7,9 @@ const policy = require("./policy.js");
|
|
|
7
7
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
8
8
|
const compose__default = /* @__PURE__ */ _interopDefault(compose);
|
|
9
9
|
const getMethod = (route) => {
|
|
10
|
-
return
|
|
10
|
+
return fp.trim(fp.toLower(route.method));
|
|
11
11
|
};
|
|
12
|
-
const getPath = (route) =>
|
|
12
|
+
const getPath = (route) => fp.trim(route.path);
|
|
13
13
|
const createRouteInfoMiddleware = (routeInfo) => (ctx, next) => {
|
|
14
14
|
const route = {
|
|
15
15
|
...routeInfo,
|
|
@@ -18,7 +18,7 @@ const createRouteInfoMiddleware = (routeInfo) => (ctx, next) => {
|
|
|
18
18
|
ctx.state.route = route;
|
|
19
19
|
return next();
|
|
20
20
|
};
|
|
21
|
-
const getAuthConfig =
|
|
21
|
+
const getAuthConfig = fp.prop("config.auth");
|
|
22
22
|
const createAuthorizeMiddleware = (strapi) => async (ctx, next) => {
|
|
23
23
|
const { auth, route } = ctx.state;
|
|
24
24
|
const authService = strapi.container.get("auth");
|
|
@@ -40,7 +40,7 @@ const createAuthenticateMiddleware = (strapi) => async (ctx, next) => {
|
|
|
40
40
|
};
|
|
41
41
|
const returnBodyMiddleware = async (ctx, next) => {
|
|
42
42
|
const values = await next();
|
|
43
|
-
if (
|
|
43
|
+
if (fp.isNil(ctx.body) && !fp.isNil(values)) {
|
|
44
44
|
ctx.body = values;
|
|
45
45
|
}
|
|
46
46
|
};
|
|
@@ -61,7 +61,7 @@ const createEndpointComposer = (strapi) => {
|
|
|
61
61
|
...policies,
|
|
62
62
|
...middlewares,
|
|
63
63
|
returnBodyMiddleware,
|
|
64
|
-
...
|
|
64
|
+
...fp.castArray(action)
|
|
65
65
|
]);
|
|
66
66
|
router[method](path, routeHandler);
|
|
67
67
|
} catch (error) {
|
|
@@ -99,7 +99,7 @@ const getAction = (route, strapi) => {
|
|
|
99
99
|
if (Array.isArray(handler) || typeof handler === "function") {
|
|
100
100
|
return handler;
|
|
101
101
|
}
|
|
102
|
-
const { controllerName, actionName } = extractHandlerParts(
|
|
102
|
+
const { controllerName, actionName } = extractHandlerParts(fp.trim(handler));
|
|
103
103
|
const controller = getController(controllerName, { pluginName, apiName, type }, strapi);
|
|
104
104
|
if (typeof controller[actionName] !== "function") {
|
|
105
105
|
throw new Error(`Handler not found "${handler}"`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose-endpoint.js","sources":["../../../src/services/server/compose-endpoint.ts"],"sourcesContent":["import { toLower, castArray, trim, prop, isNil } from 'lodash/fp';\nimport type { Strapi, Common } from '@strapi/types';\nimport { errors } from '@strapi/utils';\nimport Router from '@koa/router';\n\nimport compose from 'koa-compose';\nimport { resolveRouteMiddlewares } from './middleware';\nimport { resolvePolicies } from './policy';\n\nconst getMethod = (route: Common.Route) => {\n return trim(toLower(route.method)) as Lowercase<Common.Route['method']>;\n};\n\nconst getPath = (route: Common.Route) => trim(route.path);\n\nconst createRouteInfoMiddleware =\n (routeInfo: Common.Route): Common.MiddlewareHandler =>\n (ctx, next) => {\n const route = {\n ...routeInfo,\n config: routeInfo.config || {},\n };\n\n ctx.state.route = route;\n return next();\n };\n\nconst getAuthConfig = prop('config.auth');\n\nconst createAuthorizeMiddleware =\n (strapi: Strapi): Common.MiddlewareHandler =>\n async (ctx, next) => {\n const { auth, route } = ctx.state;\n\n const authService = strapi.container.get('auth');\n\n try {\n await authService.verify(auth, getAuthConfig(route));\n\n return await next();\n } catch (error) {\n if (error instanceof errors.UnauthorizedError) {\n return ctx.unauthorized();\n }\n\n if (error instanceof errors.ForbiddenError) {\n return ctx.forbidden();\n }\n\n throw error;\n }\n };\n\nconst createAuthenticateMiddleware =\n (strapi: Strapi): Common.MiddlewareHandler =>\n async (ctx, next) => {\n return strapi.container.get('auth').authenticate(ctx, next);\n };\n\nconst returnBodyMiddleware: Common.MiddlewareHandler = async (ctx, next) => {\n const values = await next();\n\n if (isNil(ctx.body) && !isNil(values)) {\n ctx.body = values;\n }\n};\n\nexport default (strapi: Strapi) => {\n const authenticate = createAuthenticateMiddleware(strapi);\n const authorize = createAuthorizeMiddleware(strapi);\n\n return (route: Common.Route, { router }: { router: Router }) => {\n try {\n const method = getMethod(route);\n const path = getPath(route);\n\n const middlewares = resolveRouteMiddlewares(route, strapi);\n const policies = resolvePolicies(route);\n\n const action = getAction(route, strapi);\n\n const routeHandler = compose([\n createRouteInfoMiddleware(route),\n authenticate,\n authorize,\n ...policies,\n ...middlewares,\n returnBodyMiddleware,\n ...castArray(action),\n ]);\n\n router[method](path, routeHandler);\n } catch (error) {\n if (error instanceof Error) {\n error.message = `Error creating endpoint ${route.method} ${route.path}: ${error.message}`;\n }\n\n throw error;\n }\n };\n};\n\nconst getController = (name: string, { pluginName, apiName }: Common.RouteInfo, strapi: Strapi) => {\n let ctrl: Common.Controller | undefined;\n\n if (pluginName) {\n if (pluginName === 'admin') {\n ctrl = strapi.controller(`admin::${name}`);\n } else {\n ctrl = strapi.plugin(pluginName).controller(name);\n }\n } else if (apiName) {\n ctrl = strapi.controller(`api::${apiName}.${name}`);\n }\n\n if (!ctrl) {\n return strapi.controller(name as Common.UID.Controller);\n }\n\n return ctrl;\n};\n\nconst extractHandlerParts = (name: string) => {\n const controllerName = name.slice(0, name.lastIndexOf('.'));\n const actionName = name.slice(name.lastIndexOf('.') + 1);\n\n return { controllerName, actionName };\n};\n\nconst getAction = (route: Common.Route, strapi: Strapi) => {\n const { handler, info } = route;\n const { pluginName, apiName, type } = info ?? {};\n\n if (Array.isArray(handler) || typeof handler === 'function') {\n return handler;\n }\n\n const { controllerName, actionName } = extractHandlerParts(trim(handler));\n\n const controller = getController(controllerName, { pluginName, apiName, type }, strapi);\n\n if (typeof controller[actionName] !== 'function') {\n throw new Error(`Handler not found \"${handler}\"`);\n }\n\n if (Symbol.for('__type__') in controller[actionName]) {\n (controller[actionName] as any)[Symbol.for('__type__')].push(type);\n } else {\n (controller[actionName] as any)[Symbol.for('__type__')] = [type];\n }\n\n return controller[actionName].bind(controller);\n};\n"],"names":["trim","toLower","prop","errors","isNil","resolveRouteMiddlewares","resolvePolicies","compose","castArray"],"mappings":";;;;;;;;AASA,MAAM,YAAY,CAAC,UAAwB;AACzC,SAAOA,
|
|
1
|
+
{"version":3,"file":"compose-endpoint.js","sources":["../../../src/services/server/compose-endpoint.ts"],"sourcesContent":["import { toLower, castArray, trim, prop, isNil } from 'lodash/fp';\nimport type { Strapi, Common } from '@strapi/types';\nimport { errors } from '@strapi/utils';\nimport Router from '@koa/router';\n\nimport compose from 'koa-compose';\nimport { resolveRouteMiddlewares } from './middleware';\nimport { resolvePolicies } from './policy';\n\nconst getMethod = (route: Common.Route) => {\n return trim(toLower(route.method)) as Lowercase<Common.Route['method']>;\n};\n\nconst getPath = (route: Common.Route) => trim(route.path);\n\nconst createRouteInfoMiddleware =\n (routeInfo: Common.Route): Common.MiddlewareHandler =>\n (ctx, next) => {\n const route = {\n ...routeInfo,\n config: routeInfo.config || {},\n };\n\n ctx.state.route = route;\n return next();\n };\n\nconst getAuthConfig = prop('config.auth');\n\nconst createAuthorizeMiddleware =\n (strapi: Strapi): Common.MiddlewareHandler =>\n async (ctx, next) => {\n const { auth, route } = ctx.state;\n\n const authService = strapi.container.get('auth');\n\n try {\n await authService.verify(auth, getAuthConfig(route));\n\n return await next();\n } catch (error) {\n if (error instanceof errors.UnauthorizedError) {\n return ctx.unauthorized();\n }\n\n if (error instanceof errors.ForbiddenError) {\n return ctx.forbidden();\n }\n\n throw error;\n }\n };\n\nconst createAuthenticateMiddleware =\n (strapi: Strapi): Common.MiddlewareHandler =>\n async (ctx, next) => {\n return strapi.container.get('auth').authenticate(ctx, next);\n };\n\nconst returnBodyMiddleware: Common.MiddlewareHandler = async (ctx, next) => {\n const values = await next();\n\n if (isNil(ctx.body) && !isNil(values)) {\n ctx.body = values;\n }\n};\n\nexport default (strapi: Strapi) => {\n const authenticate = createAuthenticateMiddleware(strapi);\n const authorize = createAuthorizeMiddleware(strapi);\n\n return (route: Common.Route, { router }: { router: Router }) => {\n try {\n const method = getMethod(route);\n const path = getPath(route);\n\n const middlewares = resolveRouteMiddlewares(route, strapi);\n const policies = resolvePolicies(route);\n\n const action = getAction(route, strapi);\n\n const routeHandler = compose([\n createRouteInfoMiddleware(route),\n authenticate,\n authorize,\n ...policies,\n ...middlewares,\n returnBodyMiddleware,\n ...castArray(action),\n ]);\n\n router[method](path, routeHandler);\n } catch (error) {\n if (error instanceof Error) {\n error.message = `Error creating endpoint ${route.method} ${route.path}: ${error.message}`;\n }\n\n throw error;\n }\n };\n};\n\nconst getController = (name: string, { pluginName, apiName }: Common.RouteInfo, strapi: Strapi) => {\n let ctrl: Common.Controller | undefined;\n\n if (pluginName) {\n if (pluginName === 'admin') {\n ctrl = strapi.controller(`admin::${name}`);\n } else {\n ctrl = strapi.plugin(pluginName).controller(name);\n }\n } else if (apiName) {\n ctrl = strapi.controller(`api::${apiName}.${name}`);\n }\n\n if (!ctrl) {\n return strapi.controller(name as Common.UID.Controller);\n }\n\n return ctrl;\n};\n\nconst extractHandlerParts = (name: string) => {\n const controllerName = name.slice(0, name.lastIndexOf('.'));\n const actionName = name.slice(name.lastIndexOf('.') + 1);\n\n return { controllerName, actionName };\n};\n\nconst getAction = (route: Common.Route, strapi: Strapi) => {\n const { handler, info } = route;\n const { pluginName, apiName, type } = info ?? {};\n\n if (Array.isArray(handler) || typeof handler === 'function') {\n return handler;\n }\n\n const { controllerName, actionName } = extractHandlerParts(trim(handler));\n\n const controller = getController(controllerName, { pluginName, apiName, type }, strapi);\n\n if (typeof controller[actionName] !== 'function') {\n throw new Error(`Handler not found \"${handler}\"`);\n }\n\n if (Symbol.for('__type__') in controller[actionName]) {\n (controller[actionName] as any)[Symbol.for('__type__')].push(type);\n } else {\n (controller[actionName] as any)[Symbol.for('__type__')] = [type];\n }\n\n return controller[actionName].bind(controller);\n};\n"],"names":["trim","toLower","prop","errors","isNil","resolveRouteMiddlewares","resolvePolicies","compose","castArray"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
2
|
+
const fp = require("lodash/fp");
|
|
3
3
|
const Koa = require("koa");
|
|
4
4
|
const createError = require("http-errors");
|
|
5
5
|
const delegate = require("delegates");
|
|
@@ -14,7 +14,7 @@ const addCustomMethods = (app) => {
|
|
|
14
14
|
const delegator = delegate__default.default(app.context, "response");
|
|
15
15
|
statuses__default.default.codes.filter((code) => code >= 400 && code < 600).forEach((code) => {
|
|
16
16
|
const name = statuses__default.default(code);
|
|
17
|
-
const camelCasedName =
|
|
17
|
+
const camelCasedName = fp.camelCase(name);
|
|
18
18
|
app.response[camelCasedName] = function responseCode(message, details = {}) {
|
|
19
19
|
const httpError = createError__default.default(code, message, { details });
|
|
20
20
|
const { status, body } = errors.formatHttpError(httpError);
|
|
@@ -32,7 +32,7 @@ const addCustomMethods = (app) => {
|
|
|
32
32
|
this.body = data;
|
|
33
33
|
};
|
|
34
34
|
app.response.deleted = function deleted(data) {
|
|
35
|
-
if (
|
|
35
|
+
if (fp.isNil(data)) {
|
|
36
36
|
this.status = 204;
|
|
37
37
|
} else {
|
|
38
38
|
this.status = 200;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"koa.js","sources":["../../../src/services/server/koa.ts"],"sourcesContent":["import { isNil, camelCase } from 'lodash/fp';\nimport Koa from 'koa';\nimport createError from 'http-errors';\nimport delegate from 'delegates';\nimport statuses from 'statuses';\nimport { formatHttpError } from '../errors';\n\ndeclare module 'koa' {\n interface BaseResponse {\n send: (data: any, status?: number) => void;\n created: (data: any) => void;\n deleted: (data: any) => void;\n _explicitStatus: boolean;\n [key: string]: (message: string, details?: unknown) => void;\n }\n}\n\nconst addCustomMethods = (app: Koa) => {\n const delegator = delegate(app.context, 'response');\n\n /* errors */\n statuses.codes\n .filter((code) => code >= 400 && code < 600)\n .forEach((code) => {\n const name = statuses(code);\n const camelCasedName = camelCase(name);\n app.response[camelCasedName] = function responseCode(message, details = {}) {\n const httpError = createError(code, message, { details });\n const { status, body } = formatHttpError(httpError);\n this.status = status;\n this.body = body;\n };\n delegator.method(camelCasedName);\n });\n\n /* send, created, deleted */\n app.response.send = function send(data, status = 200) {\n this.status = status;\n this.body = data;\n };\n\n app.response.created = function created(data) {\n this.status = 201;\n this.body = data;\n };\n\n app.response.deleted = function deleted(data) {\n if (isNil(data)) {\n this.status = 204;\n } else {\n this.status = 200;\n this.body = data;\n }\n };\n\n delegator.method('send').method('created').method('deleted');\n\n return app;\n};\n\nconst createKoaApp = ({ proxy, keys }: { proxy: boolean; keys: string[] }) => {\n const app = new Koa({ proxy });\n app.keys = keys;\n\n addCustomMethods(app);\n\n return app;\n};\n\nexport default createKoaApp;\n"],"names":["delegate","statuses","camelCase","createError","formatHttpError","isNil","Koa"],"mappings":";;;;;;;;;;;;AAiBA,MAAM,mBAAmB,CAAC,QAAa;AACrC,QAAM,YAAYA,kBAAA,QAAS,IAAI,SAAS,UAAU;AAGzCC,oBAAAA,QAAA,MACN,OAAO,CAAC,SAAS,QAAQ,OAAO,OAAO,GAAG,EAC1C,QAAQ,CAAC,SAAS;AACX,UAAA,OAAOA,0BAAS,IAAI;AACpB,UAAA,iBAAiBC,
|
|
1
|
+
{"version":3,"file":"koa.js","sources":["../../../src/services/server/koa.ts"],"sourcesContent":["import { isNil, camelCase } from 'lodash/fp';\nimport Koa from 'koa';\nimport createError from 'http-errors';\nimport delegate from 'delegates';\nimport statuses from 'statuses';\nimport { formatHttpError } from '../errors';\n\ndeclare module 'koa' {\n interface BaseResponse {\n send: (data: any, status?: number) => void;\n created: (data: any) => void;\n deleted: (data: any) => void;\n _explicitStatus: boolean;\n [key: string]: (message: string, details?: unknown) => void;\n }\n}\n\nconst addCustomMethods = (app: Koa) => {\n const delegator = delegate(app.context, 'response');\n\n /* errors */\n statuses.codes\n .filter((code) => code >= 400 && code < 600)\n .forEach((code) => {\n const name = statuses(code);\n const camelCasedName = camelCase(name);\n app.response[camelCasedName] = function responseCode(message, details = {}) {\n const httpError = createError(code, message, { details });\n const { status, body } = formatHttpError(httpError);\n this.status = status;\n this.body = body;\n };\n delegator.method(camelCasedName);\n });\n\n /* send, created, deleted */\n app.response.send = function send(data, status = 200) {\n this.status = status;\n this.body = data;\n };\n\n app.response.created = function created(data) {\n this.status = 201;\n this.body = data;\n };\n\n app.response.deleted = function deleted(data) {\n if (isNil(data)) {\n this.status = 204;\n } else {\n this.status = 200;\n this.body = data;\n }\n };\n\n delegator.method('send').method('created').method('deleted');\n\n return app;\n};\n\nconst createKoaApp = ({ proxy, keys }: { proxy: boolean; keys: string[] }) => {\n const app = new Koa({ proxy });\n app.keys = keys;\n\n addCustomMethods(app);\n\n return app;\n};\n\nexport default createKoaApp;\n"],"names":["delegate","statuses","camelCase","createError","formatHttpError","isNil","Koa"],"mappings":";;;;;;;;;;;;AAiBA,MAAM,mBAAmB,CAAC,QAAa;AACrC,QAAM,YAAYA,kBAAA,QAAS,IAAI,SAAS,UAAU;AAGzCC,oBAAAA,QAAA,MACN,OAAO,CAAC,SAAS,QAAQ,OAAO,OAAO,GAAG,EAC1C,QAAQ,CAAC,SAAS;AACX,UAAA,OAAOA,0BAAS,IAAI;AACpB,UAAA,iBAAiBC,aAAU,IAAI;AACjC,QAAA,SAAS,cAAc,IAAI,SAAS,aAAa,SAAS,UAAU,IAAI;AAC1E,YAAM,YAAYC,qBAAAA,QAAY,MAAM,SAAS,EAAE,SAAS;AACxD,YAAM,EAAE,QAAQ,KAAK,IAAIC,uBAAgB,SAAS;AAClD,WAAK,SAAS;AACd,WAAK,OAAO;AAAA,IAAA;AAEd,cAAU,OAAO,cAAc;AAAA,EAAA,CAChC;AAGH,MAAI,SAAS,OAAO,SAAS,KAAK,MAAM,SAAS,KAAK;AACpD,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EAAA;AAGd,MAAI,SAAS,UAAU,SAAS,QAAQ,MAAM;AAC5C,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EAAA;AAGd,MAAI,SAAS,UAAU,SAAS,QAAQ,MAAM;AACxC,QAAAC,GAAAA,MAAM,IAAI,GAAG;AACf,WAAK,SAAS;AAAA,IAAA,OACT;AACL,WAAK,SAAS;AACd,WAAK,OAAO;AAAA,IACd;AAAA,EAAA;AAGF,YAAU,OAAO,MAAM,EAAE,OAAO,SAAS,EAAE,OAAO,SAAS;AAEpD,SAAA;AACT;AAEA,MAAM,eAAe,CAAC,EAAE,OAAO,WAA+C;AAC5E,QAAM,MAAM,IAAIC,aAAAA,QAAI,EAAE,MAAO,CAAA;AAC7B,MAAI,OAAO;AAEX,mBAAiB,GAAG;AAEb,SAAA;AACT;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const path = require("path");
|
|
4
|
-
const
|
|
4
|
+
const fp = require("lodash/fp");
|
|
5
5
|
const strapiUtils = require("@strapi/utils");
|
|
6
6
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
7
7
|
const path__default = /* @__PURE__ */ _interopDefault(path);
|
|
@@ -16,13 +16,13 @@ const instantiateMiddleware = (middlewareFactory, name, config, strapi) => {
|
|
|
16
16
|
};
|
|
17
17
|
const resolveRouteMiddlewares = (route, strapi) => {
|
|
18
18
|
const middlewaresConfig = route?.config?.middlewares ?? [];
|
|
19
|
-
if (!
|
|
19
|
+
if (!fp.isArray(middlewaresConfig)) {
|
|
20
20
|
throw new Error("Route middlewares config must be an array");
|
|
21
21
|
}
|
|
22
22
|
const middlewares = resolveMiddlewares(middlewaresConfig, strapi);
|
|
23
23
|
return middlewares.map(({ handler }) => handler);
|
|
24
24
|
};
|
|
25
|
-
const dummyMiddleware = (
|
|
25
|
+
const dummyMiddleware = (_, next) => next();
|
|
26
26
|
const resolveMiddlewares = (config, strapi) => {
|
|
27
27
|
const middlewares = [];
|
|
28
28
|
for (const item of config) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sources":["../../../src/services/server/middleware.ts"],"sourcesContent":["import path from 'path';\nimport { isArray } from 'lodash/fp';\nimport { importDefault } from '@strapi/utils';\nimport type { Strapi, Common } from '@strapi/types';\n\nconst instantiateMiddleware = (\n middlewareFactory: Common.MiddlewareFactory,\n name: string,\n config: unknown,\n strapi: Strapi\n) => {\n try {\n return middlewareFactory(config, { strapi });\n } catch (e) {\n if (e instanceof Error) {\n throw new Error(`Middleware \"${name}\": ${e.message}`);\n }\n }\n};\n\nconst resolveRouteMiddlewares = (route: Common.Route, strapi: Strapi) => {\n const middlewaresConfig = route?.config?.middlewares ?? [];\n\n if (!isArray(middlewaresConfig)) {\n throw new Error('Route middlewares config must be an array');\n }\n\n const middlewares = resolveMiddlewares(middlewaresConfig, strapi);\n\n return middlewares.map(({ handler }) => handler);\n};\n\nconst dummyMiddleware: Common.MiddlewareHandler = (_, next) => next();\n\n/**\n * Initialize every configured middlewares\n */\nconst resolveMiddlewares = (\n config: Array<\n | string\n | {\n name?: string;\n resolve?: string;\n config?: unknown;\n }\n | Common.MiddlewareHandler\n >,\n strapi: Strapi\n) => {\n const middlewares: {\n name: string | null;\n handler: Common.MiddlewareHandler;\n }[] = [];\n\n for (const item of config) {\n if (typeof item === 'function') {\n middlewares.push({\n name: null,\n handler: item,\n });\n\n continue;\n }\n\n if (typeof item === 'string') {\n const middlewareFactory = strapi.middleware(item);\n\n if (!middlewareFactory) {\n throw new Error(`Middleware ${item} not found.`);\n }\n\n middlewares.push({\n name: item,\n handler: instantiateMiddleware(middlewareFactory, item, {}, strapi) ?? dummyMiddleware,\n });\n\n continue;\n }\n\n if (typeof item === 'object' && item !== null) {\n const { name, resolve, config = {} } = item;\n\n if (name) {\n const middlewareFactory = strapi.middleware(name);\n middlewares.push({\n name,\n handler:\n instantiateMiddleware(middlewareFactory, name, config, strapi) ?? dummyMiddleware,\n });\n\n continue;\n }\n\n if (resolve) {\n const resolvedMiddlewareFactory = resolveCustomMiddleware(resolve, strapi);\n middlewares.push({\n name: resolve,\n handler:\n instantiateMiddleware(resolvedMiddlewareFactory, resolve, config, strapi) ??\n dummyMiddleware,\n });\n\n continue;\n }\n\n throw new Error('Invalid middleware configuration. Missing name or resolve properties.');\n }\n\n throw new Error(\n 'Middleware config must either be a string or an object {name?: string, resolve?: string, config: any}.'\n );\n }\n\n return middlewares;\n};\n\n/**\n * Resolve middleware from package name or path\n */\nconst resolveCustomMiddleware = (resolve: string, strapi: Strapi) => {\n let modulePath;\n\n try {\n modulePath = require.resolve(resolve);\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'MODULE_NOT_FOUND') {\n modulePath = path.resolve(strapi.dirs.dist.root, resolve);\n } else {\n throw error;\n }\n }\n\n try {\n return importDefault(modulePath);\n } catch (err) {\n throw new Error(`Could not load middleware \"${modulePath}\".`);\n }\n};\n\nexport { resolveRouteMiddlewares, resolveMiddlewares };\n"],"names":["isArray","
|
|
1
|
+
{"version":3,"file":"middleware.js","sources":["../../../src/services/server/middleware.ts"],"sourcesContent":["import path from 'path';\nimport { isArray } from 'lodash/fp';\nimport { importDefault } from '@strapi/utils';\nimport type { Strapi, Common } from '@strapi/types';\n\nconst instantiateMiddleware = (\n middlewareFactory: Common.MiddlewareFactory,\n name: string,\n config: unknown,\n strapi: Strapi\n) => {\n try {\n return middlewareFactory(config, { strapi });\n } catch (e) {\n if (e instanceof Error) {\n throw new Error(`Middleware \"${name}\": ${e.message}`);\n }\n }\n};\n\nconst resolveRouteMiddlewares = (route: Common.Route, strapi: Strapi) => {\n const middlewaresConfig = route?.config?.middlewares ?? [];\n\n if (!isArray(middlewaresConfig)) {\n throw new Error('Route middlewares config must be an array');\n }\n\n const middlewares = resolveMiddlewares(middlewaresConfig, strapi);\n\n return middlewares.map(({ handler }) => handler);\n};\n\nconst dummyMiddleware: Common.MiddlewareHandler = (_, next) => next();\n\n/**\n * Initialize every configured middlewares\n */\nconst resolveMiddlewares = (\n config: Array<\n | string\n | {\n name?: string;\n resolve?: string;\n config?: unknown;\n }\n | Common.MiddlewareHandler\n >,\n strapi: Strapi\n) => {\n const middlewares: {\n name: string | null;\n handler: Common.MiddlewareHandler;\n }[] = [];\n\n for (const item of config) {\n if (typeof item === 'function') {\n middlewares.push({\n name: null,\n handler: item,\n });\n\n continue;\n }\n\n if (typeof item === 'string') {\n const middlewareFactory = strapi.middleware(item);\n\n if (!middlewareFactory) {\n throw new Error(`Middleware ${item} not found.`);\n }\n\n middlewares.push({\n name: item,\n handler: instantiateMiddleware(middlewareFactory, item, {}, strapi) ?? dummyMiddleware,\n });\n\n continue;\n }\n\n if (typeof item === 'object' && item !== null) {\n const { name, resolve, config = {} } = item;\n\n if (name) {\n const middlewareFactory = strapi.middleware(name);\n middlewares.push({\n name,\n handler:\n instantiateMiddleware(middlewareFactory, name, config, strapi) ?? dummyMiddleware,\n });\n\n continue;\n }\n\n if (resolve) {\n const resolvedMiddlewareFactory = resolveCustomMiddleware(resolve, strapi);\n middlewares.push({\n name: resolve,\n handler:\n instantiateMiddleware(resolvedMiddlewareFactory, resolve, config, strapi) ??\n dummyMiddleware,\n });\n\n continue;\n }\n\n throw new Error('Invalid middleware configuration. Missing name or resolve properties.');\n }\n\n throw new Error(\n 'Middleware config must either be a string or an object {name?: string, resolve?: string, config: any}.'\n );\n }\n\n return middlewares;\n};\n\n/**\n * Resolve middleware from package name or path\n */\nconst resolveCustomMiddleware = (resolve: string, strapi: Strapi) => {\n let modulePath;\n\n try {\n modulePath = require.resolve(resolve);\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'MODULE_NOT_FOUND') {\n modulePath = path.resolve(strapi.dirs.dist.root, resolve);\n } else {\n throw error;\n }\n }\n\n try {\n return importDefault(modulePath);\n } catch (err) {\n throw new Error(`Could not load middleware \"${modulePath}\".`);\n }\n};\n\nexport { resolveRouteMiddlewares, resolveMiddlewares };\n"],"names":["isArray","config","path","importDefault"],"mappings":";;;;;;;AAKA,MAAM,wBAAwB,CAC5B,mBACA,MACA,QACA,WACG;AACC,MAAA;AACF,WAAO,kBAAkB,QAAQ,EAAE,OAAQ,CAAA;AAAA,WACpC,GAAG;AACV,QAAI,aAAa,OAAO;AACtB,YAAM,IAAI,MAAM,eAAe,IAAI,MAAM,EAAE,OAAO,EAAE;AAAA,IACtD;AAAA,EACF;AACF;AAEM,MAAA,0BAA0B,CAAC,OAAqB,WAAmB;AACvE,QAAM,oBAAoB,OAAO,QAAQ,eAAe,CAAA;AAEpD,MAAA,CAACA,GAAAA,QAAQ,iBAAiB,GAAG;AACzB,UAAA,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AAEM,QAAA,cAAc,mBAAmB,mBAAmB,MAAM;AAEhE,SAAO,YAAY,IAAI,CAAC,EAAE,cAAc,OAAO;AACjD;AAEA,MAAM,kBAA4C,CAAC,GAAG,SAAS,KAAK;AAK9D,MAAA,qBAAqB,CACzB,QASA,WACG;AACH,QAAM,cAGA,CAAA;AAEN,aAAW,QAAQ,QAAQ;AACrB,QAAA,OAAO,SAAS,YAAY;AAC9B,kBAAY,KAAK;AAAA,QACf,MAAM;AAAA,QACN,SAAS;AAAA,MAAA,CACV;AAED;AAAA,IACF;AAEI,QAAA,OAAO,SAAS,UAAU;AACtB,YAAA,oBAAoB,OAAO,WAAW,IAAI;AAEhD,UAAI,CAAC,mBAAmB;AACtB,cAAM,IAAI,MAAM,cAAc,IAAI,aAAa;AAAA,MACjD;AAEA,kBAAY,KAAK;AAAA,QACf,MAAM;AAAA,QACN,SAAS,sBAAsB,mBAAmB,MAAM,CAAC,GAAG,MAAM,KAAK;AAAA,MAAA,CACxE;AAED;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,YAAM,EAAE,MAAM,SAAS,QAAAC,UAAS,CAAA,EAAO,IAAA;AAEvC,UAAI,MAAM;AACF,cAAA,oBAAoB,OAAO,WAAW,IAAI;AAChD,oBAAY,KAAK;AAAA,UACf;AAAA,UACA,SACE,sBAAsB,mBAAmB,MAAMA,SAAQ,MAAM,KAAK;AAAA,QAAA,CACrE;AAED;AAAA,MACF;AAEA,UAAI,SAAS;AACL,cAAA,4BAA4B,wBAAwB,SAAS,MAAM;AACzE,oBAAY,KAAK;AAAA,UACf,MAAM;AAAA,UACN,SACE,sBAAsB,2BAA2B,SAASA,SAAQ,MAAM,KACxE;AAAA,QAAA,CACH;AAED;AAAA,MACF;AAEM,YAAA,IAAI,MAAM,uEAAuE;AAAA,IACzF;AAEA,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEO,SAAA;AACT;AAKA,MAAM,0BAA0B,CAAC,SAAiB,WAAmB;AAC/D,MAAA;AAEA,MAAA;AACW,iBAAA,QAAQ,QAAQ,OAAO;AAAA,WAC7B,OAAO;AACd,QAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,oBAAoB;AAClF,mBAAaC,cAAAA,QAAK,QAAQ,OAAO,KAAK,KAAK,MAAM,OAAO;AAAA,IAAA,OACnD;AACC,YAAA;AAAA,IACR;AAAA,EACF;AAEI,MAAA;AACF,WAAOC,YAAAA,cAAc,UAAU;AAAA,WACxB,KAAK;AACZ,UAAM,IAAI,MAAM,8BAA8B,UAAU,IAAI;AAAA,EAC9D;AACF;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const Router = require("@koa/router");
|
|
4
|
-
const
|
|
4
|
+
const fp = require("lodash/fp");
|
|
5
5
|
const strapiUtils = require("@strapi/utils");
|
|
6
6
|
const composeEndpoint = require("./compose-endpoint.js");
|
|
7
7
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
@@ -76,7 +76,7 @@ const createRouteManager = (strapi, opts = {}) => {
|
|
|
76
76
|
} else if (routes.routes) {
|
|
77
77
|
const subRouter = new Router__default.default({ prefix: routes.prefix });
|
|
78
78
|
routes.routes.forEach((route) => {
|
|
79
|
-
const hasPrefix =
|
|
79
|
+
const hasPrefix = fp.has("prefix", route.config);
|
|
80
80
|
createRoute(route, hasPrefix ? router : subRouter);
|
|
81
81
|
});
|
|
82
82
|
return router.use(subRouter.routes(), subRouter.allowedMethods());
|