@weverson_na/prisma-generator-nestjs-dto
Version:
Advanced Prisma Generator with Smart Merge v2: Creates DTO and Entity classes with AST-based preservation, intelligent import management, and modular architecture for NestJS
220 lines (219 loc) • 9.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DecoratorStrategy = void 0;
const fs_1 = require("fs");
const annotations_1 = require("./annotations");
class DecoratorStrategy {
constructor(customDecoratorConfigsPath) {
var _a;
this.omitDecorators = [
...annotations_1.DTO_RELATION_MODIFIERS,
...annotations_1.DTO_RELATION_MODIFIERS_ON_CREATE,
...annotations_1.DTO_RELATION_MODIFIERS_ON_UPDATE,
];
this.decoratorCategories = [
{
importPath: '@nestjs/swagger',
names: [/ApiProperty/, /ApiExtraModels/],
},
{
importPath: 'class-transformer',
names: [/Exclude/, /Expose/, /Transform/, /Type/],
},
{
importPath: 'class-validator',
names: [
/Allow/,
/IsDefined/,
/IsOptional/,
/Validate/,
/ValidateBy/,
/ValidateIf/,
/ValidateNested/,
/ValidatePromise/,
/IsLatLong/,
/IsLatitude/,
/IsLongitude/,
/Equals/,
/NotEquals/,
/IsEmpty/,
/IsNotEmpty/,
/IsIn/,
/IsNotIn/,
/IsDivisibleBy/,
/IsPositive/,
/IsNegative/,
/Max/,
/Min/,
/MinDate/,
/MaxDate/,
/Contains/,
/NotContains/,
/IsAlpha/,
/IsAlphanumeric/,
/IsDecimal/,
/IsAscii/,
/IsBase64/,
/IsByteLength/,
/IsCreditCard/,
/IsCurrency/,
/IsEmail/,
/IsFQDN/,
/IsFullWidth/,
/IsHalfWidth/,
/IsVariableWidth/,
/IsHexColor/,
/IsHexadecimal/,
/IsMacAddress/,
/IsIP/,
/IsPort/,
/IsISBN/,
/IsISIN/,
/IsISO8601/,
/IsJSON/,
/IsJWT/,
/IsLowercase/,
/IsMobilePhone/,
/IsISO31661Alpha2/,
/IsISO31661Alpha3/,
/IsMongoId/,
/IsMultibyte/,
/IsSurrogatePair/,
/IsUrl/,
/IsUUID/,
/IsFirebasePushId/,
/IsUppercase/,
/Length/,
/MaxLength/,
/MinLength/,
/Matches/,
/IsPhoneNumber/,
/IsMilitaryTime/,
/IsHash/,
/IsISSN/,
/IsDateString/,
/IsBooleanString/,
/IsNumberString/,
/IsBase32/,
/IsBIC/,
/IsBtcAddress/,
/IsDataURI/,
/IsEAN/,
/IsEthereumAddress/,
/IsHSL/,
/IsIBAN/,
/IsIdentityCard/,
/IsISRC/,
/IsLocale/,
/IsMagnetURI/,
/IsMimeType/,
/IsOctal/,
/IsPassportNumber/,
/IsPostalCode/,
/IsRFC3339/,
/IsRgbColor/,
/IsSemVer/,
/IsStrongPassword/,
/IsTimeZone/,
/IsBase58/,
/is-tax-id/,
/is-iso4217-currency-code/,
/IsBoolean/,
/IsDate/,
/IsNumber/,
/IsEnum/,
/IsInt/,
/IsString/,
/IsArray/,
/IsObject/,
/ArrayContains/,
/ArrayNotContains/,
/ArrayNotEmpty/,
/ArrayMinSize/,
/ArrayMaxSize/,
/ArrayUnique/,
/IsNotEmptyObject/,
/IsInstance/,
],
},
];
console.log(`[DecoratorStrategy] Constructor called with path: ${customDecoratorConfigsPath}`);
if (!customDecoratorConfigsPath) {
console.log('[DecoratorStrategy] WARNING: No config path provided! Stack trace:');
console.log((_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.split('\n').slice(1, 5).join('\n'));
}
let combinedCategories = this.decoratorCategories;
let customConfigs = [];
if (customDecoratorConfigsPath) {
console.log(`Using custom decorator configs from ${customDecoratorConfigsPath}`);
try {
const customDecoratorConfigs = (0, fs_1.readFileSync)(customDecoratorConfigsPath, 'utf8');
customConfigs = JSON.parse(customDecoratorConfigs);
console.log(`Custom decorator configs loaded: ${JSON.stringify(customConfigs)}`);
}
catch (err) {
console.error('Error loading custom decorator configs:', err);
throw new Error('Invalid JSON for customDecoratorConfigs');
}
}
if (customConfigs.length) {
console.log(`Found ${customConfigs.length} custom decorator configs: ${JSON.stringify(customConfigs)}`);
const processedCustomConfigs = customConfigs.map((category) => ({
...category,
names: category.names.map((name) => typeof name === 'string' ? new RegExp(name) : name),
}));
console.log(`Processed custom decorator configs: ${JSON.stringify(processedCustomConfigs.map((category) => ({
...category,
names: category.names.map((name) => name instanceof RegExp ? name.toString() : name),
})), null, 2)}`);
combinedCategories = [...combinedCategories, ...processedCustomConfigs];
}
console.log('[DecoratorStrategy] Final combined categories:', combinedCategories.map(cat => ({
importPath: cat.importPath,
nameCount: cat.names.length
})));
this.decoratorImportMap = combinedCategories.flatMap(({ importPath, names }) => names.map((name) => ({ name, importPath })));
console.log('[DecoratorStrategy] Import map created with', this.decoratorImportMap.length, 'entries');
}
getValidDecorators(doc) {
const decorators = this.decoratorsStringToArray(doc);
return decorators.filter((decorator) => this.verifyIfDecoratorIsValid(decorator) &&
!this.omitDecorators.find((omitDecorator) => omitDecorator.test(decorator)));
}
decoratorsStringToArray(doc) {
const decorators = doc
.split('\n')
.map((line) => line.trim())
.filter((line) => line.startsWith('@'));
return decorators;
}
verifyIfDecoratorIsValid(decoratorName) {
return this.decoratorImportMap.some(({ name }) => name.test(decoratorName));
}
getValidDecoratorAndImportsByDoc(doc) {
if (!doc)
return [];
const decorators = this.decoratorsStringToArray(doc);
console.log(`Found decorators in doc: ${decorators.join(', ')}`);
return decorators
.map((decorator) => this.getValidDecoratorAndImports(decorator))
.filter((result) => !!result);
}
formatValidDecoratorResultToFromDestruct(validDecoratorResult) {
return Array.from(validDecoratorResult.reduce((map, { importPath, decoratorName }) => { var _a; return map.set(importPath, [...((_a = map.get(importPath)) !== null && _a !== void 0 ? _a : []), decoratorName]); }, new Map())).map(([from, destruct]) => ({ from, destruct }));
}
getValidDecoratorAndImports(decoratorName) {
const hasCustomDecorators = this.decoratorImportMap.some(({ importPath }) => importPath === '@angular/core');
if (!hasCustomDecorators) {
console.log(`[DecoratorStrategy] WARNING: No @angular/core decorators in import map for decorator: ${decoratorName}`);
}
console.log('Checking decorator imports:', this.decoratorImportMap.filter(({ importPath }) => importPath !== 'class-validator'));
const match = this.decoratorImportMap.find(({ name }) => name.test(decoratorName));
if (!match) {
console.log(`[DecoratorStrategy] No match found for decorator: ${decoratorName}`);
return undefined;
}
return { importPath: match.importPath, decoratorName: match.name.source };
}
}
exports.DecoratorStrategy = DecoratorStrategy;