prisma-class-validator-generator
Version:
Prisma 2+ generator to emit typescript models of your database with class validator
281 lines • 9.46 kB
JavaScript
;
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