@elsikora/nestjs-crud-automator
Version:
A library for automating the creation of CRUD operations in NestJS.
89 lines (85 loc) • 4.08 kB
JavaScript
;
var contextualManual_constant = require('../../../constant/dto/contextual-manual.constant.js');
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 get_utility = require('../manual/property-metadata/get.utility.js');
const contextualManualDtoCache = new WeakMap();
/**
* Generates a path-aware DTO wrapper for a nested manual DTO inside an auto-generated CRUD DTO.
* The wrapper replays all original `ApiProperty*` decorators so Swagger, validation, and
* class-transformer semantics remain intact while the schema name becomes context-specific.
* @param {Type<unknown>} sourceDto - Source manual DTO class.
* @param {EApiRouteType} method - Current auto DTO route method.
* @param {EApiDtoType} dtoType - Current auto DTO type.
* @param {string} parentDtoName - Parent generated DTO class name.
* @param {string} propertyPathSegment - Current nested path segment to append.
* @returns {Type<unknown>} Context-specific wrapper or the original class when replay metadata is unavailable.
*/
function DtoGenerateContextualManualDto(sourceDto, method, dtoType, parentDtoName, propertyPathSegment) {
if (sourceDto === Object || IsContextualManualDto(sourceDto)) {
return sourceDto;
}
const sourcePrototype = sourceDto.prototype;
const propertyMetadata = get_utility.GetManualDtoPropertyMetadata(sourcePrototype);
if (propertyMetadata.size === 0) {
return sourceDto;
}
// eslint-disable-next-line @elsikora/typescript/no-magic-numbers
const parentDtoNameBase = parentDtoName.endsWith("DTO") ? parentDtoName.slice(0, -3) : parentDtoName;
const className = `${parentDtoNameBase}${camelCaseString_utility.CamelCaseString(propertyPathSegment)}DTO`;
const cached = contextualManualDtoCache.get(sourceDto)?.get(className);
if (cached) {
return cached;
}
class GeneratedDTO {
constructor() {
for (const propertyKey of propertyMetadata.keys()) {
Object.defineProperty(this, propertyKey, {
// 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: className,
});
Reflect.defineMetadata?.(contextualManual_constant.CONTEXTUAL_MANUAL_DTO_CONSTANT.METADATA_KEY, {
dtoType,
method,
source: sourceDto,
}, GeneratedDTO);
let dtoCache = contextualManualDtoCache.get(sourceDto);
if (!dtoCache) {
dtoCache = new Map();
contextualManualDtoCache.set(sourceDto, dtoCache);
}
dtoCache.set(className, GeneratedDTO);
push_utility.DtoAutoContextPush(GeneratedDTO.prototype, method, dtoType);
try {
for (const [propertyKey, metadata] of propertyMetadata.entries()) {
metadata.apply(GeneratedDTO.prototype, propertyKey);
}
}
finally {
pop_utility.DtoAutoContextPop(GeneratedDTO.prototype);
}
return GeneratedDTO;
}
/**
* Returns whether a class was materialized as a context-specific wrapper around a manual DTO.
* @param {unknown} value - Constructor candidate.
* @returns {boolean} Whether the candidate is a generated contextual manual DTO.
*/
function IsContextualManualDto(value) {
return typeof value === "function" && Boolean(Reflect.getMetadata?.(contextualManual_constant.CONTEXTUAL_MANUAL_DTO_CONSTANT.METADATA_KEY, value));
}
exports.DtoGenerateContextualManualDto = DtoGenerateContextualManualDto;
exports.IsContextualManualDto = IsContextualManualDto;
//# sourceMappingURL=manual-child.utility.js.map