UNPKG

@elsikora/nestjs-crud-automator

Version:

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

118 lines (114 loc) 6.69 kB
'use strict'; 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'); require('../../enum/decorator/api/dto-type.enum.js'); require('../../enum/decorator/api/function/type.enum.js'); 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'); var desribeType_enum = 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'); require('../../enum/decorator/api/route-type.enum.js'); var swagger = require('@nestjs/swagger'); var camelCaseString_utility = require('../camel-case-string.utility.js'); var buildDecorator_utility = require('./build-decorator.utility.js'); var isPropertyExposedForGuard_utility = require('./is-property-exposed-for-guard.utility.js'); /** * Generates dynamic DTOs for object-type properties based on property metadata. * Creates classes on the fly with appropriate decorators for each property and sets up * proper inheritance and naming conventions. * @param {M} method - The API route type (CREATE, DELETE, GET, etc.) * @param {TApiPropertyDescribeProperties} propertyMetadata - Metadata describing the property * @param {IApiEntity<E>} entity - The entity metadata * @param {D} dtoType - The type of DTO (REQUEST, RESPONSE, etc.) * @param {string} _propertyName - The name of the property * @param {Type<IAuthGuard>} [currentGuard] - Optional authentication guard * @returns {Record<string, Type<unknown>> | undefined} A record of generated DTO classes or undefined if generation not needed * @template E - The entity type * @template M - The API route type * @template D - The DTO type */ // eslint-disable-next-line @elsikora/typescript/no-unnecessary-type-parameters function DtoGenerateDynamic(method, propertyMetadata, entity, dtoType, _propertyName, currentGuard) { if (propertyMetadata.type !== desribeType_enum.EApiPropertyDescribeType.OBJECT) { return undefined; } const properties = propertyMetadata.properties?.[method]; if (properties?.[dtoType]?.isEnabled === false || (properties?.[dtoType]?.isResponse && properties?.[dtoType]?.isExpose === false)) { return undefined; } if (!isPropertyExposedForGuard_utility.DtoIsPropertyExposedForGuard(method, propertyMetadata, dtoType, currentGuard)) { return undefined; } const generatedDTOs = {}; if (propertyMetadata.type === desribeType_enum.EApiPropertyDescribeType.OBJECT && !Array.isArray(propertyMetadata.dataType) && "isDynamicallyGenerated" in propertyMetadata && propertyMetadata.isDynamicallyGenerated) { const dataForGeneration = []; for (const dynamicDtoName of Object.keys(propertyMetadata.dataType)) { if (propertyMetadata.dataType[dynamicDtoName]) { dataForGeneration.push({ data: propertyMetadata.dataType[dynamicDtoName], name: dynamicDtoName, }); } } for (const { data, name } of dataForGeneration) { const nestedDTOs = {}; const allNestedTypes = []; for (const propertyName of Object.keys(data)) { const propertyData = data[propertyName]; if (propertyData && propertyData.type === desribeType_enum.EApiPropertyDescribeType.OBJECT && !Array.isArray(propertyData.dataType) && "isDynamicallyGenerated" in propertyData && propertyData.isDynamicallyGenerated) { const nestedPropertyName = `${_propertyName}${camelCaseString_utility.CamelCaseString(name)}${camelCaseString_utility.CamelCaseString(propertyName)}`; const childNestedDTOs = DtoGenerateDynamic(method, propertyData, entity, dtoType, nestedPropertyName, currentGuard); if (childNestedDTOs && Object.keys(childNestedDTOs).length > 0) { nestedDTOs[propertyName] = childNestedDTOs; for (const dto of Object.values(childNestedDTOs)) { if (dto) { allNestedTypes.push(dto); } } } } } class GeneratedDTO { constructor() { for (const propertyName of Object.keys(data)) { Object.defineProperty(this, propertyName, { // eslint-disable-next-line @elsikora/typescript/naming-convention configurable: true, // eslint-disable-next-line @elsikora/typescript/naming-convention enumerable: true, value: undefined, // eslint-disable-next-line @elsikora/typescript/naming-convention writable: true, }); } } } for (const propertyName of Object.keys(data)) { if (data[propertyName]) { const propertyGeneratedDTOs = nestedDTOs[propertyName] ?? {}; const decorators = buildDecorator_utility.DtoBuildDecorator(method, data[propertyName], entity, dtoType, propertyName, currentGuard, propertyGeneratedDTOs); if (decorators) { for (const [, decorator] of decorators.entries()) { decorator(GeneratedDTO.prototype, propertyName); } } } } Object.defineProperty(GeneratedDTO, "name", { value: `${entity.name ?? "UnknownResource"}${camelCaseString_utility.CamelCaseString(method)}${camelCaseString_utility.CamelCaseString(dtoType)}${camelCaseString_utility.CamelCaseString(_propertyName)}${camelCaseString_utility.CamelCaseString(name)}DTO`, }); if (allNestedTypes.length > 0) { swagger.ApiExtraModels(...allNestedTypes)(GeneratedDTO); } generatedDTOs[name] = GeneratedDTO; } } return generatedDTOs; } exports.DtoGenerateDynamic = DtoGenerateDynamic; //# sourceMappingURL=generate-dynamic.utility.js.map