@arianaprojects/prisma-nestjs-crud-generator
Version:
code generator from Prisma schema
192 lines (170 loc) • 7.31 kB
text/typescript
import { DMMF } from '@prisma/generator-helper/dist/dmmf';
import { classGenerator, importGenerator } from '../templates';
import { defaultGenerator, tsTypes } from '../util';
import Model from './Model';
export default class Types {
parent: Model;
entity: string;
dto: string;
constructor(parent: Model) {
this.parent = parent;
this.generateDTO();
this.generateEntity();
}
public get entityDTO(): string {
return this.dto;
}
public get entityGetter(): string {
return this.entity;
}
private generateDTO() {
let res: string[] = [];
res.push(this.dtoImport());
res.push(this.classGenerator(`Create${this.parent.namePascal}Dto`, this.parent.createFields, true, false, true, false));
res.push(this.classGenerator(`Update${this.parent.namePascal}Dto`, this.parent.updateFields, true, false, true, true));
res.push(this.classGenerator(`Find${this.parent.namePascal}Dto`, this.parent.findFields, true, false, true, true));
res.push(this.classGenerator(`Connect${this.parent.namePascal}Dto`, this.parent.connectFields, true, false, true, false));
res.push(this.classGenerator(`Access${this.parent.namePascal}Dto`, this.parent.accessField, false, false, false, false));
res.push(this.classGenerator(`Deleted${this.parent.namePascal}Dto`, this.parent.deletedField, false, false, false, false));
res.push(this.classGenerator(`Pseudonymisation${this.parent.namePascal}Dto`, this.parent.updateFieldsAdmin, false, false, false, true));
res.push(this.classGenerator(`Create${this.parent.namePascal}AdminDto`, this.parent.createFieldsAdmin, true, false, true, false));
res.push(this.classGenerator(`Update${this.parent.namePascal}AdminDto`, this.parent.updateFieldsAdmin, true, false, true, true));
res.push(this.classGenerator(`Find${this.parent.namePascal}AdminDto`, this.parent.findFieldsAdmin, true, false, true, true));
res.push(this.classGenerator(`Connect${this.parent.namePascal}AdminDto`, this.parent.connectFieldsAdmin, true, false, true, false));
this.dto = res.join('\n\n');
}
private generateEntity() {
let res: string[] = [];
res.push(this.entityImport());
res.push(this.classGenerator(this.parent.namePascal, this.parent.entityFields, true, true, true, false, true));
this.entity = res.join('\n');
}
private dtoImport(): string {
let res: string[] = [
`import { Exclude, Expose, Type } from 'class-transformer';`,
`import {
IsArray,
IsBoolean,
IsDate,
IsDecimal,
IsEnum,
IsNotEmpty,
IsNumber,
IsObject,
IsOptional,
IsJSON,IsInt,
ValidateNested,IsString
} from 'class-validator';`,
"import { Decimal } from '@prisma/client/runtime';",
"import { ApiProperty } from '@nestjs/swagger';",
`import { Prisma, ${this.parent.enumFields
.map((f) => {
return f.type;
})
.join(',')} } from '@prisma/client';`,
];
return res.join('\n');
}
private entityImport() {
let res: string[] = [
`import { Exclude, Expose, Type } from 'class-transformer';`,
`import {
IsArray,
IsBoolean,
IsDate,
IsDecimal,
IsEnum,
IsNotEmpty,
IsNumber,
IsObject,
IsOptional,
IsJSON,IsInt,
ValidateNested,IsString
} from 'class-validator';`,
"import { ApiProperty } from '@nestjs/swagger';",
"import { Decimal } from '@prisma/client/runtime';",
];
const importPrisma =
'{Prisma,' +
this.parent.enumFields
.map((f) => {
return f.type;
})
.join(',') +
'}';
res.push(importGenerator(importPrisma, '"@prisma/client"'));
this.parent.objectFields.map((f) => {
res.push(importGenerator('{' + this.parent.toPascalCase(tsTypes(f.type)) + '}', `"../${this.parent.toCamelCase(tsTypes(f.type))}/${this.parent.toCamelCase(tsTypes(f.type))}.entity"`));
});
return res.join('\n');
}
private classGenerator(name: string, fields: DMMF.Field[], classValidator: boolean = true, classTransformer: boolean = true, apiProperty: boolean = true, isOptional: boolean = true, entity: boolean = false) {
const body = fields.map((f) => this.fieldDecoratorGenerator(f, classValidator, classTransformer, apiProperty, isOptional, entity)).join('\n\n');
return classGenerator(name, body);
}
private fieldDecoratorGenerator(f: DMMF.Field, classValidator: boolean = true, classTransformer: boolean = true, apiProperty: boolean = true, isOptional: boolean, entity: boolean = false) {
let res: string[] = [];
if (classTransformer) res.push(this.classTransformerDecorator(f, entity));
if (apiProperty) res.push(this.apiPropertyDecorator(f, isOptional, entity));
if (classValidator) res.push(this.classValidatorDecorator(f, isOptional, entity));
res.push(this.fieldGenerator(f, isOptional, entity));
return res.join('\n');
}
private fieldGenerator(f: DMMF.Field, isOptional, entity: boolean = false) {
let res: string[] = [];
res.push();
res.push(f.name);
if (isOptional || !f.isRequired || f.kind == 'object') res.push('?');
res.push(':');
res.push(tsTypes(f.type, entity));
if (f.isList) res.push('[]');
return res.join(' ');
}
private classTransformerDecorator(f: DMMF.Field, entity: boolean = false) {
let res: string[] = [];
if (this.parent.isExcludeList(f.name)) res.push('@Exclude()');
return res.join('\n');
}
private apiPropertyDecorator(f: DMMF.Field, isOptional, entity: boolean = false) {
let res: string[] = [];
if (this.parent.isInBlackList(f.name)) return '';
res.push('@ApiProperty({');
// Array
if (f.isList) res.push('isArray: true,');
// type
if (f.kind == 'object') res.push(`type: ()=>${f.type},`);
else if (f.kind == 'enum') res.push(`enum: ${f.type},`);
else if (f.kind == 'unsupported') res.push(`// TODO`);
if (f.type == 'Decimal' || f.type == 'Float') res.push('type: ()=>Decimal,');
// not required
if (isOptional || !f.isRequired) res.push(`required:false,`);
// default
const d = defaultGenerator(f.name, tsTypes(f.type, entity));
if (!!d) res.push(`default:${d}`);
res.push('})');
return res.join('\n');
}
private classValidatorDecorator(f: DMMF.Field, isOptional: boolean, entity: boolean = false) {
// console.log(f);
let res: string[] = [];
// array
if (f.isList) res.push('@IsArray()');
// required
if (!isOptional && f.isRequired && f.kind != 'object') res.push('@IsNotEmpty()');
else res.push('@IsOptional()');
// kind
if (f.kind == 'enum') res.push(``);
else if (f.kind == 'object') res.push('@ValidateNested()');
//types
if (f.type == 'Int' || f.type == 'BigInt') {
res.push('@IsInt()');
if (f.isId) res.push('@Type(() => Number)');
} else if (f.type == 'String' || f.type == 'Text') res.push('@IsString()');
else if (f.type == 'DateTime') res.push('@IsDate()');
else if (f.type == 'Boolean') res.push('@IsBoolean()');
else if (f.type == 'Decimal' || f.type == 'Float') res.push('@IsDecimal()');
else if (f.type == 'Json') res.push('@IsJSON()');
else res.push('@IsObject()');
return res.join('\n');
}
}