@elsikora/nestjs-crud-automator
Version:
A library for automating the creation of CRUD operations in NestJS.
139 lines (135 loc) • 8.17 kB
JavaScript
;
require('../../../enum/decorator/api/action.enum.js');
require('../../../enum/decorator/api/authentication-type.enum.js');
require('../../../enum/decorator/api/controller/get-list/query/filter/missing-behavior.enum.js');
require('../../../enum/decorator/api/controller/get-list/query/unlisted-fields.enum.js');
require('../../../enum/decorator/api/controller/relation-reference-shape.enum.js');
require('../../../enum/decorator/api/controller/request/target.enum.js');
require('../../../enum/decorator/api/controller/request/transformer-type.enum.js');
require('../../../enum/decorator/api/controller/response-target.enum.js');
require('../../../enum/decorator/api/dto-type.enum.js');
require('../../../enum/decorator/api/function/context-storage-kind.enum.js');
require('../../../enum/decorator/api/function/subscriber-transaction-expectation.enum.js');
require('../../../enum/decorator/api/function/transaction/event-status.enum.js');
require('../../../enum/decorator/api/function/transaction/failure-stage.enum.js');
require('../../../enum/decorator/api/function/transaction/mode.enum.js');
require('../../../enum/decorator/api/function/transaction/outcome.enum.js');
require('../../../enum/decorator/api/function/transaction/owner-kind.enum.js');
require('../../../enum/decorator/api/function/transaction/trace-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/subscriber-authorization-expectation.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 pop_utility = require('../auto/context/pop.utility.js');
var push_utility = require('../auto/context/push.utility.js');
var buildDecorator_utility = require('../build-decorator.utility.js');
var exposedForGuard_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 (!exposedForGuard_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?.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,
});
}
}
}
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`,
});
push_utility.DtoAutoContextPush(GeneratedDTO.prototype, method, dtoType);
try {
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);
}
}
}
}
if (allNestedTypes.length > 0) {
swagger.ApiExtraModels(...allNestedTypes)(GeneratedDTO);
}
generatedDTOs[name] = GeneratedDTO;
}
finally {
pop_utility.DtoAutoContextPop(GeneratedDTO.prototype);
}
}
}
return generatedDTOs;
}
exports.DtoGenerateDynamic = DtoGenerateDynamic;
//# sourceMappingURL=dynamic.utility.js.map