UNPKG

@elsikora/nestjs-crud-automator

Version:

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

140 lines (137 loc) 7.83 kB
import '../../../enum/decorator/api/action.enum.js'; import '../../../enum/decorator/api/authentication-type.enum.js'; import '../../../enum/decorator/api/controller/get-list/query/filter/missing-behavior.enum.js'; import '../../../enum/decorator/api/controller/get-list/query/unlisted-fields.enum.js'; import '../../../enum/decorator/api/controller/relation-reference-shape.enum.js'; import '../../../enum/decorator/api/controller/request/target.enum.js'; import '../../../enum/decorator/api/controller/request/transformer-type.enum.js'; import '../../../enum/decorator/api/controller/response-target.enum.js'; import { EApiDtoType } from '../../../enum/decorator/api/dto-type.enum.js'; import '../../../enum/decorator/api/function/context-storage-kind.enum.js'; import '../../../enum/decorator/api/function/subscriber-transaction-expectation.enum.js'; import '../../../enum/decorator/api/function/transaction/event-status.enum.js'; import '../../../enum/decorator/api/function/transaction/failure-stage.enum.js'; import '../../../enum/decorator/api/function/transaction/mode.enum.js'; import '../../../enum/decorator/api/function/transaction/outcome.enum.js'; import '../../../enum/decorator/api/function/transaction/owner-kind.enum.js'; import '../../../enum/decorator/api/function/transaction/trace-type.enum.js'; import '../../../enum/decorator/api/function/type.enum.js'; import '../../../enum/decorator/api/on-type.enum.js'; import '../../../enum/decorator/api/property/data-type.enum.js'; import '../../../enum/decorator/api/property/date/identifier.enum.js'; import '../../../enum/decorator/api/property/date/type.enum.js'; import '../../../enum/decorator/api/property/desribe-type.enum.js'; import '../../../enum/decorator/api/property/number-type.enum.js'; import '../../../enum/decorator/api/property/string-type.enum.js'; import '../../../enum/decorator/api/route/subscriber-authorization-expectation.enum.js'; import '../../../enum/decorator/api/route/type.enum.js'; import { applyDecorators } from '@nestjs/common'; import { ROUTE_ARGS_METADATA, PARAMTYPES_METADATA } from '@nestjs/common/constants.js'; import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum.js'; import { ApiExtraModels, ApiBody } from '@nestjs/swagger'; import { ApiControllerGetDto } from '../controller/get/dto.utility.js'; import { ApiRouteBuildDiscriminatedDtoOpenApiSchema } from './discriminator/build-open-api-schema.utility.js'; import { ApiRouteIsDiscriminatedDtoProperties } from './discriminator/is-dto-properties.utility.js'; import '@nestjs/swagger/dist/constants.js'; import { ApiRouteCollectDtoWithRegisteredChildren } from './dto-collect-with-registered-children.utility.js'; import { GenerateEntityInformation } from '../../generate-entity-information.utility.js'; /** * Applies request DTO metadata used by Nest Swagger for custom routes. * @template E - Entity type represented by the route metadata. * @param {object} target - Controller prototype that owns the custom route. * @param {string | symbol} propertyKey - Custom route method name. * @param {IApiRouteMetadata<E>} metadata - Route metadata used to resolve generated DTOs. * @param {IApiRouteRuntimeProperties<E, undefined>} runtimeProperties - Runtime route config containing dto/autoDto. * @param {PropertyDescriptor} descriptor - Custom route method descriptor. * @returns {void} */ function ApiRouteApplyDtoMetadata(target, propertyKey, metadata, runtimeProperties, descriptor) { const bodyDto = resolveRequestDto(metadata, runtimeProperties, EApiDtoType.BODY); const parametersDtoConfig = resolveRequestDto(metadata, runtimeProperties, EApiDtoType.PARAMETERS); const queryDtoConfig = resolveRequestDto(metadata, runtimeProperties, EApiDtoType.QUERY); const parametersDto = ApiRouteIsDiscriminatedDtoProperties(parametersDtoConfig) ? undefined : parametersDtoConfig; const queryDto = ApiRouteIsDiscriminatedDtoProperties(queryDtoConfig) ? undefined : queryDtoConfig; const routeArgumentsMetadata = Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, propertyKey); const parameterTypes = [...(Reflect.getMetadata(PARAMTYPES_METADATA, target, propertyKey) ?? [])]; for (const { dto, parameterType } of [ { dto: ApiRouteIsDiscriminatedDtoProperties(bodyDto) ? Object : bodyDto, parameterType: RouteParamtypes.BODY }, { dto: parametersDto, parameterType: RouteParamtypes.PARAM }, { dto: queryDto, parameterType: RouteParamtypes.QUERY }, ]) { if (!dto) { continue; } const argumentIndex = resolveRouteArgumentIndex(routeArgumentsMetadata, parameterType); if (argumentIndex !== undefined) { parameterTypes[argumentIndex] = dto; } } if (parameterTypes.length > 0) { Reflect.defineMetadata(PARAMTYPES_METADATA, parameterTypes, target, propertyKey); } const requestDtos = []; for (const dto of [bodyDto, parametersDto, queryDto]) { if (ApiRouteIsDiscriminatedDtoProperties(dto)) { ApiRouteCollectDtoWithRegisteredChildren(requestDtos, dto.type); } else if (dto) { ApiRouteCollectDtoWithRegisteredChildren(requestDtos, dto); } } const swaggerDecorators = requestDtos.length > 0 ? [ApiExtraModels(...requestDtos)] : []; if (ApiRouteIsDiscriminatedDtoProperties(bodyDto)) { swaggerDecorators.push(ApiBody({ schema: ApiRouteBuildDiscriminatedDtoOpenApiSchema(bodyDto, "ApiRouteCustom body"), })); } if (swaggerDecorators.length > 0) { applyDecorators(...swaggerDecorators)(target, propertyKey, descriptor); } } /** * Resolves an explicitly configured request DTO or a generated DTO when the custom route has a CRUD route type. * @template E - Entity type represented by the route metadata. * @param {IApiRouteMetadata<E>} metadata - Route metadata used for entity and route type. * @param {IApiRouteRuntimeProperties<E, undefined>} runtimeProperties - Runtime route config containing dto/autoDto. * @param {Exclude<EApiDtoType, EApiDtoType.RESPONSE>} dtoType - Request DTO target. * @returns {TApiRouteRequestDto | undefined} Resolved request DTO. */ function resolveRequestDto(metadata, runtimeProperties, dtoType) { const configuredDto = runtimeProperties.dto?.[dtoType]; if (configuredDto) { return configuredDto; } if (!metadata.route.type || !runtimeProperties.autoDto?.[dtoType]) { return undefined; } const entity = GenerateEntityInformation(metadata.resource.entity); const controllerProperties = { entity: metadata.resource.entity}; const routeConfig = { ...runtimeProperties, security: metadata.security, }; return ApiControllerGetDto(controllerProperties, entity, metadata.route.type, dtoType, routeConfig); } /** * Resolves an argument index from Nest route argument metadata. * @param {Record<string, { data?: unknown; index?: number }> | undefined} routeArgumentsMetadata - Nest route arguments metadata. * @param {RouteParamtypes} parameterType - Nest parameter type to find. * @returns {number | undefined} Whole-object argument index for the requested parameter type. */ function resolveRouteArgumentIndex(routeArgumentsMetadata, parameterType) { if (!routeArgumentsMetadata) { return undefined; } for (const entry of Object.entries(routeArgumentsMetadata)) { const [key, value] = entry; const [type] = key.split(":"); const metadataParameterType = Number(type); if (metadataParameterType === parameterType && value.data === undefined) { return value.index; } } return undefined; } export { ApiRouteApplyDtoMetadata }; //# sourceMappingURL=apply-dto-metadata.utility.js.map