UNPKG

prisma-class-validator-generator

Version:

Prisma 2+ generator to emit typescript models of your database with class validator

281 lines 9.46 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateSwaggerImport = exports.getSwaggerImportsByType = exports.shouldImportSwagger = exports.generateEnumImports = exports.generateHelpersImports = exports.generateRelationImportsImport = exports.generatePrismaImport = exports.generateClassValidatorImport = exports.getDecoratorsImportsByType = exports.getSwaggerDecoratorByFieldType = exports.getDecoratorsByFieldType = exports.getTSDataTypeFromFieldType = exports.shouldImportHelpers = exports.shouldImportPrisma = exports.generateModelsIndexFile = void 0; exports.generateEnumsIndexFile = generateEnumsIndexFile; const path_1 = __importDefault(require("path")); const generateModelsIndexFile = (prismaClientDmmf, project, outputDir) => { const modelsBarrelExportSourceFile = project.createSourceFile(path_1.default.resolve(outputDir, 'models', 'index.ts'), undefined, { overwrite: true }); modelsBarrelExportSourceFile.addExportDeclarations(prismaClientDmmf.datamodel.models .map((model) => model.name) .sort() .map((modelName) => ({ moduleSpecifier: `./${modelName}.model`, namedExports: [modelName], }))); }; exports.generateModelsIndexFile = generateModelsIndexFile; const shouldImportPrisma = (fields) => { return fields.some((field) => ['Decimal', 'Json'].includes(field.type)); }; exports.shouldImportPrisma = shouldImportPrisma; const shouldImportHelpers = (fields) => { return fields.some((field) => ['enum'].includes(field.kind)); }; exports.shouldImportHelpers = shouldImportHelpers; const getTSDataTypeFromFieldType = (field) => { let type = field.type; switch (field.type) { case 'Int': case 'Float': type = 'number'; break; case 'DateTime': type = 'Date'; break; case 'String': type = 'string'; break; case 'Boolean': type = 'boolean'; break; case 'Decimal': type = 'Prisma.Decimal'; break; case 'Json': type = 'Prisma.JsonValue'; break; case 'Bytes': type = 'Uint8Array'; break; } if (field.isList) { type = `${type}[]`; } // Add null union for optional fields to match Prisma client behavior if (!field.isRequired) { type = `${type} | null`; } return type; }; exports.getTSDataTypeFromFieldType = getTSDataTypeFromFieldType; const getDecoratorsByFieldType = (field, includeSwagger = false) => { const decorators = []; // Add Swagger decorators first if enabled if (includeSwagger) { const swaggerDecorator = (0, exports.getSwaggerDecoratorByFieldType)(field); if (swaggerDecorator) { decorators.push(swaggerDecorator); } } // Add class-validator decorators switch (field.type) { case 'Int': decorators.push({ name: 'IsInt', arguments: [], }); break; case 'Float': decorators.push({ name: 'IsNumber', arguments: [], }); break; case 'DateTime': decorators.push({ name: 'IsDate', arguments: [], }); break; case 'String': decorators.push({ name: 'IsString', arguments: field.isList ? [`{ each:true }`] : [], }); break; case 'Boolean': decorators.push({ name: 'IsBoolean', arguments: [], }); break; } if (field.isRequired) { decorators.unshift({ name: 'IsDefined', arguments: [], }); } else { decorators.unshift({ name: 'IsOptional', arguments: [], }); } if (field.kind === 'enum') { decorators.push({ name: 'IsIn', arguments: [`getEnumValues(${String(field.type)})`], }); } return decorators; }; exports.getDecoratorsByFieldType = getDecoratorsByFieldType; const getSwaggerDecoratorByFieldType = (field) => { const args = []; // Base properties if (field.hasDefaultValue && field.default !== null) { if (typeof field.default === 'object' && 'name' in field.default) { // Handle function defaults like autoincrement(), now() args.push(`example: 'Generated by ${field.default.name}'`); } else { args.push(`example: ${JSON.stringify(field.default)}`); } } // Type-specific properties switch (field.type) { case 'Int': args.push('type: "integer"'); break; case 'Float': args.push('type: "number"'); break; case 'String': args.push('type: "string"'); break; case 'Boolean': args.push('type: "boolean"'); break; case 'DateTime': args.push('type: "string"', 'format: "date-time"'); break; case 'Decimal': args.push('type: "string"', 'description: "Decimal value as string"'); break; case 'Json': args.push('type: Object'); break; case 'Bytes': args.push('type: "string"', 'format: "byte"'); break; } // Array handling if (field.isList) { args.push('isArray: true'); } // Required/optional if (!field.isRequired) { args.push('required: false'); } // Enum handling if (field.kind === 'enum') { args.push(`enum: Object.values(${field.type})`); } if (field.relationName) { args.push(`type: () => ${field.type}`); } return { name: 'ApiProperty', arguments: args.length > 0 ? [`{ ${args.join(', ')} }`] : [], }; }; exports.getSwaggerDecoratorByFieldType = getSwaggerDecoratorByFieldType; const getDecoratorsImportsByType = (field) => { const validatorImports = new Set(); switch (field.type) { case 'Int': validatorImports.add('IsInt'); break; case 'Float': validatorImports.add('IsNumber'); break; case 'DateTime': validatorImports.add('IsDate'); break; case 'String': validatorImports.add('IsString'); break; case 'Boolean': validatorImports.add('IsBoolean'); break; } if (field.isRequired) { validatorImports.add('IsDefined'); } else { validatorImports.add('IsOptional'); } if (field.kind === 'enum') { validatorImports.add('IsIn'); } return [...validatorImports]; }; exports.getDecoratorsImportsByType = getDecoratorsImportsByType; const generateClassValidatorImport = (sourceFile, validatorImports) => { sourceFile.addImportDeclaration({ moduleSpecifier: 'class-validator', namedImports: validatorImports, }); }; exports.generateClassValidatorImport = generateClassValidatorImport; const generatePrismaImport = (sourceFile) => { sourceFile.addImportDeclaration({ moduleSpecifier: '@prisma/client', namedImports: ['Prisma'], }); }; exports.generatePrismaImport = generatePrismaImport; const generateRelationImportsImport = (sourceFile, relationImports) => { sourceFile.addImportDeclaration({ moduleSpecifier: './', namedImports: relationImports, }); }; exports.generateRelationImportsImport = generateRelationImportsImport; const generateHelpersImports = (sourceFile, helpersImports) => { sourceFile.addImportDeclaration({ moduleSpecifier: '../helpers', namedImports: helpersImports, }); }; exports.generateHelpersImports = generateHelpersImports; const generateEnumImports = (sourceFile, fields) => { const enumsToImport = fields .filter((field) => field.kind === 'enum') .map((field) => field.type); if (enumsToImport.length > 0) { sourceFile.addImportDeclaration({ moduleSpecifier: '../enums', namedImports: enumsToImport, }); } }; exports.generateEnumImports = generateEnumImports; const shouldImportSwagger = (fields) => { return fields.length > 0; // Always import if we have fields and swagger is enabled }; exports.shouldImportSwagger = shouldImportSwagger; const getSwaggerImportsByType = (fields) => { const swaggerImports = new Set(['ApiProperty']); // Add more swagger imports as needed return [...swaggerImports]; }; exports.getSwaggerImportsByType = getSwaggerImportsByType; const generateSwaggerImport = (sourceFile, swaggerImports) => { sourceFile.addImportDeclaration({ moduleSpecifier: '@nestjs/swagger', namedImports: swaggerImports, }); }; exports.generateSwaggerImport = generateSwaggerImport; function generateEnumsIndexFile(sourceFile, enumNames) { sourceFile.addExportDeclarations(enumNames.sort().map((name) => ({ moduleSpecifier: `./${name}.enum`, namedExports: [name], }))); } //# sourceMappingURL=helpers.js.map