UNPKG

@elsikora/nestjs-crud-automator

Version:

A library for automating the creation of CRUD operations in NestJS.

490 lines (485 loc) 38.4 kB
'use strict'; var executor_class = require('../../class/api/subscriber/executor.class.js'); var controller_constant = require('../../constant/decorator/api/controller.constant.js'); var function_constant = require('../../constant/decorator/api/function.constant.js'); require('../../enum/decorator/api/action.enum.js'); require('../../enum/decorator/api/authentication-type.enum.js'); require('../../enum/decorator/api/controller/load-relations-strategy.enum.js'); require('../../enum/decorator/api/controller/request-transformer-type.enum.js'); var dtoType_enum = require('../../enum/decorator/api/dto-type.enum.js'); require('../../enum/decorator/api/function/type.enum.js'); var onType_enum = require('../../enum/decorator/api/on-type.enum.js'); require('../../enum/decorator/api/property/data-type.enum.js'); require('../../enum/decorator/api/property/date/identifier.enum.js'); require('../../enum/decorator/api/property/date/type.enum.js'); require('../../enum/decorator/api/property/desribe-type.enum.js'); require('../../enum/decorator/api/property/number-type.enum.js'); require('../../enum/decorator/api/property/string-type.enum.js'); var routeType_enum = require('../../enum/decorator/api/route-type.enum.js'); var common = require('@nestjs/common'); var swagger = require('@nestjs/swagger'); var applyDecorators_utility = require('../../utility/api/controller/apply-decorators.utility.js'); var applyMetadata_utility = require('../../utility/api/controller/apply-metadata.utility.js'); var transformFilter_utility = require('../../utility/api/controller/get-list/transform-filter.utility.js'); require('../../enum/filter-operation.enum.js'); require('typeorm/index'); var getPrimaryColumn_utility = require('../../utility/api/controller/get-primary-column.utility.js'); var handleRequestRelations_utility = require('../../utility/api/controller/handle-request-relations.utility.js'); var transformData_utility = require('../../utility/api/controller/transform-data.utility.js'); var validateRequest_utility = require('../../utility/api/controller/validate-request.utility.js'); var writeDtoSwagger_utility = require('../../utility/api/controller/write-dto-swagger.utility.js'); var writeMethod_utility = require('../../utility/api/controller/write-method.utility.js'); require('../../constant/interface/api/property/default-string-format.constant.js'); require('typeorm'); require('reflect-metadata'); require('lodash/cloneDeep'); var applyResult_utility = require('../../utility/authorization/decision/apply-result.utility.js'); var attachResource_utility = require('../../utility/authorization/decision/attach-resource.utility.js'); var resolveFromRequest_utility = require('../../utility/authorization/decision/resolve-from-request.utility.js'); var where_utility = require('../../utility/authorization/scope/merge/where.utility.js'); require('../../constant/utility/dto/constant.js'); var errorException_utility = require('../../utility/error-exception.utility.js'); require('../../external/tslib/tslib.es6.js'); var classTransformer = require('class-transformer'); require('class-validator'); require('lodash/random'); require('../../validator/is-regular-expression.validator.js'); require('node:crypto'); require('../../validator/must-match-one-of-schemas.validator.js'); var generate_utility = require('../../utility/dto/generate.utility.js'); require('../../enum/filter-order-direction.enum.js'); require('../../validator/all-or-none-of-listed-properties.validator.js'); var generateEntityInformation_utility = require('../../utility/generate-entity-information.utility.js'); class ApiControllerFactory { target; properties; get targetPrototype() { return this.target.prototype; } ENTITY; constructor(target, properties) { this.target = target; this.properties = properties; this.ENTITY = generateEntityInformation_utility.GenerateEntityInformation(properties.entity); if (!this.ENTITY.primaryKey) { throw errorException_utility.ErrorException(`Primary key for entity ${this.properties.entity.name ?? "UnknownResource"} not found`); } common.Controller(this.properties.path ?? (this.properties.entity.name ? this.properties.entity.name.toLowerCase() : "UnknownResource"))(this.target); swagger.ApiTags(this.properties.name ?? this.properties.entity.name ?? "UnknownResource")(this.target); Reflect.defineMetadata(controller_constant.CONTROLLER_API_DECORATOR_CONSTANT.ENTITY_METADATA_KEY, this.properties.entity, this.target); } createMethod(method) { if (!(method in this.properties.routes) || this.properties.routes[method]?.isEnabled !== false) { const routeConfig = this.properties.routes[method] ?? {}; const routeDecorators = routeConfig.decorators ?? []; const methodName = `${controller_constant.CONTROLLER_API_DECORATOR_CONSTANT.RESERVED_METHOD_PREFIX}${method}`; writeMethod_utility.ApiControllerWriteMethod(this, this.targetPrototype, method, this.properties, this.ENTITY); const targetMethod = this.targetPrototype[methodName]; applyMetadata_utility.ApiControllerApplyMetadata(this.target, this.targetPrototype, this.ENTITY, this.properties, method, methodName, routeConfig); if (this.properties.routes[method]?.shouldWriteToController !== false) { applyDecorators_utility.ApiControllerApplyDecorators(targetMethod, this.ENTITY, this.properties, method, methodName, routeConfig, routeDecorators); } writeDtoSwagger_utility.ApiControllerWriteDtoSwagger(this.target, this.ENTITY, this.properties, method, routeConfig, this.ENTITY); // Reflect.defineMetadata(PARAMTYPES_METADATA, [routeConfig.dto.request], this.target, methodNameOnController); // Reflect.defineMetadata(PATH_METADATA, `:${this.ENTITY.name}`, this.target, methodNameOnController); /* const dtoProperties: Record<string, unknown> = (Reflect.getMetadata(DECORATORS.API_MODEL_PROPERTIES, routeConfig.dto.request) || {}) as Record<string, unknown>; const dtoPropertiesArray: Array<unknown> = (Reflect.getMetadata(DECORATORS.API_MODEL_PROPERTIES_ARRAY, routeConfig.dto.request) || []) as Array<unknown>; Reflect.defineMetadata(DECORATORS.API_MODEL_PROPERTIES, dtoProperties, routeConfig.dto.request); Reflect.defineMetadata(DECORATORS.API_MODEL_PROPERTIES_ARRAY, dtoPropertiesArray, routeConfig.dto.request); */ } } init() { for (const method of Object.values(routeType_enum.EApiRouteType)) { this.createMethod(method); } } [routeType_enum.EApiRouteType.CREATE](method, methodName, properties, entityMetadata) { this.targetPrototype[methodName] = Object.defineProperty(async function (body, headers, ip, authenticationRequest) { const entityInstance = new properties.entity(); let authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); const beforeExecutionContext = { DATA: { authorizationDecision, entityMetadata, method, methodName, properties }, ENTITY: entityInstance, result: { authenticationRequest, body, headers, ip }, ROUTE_TYPE: routeType_enum.EApiRouteType.CREATE, }; const beforeResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.CREATE, onType_enum.EApiSubscriberOnType.BEFORE, beforeExecutionContext); if (beforeResult) { body = beforeResult.body; headers = beforeResult.headers; ip = beforeResult.ip; authenticationRequest = beforeResult.authenticationRequest; authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); } try { const primaryKey = getPrimaryColumn_utility.ApiControllerGetPrimaryColumn(body, entityMetadata); if (!primaryKey) { const errorExecutionContext = { DATA: beforeExecutionContext.DATA, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.CREATE, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.CREATE, onType_enum.EApiSubscriberOnType.BEFORE_ERROR, errorExecutionContext, new Error("Primary key not found in entity columns")); throw errorException_utility.ErrorException("Primary key not found in entity columns"); } transformData_utility.ApiControllerTransformData(properties.routes[method]?.request?.transformers, properties, { body }, { authenticationRequest, headers, ip }); await validateRequest_utility.ApiControllerValidateRequest(properties.routes[method]?.request?.validators, properties, body); await handleRequestRelations_utility.ApiControllerHandleRequestRelations(this, properties, properties.routes[method]?.request?.relations, body); const createResponse = await this.service.create(body); const dto = generate_utility.DtoGenerate(properties.entity, entityMetadata, method, dtoType_enum.EApiDtoType.RESPONSE, properties.routes[method]?.autoDto?.[dtoType_enum.EApiDtoType.RESPONSE], properties.routes[method]?.authentication?.guard); const requestProperties = { relations: properties.routes[method]?.response?.relations, where: where_utility.AuthorizationScopeMergeWhere({ [primaryKey.key]: createResponse[primaryKey.key] }, authorizationDecision?.scope?.where), }; const response = await this.service.get(requestProperties); authorizationDecision = attachResource_utility.AuthorizationDecisionAttachResource(authorizationDecision, response); transformData_utility.ApiControllerTransformData(properties.routes[method]?.response?.transformers, properties, { response }, { authenticationRequest, headers, ip }); const afterExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, body, headers, ip }, ENTITY: response, result: response, ROUTE_TYPE: routeType_enum.EApiRouteType.CREATE, }; const afterResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, response, routeType_enum.EApiRouteType.CREATE, onType_enum.EApiSubscriberOnType.AFTER, afterExecutionContext); const finalResponse = afterResult ?? response; authorizationDecision = attachResource_utility.AuthorizationDecisionAttachResource(authorizationDecision, finalResponse); const transformedResponse = await applyResult_utility.AuthorizationDecisionApplyResult(authorizationDecision, finalResponse); return classTransformer.plainToInstance(dto, transformedResponse, { /* eslint-disable-next-line @elsikora/typescript/naming-convention */ excludeExtraneousValues: true, strategy: "excludeAll", }); } catch (error) { const errorExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, body, headers, ip }, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.CREATE, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.CREATE, onType_enum.EApiSubscriberOnType.AFTER_ERROR, errorExecutionContext, error); throw error; } }, "name", { value: methodName }); } [routeType_enum.EApiRouteType.DELETE](method, methodName, properties, entityMetadata) { this.targetPrototype[methodName] = Object.defineProperty(async function (parameters, headers, ip, authenticationRequest) { const entityInstance = new properties.entity(); let authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); const beforeExecutionContext = { DATA: { authorizationDecision, entityMetadata, method, methodName, properties }, ENTITY: entityInstance, result: { authenticationRequest, headers, ip, parameters }, ROUTE_TYPE: routeType_enum.EApiRouteType.DELETE, }; const beforeResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.DELETE, onType_enum.EApiSubscriberOnType.BEFORE, beforeExecutionContext); if (beforeResult) { parameters = beforeResult.parameters; headers = beforeResult.headers; ip = beforeResult.ip; authenticationRequest = beforeResult.authenticationRequest; authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); } try { const primaryKey = getPrimaryColumn_utility.ApiControllerGetPrimaryColumn(parameters, entityMetadata); if (!primaryKey) { const errorExecutionContext = { DATA: beforeExecutionContext.DATA, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.DELETE, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.DELETE, onType_enum.EApiSubscriberOnType.BEFORE_ERROR, errorExecutionContext, new Error("Primary key not found in entity columns")); throw errorException_utility.ErrorException("Primary key not found in entity columns"); } transformData_utility.ApiControllerTransformData(properties.routes[method]?.request?.transformers, properties, { parameters }, { authenticationRequest, headers, ip }); await validateRequest_utility.ApiControllerValidateRequest(properties.routes[method]?.request?.validators, properties, parameters); await handleRequestRelations_utility.ApiControllerHandleRequestRelations(this, properties, properties.routes[method]?.request?.relations, parameters); const requestCriteria = { [primaryKey.key]: primaryKey.value, }; const scopedCriteria = where_utility.AuthorizationScopeMergeWhere(requestCriteria, authorizationDecision?.scope?.where); await this.service.delete(scopedCriteria ?? requestCriteria); const afterExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, headers, ip, parameters }, ENTITY: entityInstance, result: parameters, ROUTE_TYPE: routeType_enum.EApiRouteType.DELETE, }; await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.DELETE, onType_enum.EApiSubscriberOnType.AFTER, afterExecutionContext); } catch (error) { const errorExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, headers, ip, parameters }, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.DELETE, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.DELETE, onType_enum.EApiSubscriberOnType.AFTER_ERROR, errorExecutionContext, error); throw error; } }, "name", { value: methodName }); } [routeType_enum.EApiRouteType.GET](method, methodName, properties, entityMetadata) { this.targetPrototype[methodName] = Object.defineProperty(async function (parameters, headers, ip, authenticationRequest) { const entityInstance = new properties.entity(); let authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); const beforeExecutionContext = { DATA: { authorizationDecision, entityMetadata, method, methodName, properties }, ENTITY: entityInstance, result: { authenticationRequest, headers, ip, parameters }, ROUTE_TYPE: routeType_enum.EApiRouteType.GET, }; const beforeResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.GET, onType_enum.EApiSubscriberOnType.BEFORE, beforeExecutionContext); if (beforeResult) { parameters = beforeResult.parameters; headers = beforeResult.headers; ip = beforeResult.ip; authenticationRequest = beforeResult.authenticationRequest; authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); } try { const primaryKey = getPrimaryColumn_utility.ApiControllerGetPrimaryColumn(parameters, entityMetadata); if (!primaryKey) { const errorExecutionContext = { DATA: beforeExecutionContext.DATA, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.GET, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.GET, onType_enum.EApiSubscriberOnType.BEFORE_ERROR, errorExecutionContext, new Error("Primary key not found in entity columns")); throw errorException_utility.ErrorException("Primary key not found in entity columns"); } transformData_utility.ApiControllerTransformData(properties.routes[method]?.request?.transformers, properties, { parameters }, { authenticationRequest, headers, ip }); await validateRequest_utility.ApiControllerValidateRequest(properties.routes[method]?.request?.validators, properties, parameters); await handleRequestRelations_utility.ApiControllerHandleRequestRelations(this, properties, properties.routes[method]?.request?.relations, parameters); const requestProperties = { relations: properties.routes[method]?.response?.relations, where: { [primaryKey.key]: primaryKey.value }, }; requestProperties.where = where_utility.AuthorizationScopeMergeWhere(requestProperties.where, authorizationDecision?.scope?.where); const response = await this.service.get(requestProperties); authorizationDecision = attachResource_utility.AuthorizationDecisionAttachResource(authorizationDecision, response); transformData_utility.ApiControllerTransformData(properties.routes[method]?.response?.transformers, properties, { response }, { authenticationRequest, headers, ip }); const afterExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, headers, ip, parameters }, ENTITY: response, result: response, ROUTE_TYPE: routeType_enum.EApiRouteType.GET, }; const afterResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, response, routeType_enum.EApiRouteType.GET, onType_enum.EApiSubscriberOnType.AFTER, afterExecutionContext); const finalResponse = afterResult ?? response; authorizationDecision = attachResource_utility.AuthorizationDecisionAttachResource(authorizationDecision, finalResponse); const transformedResponse = await applyResult_utility.AuthorizationDecisionApplyResult(authorizationDecision, finalResponse); const dto = generate_utility.DtoGenerate(properties.entity, entityMetadata, method, dtoType_enum.EApiDtoType.RESPONSE, properties.routes[method]?.autoDto?.[dtoType_enum.EApiDtoType.RESPONSE], properties.routes[method]?.authentication?.guard); return classTransformer.plainToInstance(dto, transformedResponse, { /* eslint-disable-next-line @elsikora/typescript/naming-convention */ excludeExtraneousValues: true, }); } catch (error) { const errorExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, headers, ip, parameters }, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.GET, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.GET, onType_enum.EApiSubscriberOnType.AFTER_ERROR, errorExecutionContext, error); throw error; } }, "name", { value: methodName }); } [routeType_enum.EApiRouteType.GET_LIST](method, methodName, properties, entityMetadata) { this.targetPrototype[methodName] = Object.defineProperty(async function (query, headers, ip, authenticationRequest) { const entityInstance = new properties.entity(); let authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); const beforeExecutionContext = { DATA: { authorizationDecision, entityMetadata, method, methodName, properties }, ENTITY: entityInstance, result: { authenticationRequest, headers, ip, query }, ROUTE_TYPE: routeType_enum.EApiRouteType.GET_LIST, }; const beforeResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.GET_LIST, onType_enum.EApiSubscriberOnType.BEFORE, beforeExecutionContext); if (beforeResult) { query = beforeResult.query; headers = beforeResult.headers; ip = beforeResult.ip; authenticationRequest = beforeResult.authenticationRequest; authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); } try { transformData_utility.ApiControllerTransformData(properties.routes[method]?.request?.transformers, properties, { query }, { authenticationRequest, headers, ip }); await validateRequest_utility.ApiControllerValidateRequest(properties.routes[method]?.request?.validators, properties, query); await handleRequestRelations_utility.ApiControllerHandleRequestRelations(this, properties, properties.routes[method]?.request?.relations, query); const { limit, orderBy, orderDirection, page, ...getListQuery } = query; const filter = transformFilter_utility.ApiControllerGetListTransformFilter(getListQuery, entityMetadata); const scopedFilter = where_utility.AuthorizationScopeMergeWhere(filter, authorizationDecision?.scope?.where); const requestProperties = { relations: properties.routes[method]?.response?.relations, skip: query.limit * (query.page - 1), take: query.limit, where: scopedFilter ?? filter, }; if (orderBy) { requestProperties.order = { [orderBy]: orderDirection ?? function_constant.FUNCTION_API_DECORATOR_CONSTANT.DEFAULT_FILTER_ORDER_BY_DIRECTION }; } const response = await this.service.getList(requestProperties); transformData_utility.ApiControllerTransformData(properties.routes[method]?.request?.transformers, properties, { response }, { authenticationRequest, headers, ip }); const afterExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, headers, ip, query }, ENTITY: entityInstance, result: response, ROUTE_TYPE: routeType_enum.EApiRouteType.GET_LIST, }; const afterResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.GET_LIST, onType_enum.EApiSubscriberOnType.AFTER, afterExecutionContext); const finalResponse = afterResult ?? response; const transformedResponse = await applyResult_utility.AuthorizationDecisionApplyResult(authorizationDecision, finalResponse); const dto = generate_utility.DtoGenerate(properties.entity, entityMetadata, method, dtoType_enum.EApiDtoType.RESPONSE, properties.routes[method]?.autoDto?.[dtoType_enum.EApiDtoType.RESPONSE], properties.routes[method]?.authentication?.guard); return classTransformer.plainToInstance(dto, transformedResponse, { // eslint-disable-next-line @elsikora/typescript/naming-convention excludeExtraneousValues: true, }); } catch (error) { const errorExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, headers, ip, query }, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.GET_LIST, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.GET_LIST, onType_enum.EApiSubscriberOnType.AFTER_ERROR, errorExecutionContext, error); throw error; } }, "name", { value: methodName }); } [routeType_enum.EApiRouteType.PARTIAL_UPDATE](method, methodName, properties, entityMetadata) { this.targetPrototype[methodName] = Object.defineProperty(async function (parameters, body, headers, ip, authenticationRequest) { const entityInstance = new properties.entity(); let authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); const beforeExecutionContext = { DATA: { authorizationDecision, entityMetadata, method, methodName, properties }, ENTITY: entityInstance, result: { authenticationRequest, body, headers, ip, parameters }, ROUTE_TYPE: routeType_enum.EApiRouteType.PARTIAL_UPDATE, }; const beforeResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.PARTIAL_UPDATE, onType_enum.EApiSubscriberOnType.BEFORE, beforeExecutionContext); if (beforeResult) { parameters = beforeResult.parameters; body = beforeResult.body; headers = beforeResult.headers; ip = beforeResult.ip; authenticationRequest = beforeResult.authenticationRequest; authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); } try { const primaryKey = getPrimaryColumn_utility.ApiControllerGetPrimaryColumn(parameters, entityMetadata); if (!primaryKey) { const errorExecutionContext = { DATA: beforeExecutionContext.DATA, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.PARTIAL_UPDATE, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.PARTIAL_UPDATE, onType_enum.EApiSubscriberOnType.BEFORE_ERROR, errorExecutionContext, new Error("Primary key not found in entity columns")); throw errorException_utility.ErrorException("Primary key not found in entity columns"); } transformData_utility.ApiControllerTransformData(properties.routes[method]?.request?.transformers, properties, { body, parameters }, { authenticationRequest, headers, ip }); await validateRequest_utility.ApiControllerValidateRequest(properties.routes[method]?.request?.validators, properties, parameters); await handleRequestRelations_utility.ApiControllerHandleRequestRelations(this, properties, properties.routes[method]?.request?.relations, parameters); const requestCriteria = { [primaryKey.key]: primaryKey.value, }; const scopedCriteria = where_utility.AuthorizationScopeMergeWhere(requestCriteria, authorizationDecision?.scope?.where); const response = await this.service.update(scopedCriteria ?? requestCriteria, body); authorizationDecision = attachResource_utility.AuthorizationDecisionAttachResource(authorizationDecision, response); transformData_utility.ApiControllerTransformData(properties.routes[method]?.response?.transformers, properties, { response }, { authenticationRequest, headers, ip }); const afterExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, body, headers, ip, parameters }, ENTITY: response, result: response, ROUTE_TYPE: routeType_enum.EApiRouteType.PARTIAL_UPDATE, }; const afterResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, response, routeType_enum.EApiRouteType.PARTIAL_UPDATE, onType_enum.EApiSubscriberOnType.AFTER, afterExecutionContext); const finalResponse = afterResult ?? response; authorizationDecision = attachResource_utility.AuthorizationDecisionAttachResource(authorizationDecision, finalResponse); const transformedResponse = await applyResult_utility.AuthorizationDecisionApplyResult(authorizationDecision, finalResponse); const dto = generate_utility.DtoGenerate(properties.entity, entityMetadata, method, dtoType_enum.EApiDtoType.RESPONSE, properties.routes[method]?.autoDto?.[dtoType_enum.EApiDtoType.RESPONSE], properties.routes[method]?.authentication?.guard); return classTransformer.plainToInstance(dto, transformedResponse, { // eslint-disable-next-line @elsikora/typescript/naming-convention excludeExtraneousValues: true, }); } catch (error) { const errorExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, body, headers, ip, parameters }, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.PARTIAL_UPDATE, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.PARTIAL_UPDATE, onType_enum.EApiSubscriberOnType.AFTER_ERROR, errorExecutionContext, error); throw error; } }, "name", { value: methodName }); } [routeType_enum.EApiRouteType.UPDATE](method, methodName, properties, entityMetadata) { this.targetPrototype[methodName] = Object.defineProperty(async function (parameters, body, headers, ip, authenticationRequest) { const entityInstance = new properties.entity(); let authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); const beforeExecutionContext = { DATA: { authorizationDecision, entityMetadata, method, methodName, properties }, ENTITY: entityInstance, result: { authenticationRequest, body, headers, ip, parameters }, ROUTE_TYPE: routeType_enum.EApiRouteType.UPDATE, }; const beforeResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.UPDATE, onType_enum.EApiSubscriberOnType.BEFORE, beforeExecutionContext); if (beforeResult) { parameters = beforeResult.parameters; body = beforeResult.body; headers = beforeResult.headers; ip = beforeResult.ip; authenticationRequest = beforeResult.authenticationRequest; authorizationDecision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(authenticationRequest); } try { const primaryKey = getPrimaryColumn_utility.ApiControllerGetPrimaryColumn(parameters, entityMetadata); if (!primaryKey) { const errorExecutionContext = { DATA: beforeExecutionContext.DATA, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.UPDATE, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.UPDATE, onType_enum.EApiSubscriberOnType.BEFORE_ERROR, errorExecutionContext, new Error("Primary key not found in entity columns")); throw errorException_utility.ErrorException("Primary key not found in entity columns"); } transformData_utility.ApiControllerTransformData(properties.routes[method]?.request?.transformers, properties, { body, parameters }, { authenticationRequest, headers, ip }); await validateRequest_utility.ApiControllerValidateRequest(properties.routes[method]?.request?.validators, properties, parameters); await handleRequestRelations_utility.ApiControllerHandleRequestRelations(this, properties, properties.routes[method]?.request?.relations, parameters); const requestCriteria = { [primaryKey.key]: primaryKey.value, }; const scopedCriteria = where_utility.AuthorizationScopeMergeWhere(requestCriteria, authorizationDecision?.scope?.where); const response = await this.service.update(scopedCriteria ?? requestCriteria, body); authorizationDecision = attachResource_utility.AuthorizationDecisionAttachResource(authorizationDecision, response); transformData_utility.ApiControllerTransformData(properties.routes[method]?.response?.transformers, properties, { response }, { authenticationRequest, headers, ip }); const afterExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, body, headers, ip, parameters }, ENTITY: response, result: response, ROUTE_TYPE: routeType_enum.EApiRouteType.UPDATE, }; const afterResult = await executor_class.ApiSubscriberExecutor.executeRouteSubscribers(this.constructor, response, routeType_enum.EApiRouteType.UPDATE, onType_enum.EApiSubscriberOnType.AFTER, afterExecutionContext); const finalResponse = afterResult ?? response; authorizationDecision = attachResource_utility.AuthorizationDecisionAttachResource(authorizationDecision, finalResponse); const transformedResponse = await applyResult_utility.AuthorizationDecisionApplyResult(authorizationDecision, finalResponse); const dto = generate_utility.DtoGenerate(properties.entity, entityMetadata, method, dtoType_enum.EApiDtoType.RESPONSE, properties.routes[method]?.autoDto?.[dtoType_enum.EApiDtoType.RESPONSE], properties.routes[method]?.authentication?.guard); return classTransformer.plainToInstance(dto, transformedResponse, { // eslint-disable-next-line @elsikora/typescript/naming-convention excludeExtraneousValues: true, }); } catch (error) { const errorExecutionContext = { DATA: { ...beforeExecutionContext.DATA, authenticationRequest, authorizationDecision, body, headers, ip, parameters }, ENTITY: entityInstance, ROUTE_TYPE: routeType_enum.EApiRouteType.UPDATE, }; await executor_class.ApiSubscriberExecutor.executeRouteErrorSubscribers(this.constructor, entityInstance, routeType_enum.EApiRouteType.UPDATE, onType_enum.EApiSubscriberOnType.AFTER_ERROR, errorExecutionContext, error); throw error; } }, "name", { value: methodName }); } } exports.ApiControllerFactory = ApiControllerFactory; //# sourceMappingURL=controller.factory.js.map