diff --git a/package.json b/package.json index 6c32638..2ddb679 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "prisma-class-generator", - "version": "0.2.9", + "name": "prisma-class-generator-custom", + "version": "1.2.5", "description": "Class generator from Prisma schema", "main": "dist/index.js", "license": "MIT", @@ -10,10 +10,10 @@ "typescript", "generator" ], - "homepage": "https://github.com/kimjbstar/prisma-class-generator", + "homepage": "https://github.com/ABHwan/prisma-class-generator", "repository": { "type": "git", - "url": "git://github.com/kimjbstar/prisma-class-generator.git" + "url": "git://github.com/ABHwan/prisma-class-generator.git" }, "scripts": { "format": "prettier --write \"src/**/*.ts\"", @@ -29,8 +29,8 @@ "node": ">=14" }, "author": { - "name": "kimjbstar", - "email": "kimjbstar@gmail.com" + "name": "ABHwan", + "email": "say5131@gmail.com" }, "dependencies": { "@prisma/client": "^5.5.2", diff --git a/prisma/postgresql.prisma b/prisma/postgresql.prisma index 9560e8b..a420e80 100755 --- a/prisma/postgresql.prisma +++ b/prisma/postgresql.prisma @@ -13,6 +13,8 @@ generator prismaClassGenerator { output = "../src/_gen/prisma-class" dryRun = "false" separateRelationFields = "false" + useValidator = "false" + rewrite = "false" } enum ProductType { diff --git a/src/components/field.component.ts b/src/components/field.component.ts index 9c78f2d..3d3e392 100755 --- a/src/components/field.component.ts +++ b/src/components/field.component.ts @@ -26,7 +26,7 @@ export class FieldComponent extends BaseComponent implements Echoable { let defaultValue = '' if (this.default) { - if (!isNaN(Date.parse(this.default))) { + if (this.type === 'Date' && !isNaN(Date.parse(this.default))) { defaultValue = `= new Date('${this.default}')` } else { defaultValue = `= ${this.default}` diff --git a/src/convertor.ts b/src/convertor.ts index c08d547..8d86395 100755 --- a/src/convertor.ts +++ b/src/convertor.ts @@ -3,13 +3,7 @@ import { ClassComponent } from './components/class.component' import { DecoratorComponent } from './components/decorator.component' import { FieldComponent } from './components/field.component' import { PrismaClassGeneratorConfig } from './generator' -import { - arrayify, - capitalizeFirst, - uniquify, - wrapArrowFunction, - wrapQuote, -} from './util' +import { arrayify, capitalizeFirst, uniquify, wrapArrowFunction, wrapQuote } from './util' /** BigInt, Boolean, Bytes, DateTime, Decimal, Float, Int, JSON, String, $ModelName */ type DefaultPrismaFieldType = @@ -185,6 +179,44 @@ export class PrismaConvertor { return decorator } + extractValidatorDecoratorsFromField = ( + dmmfField: DMMF.Field, + ): DecoratorComponent[] => { + const decorators: DecoratorComponent[] = [] + const importFrom = 'class-validator' + let name: string; + switch (dmmfField.type) { + case 'Int': + name = 'IsInt' + break; + case 'DateTime': + name = 'IsDate' + break; + case 'String': + name = 'IsString' + break; + case 'Boolean': + name = 'IsBoolean' + break; + } + if (name && !dmmfField.isList) { + decorators.push(new DecoratorComponent({ name, importFrom })) + } + + if (dmmfField.isRequired) { + name = 'IsDefined' + decorators.push(new DecoratorComponent({ name, importFrom })) + } else { + name = 'IsOptional' + decorators.push(new DecoratorComponent({ name, importFrom })) + } + if (dmmfField.kind === 'enum') { + name = 'IsEnum' + decorators.push(new DecoratorComponent({ name, importFrom, params: [`${String(dmmfField.type)}`] })) + } + return decorators; + } + getClass = (input: ConvertModelInput): ClassComponent => { /** options */ const options = Object.assign( @@ -212,7 +244,11 @@ export class PrismaConvertor { const relationTypes = uniquify( model.fields .filter( - (field) => field.relationName && (this._config.separateRelationFields ? true : model.name !== field.type), + (field) => + field.relationName && + (this._config.separateRelationFields + ? true + : model.name !== field.type), ) .map((v) => v.type), ) @@ -343,6 +379,11 @@ export class PrismaConvertor { field.decorators.push(decorator) } + if (this.config.useValidator) { + const decorators = this.extractValidatorDecoratorsFromField(dmmfField) + field.decorators.push(...decorators) + } + if (this.config.useGraphQL) { const decorator = this.extractTypeGraphQLDecoratorFromField(dmmfField) diff --git a/src/generator.ts b/src/generator.ts index 608c23f..5d076d8 100755 --- a/src/generator.ts +++ b/src/generator.ts @@ -2,13 +2,7 @@ import { GeneratorOptions } from '@prisma/generator-helper' import { parseEnvValue } from '@prisma/internals' import * as path from 'path' import { PrismaConvertor } from './convertor' -import { - getRelativeTSPath, - parseBoolean, - parseNumber, - prettierFormat, - writeTSFile, -} from './util' +import { getRelativeTSPath, parseBoolean, parseNumber, prettierFormat, rmdir, writeTSFile } from './util' import { INDEX_TEMPLATE } from './templates/index.template' import { ImportComponent } from './components/import.component' import * as prettier from 'prettier' @@ -53,6 +47,14 @@ export const PrismaClassGeneratorOptions = { defaultValue: false, desc: 'preserve default nullable behavior', }, + useValidator: { + desc: 'use nest js class-validator decorators', + defaultValue: false, + }, + rewrite: { + defaultValue: false, + desc: 'rewrite output at generate' + }, } as const export type PrismaClassGeneratorOptionsKeys = @@ -133,6 +135,8 @@ export class PrismaClassGenerator { const config = this.getConfig() this.setPrismaClientPath() + await rmdir(output, config.rewrite) + const convertor = PrismaConvertor.getInstance() convertor.dmmf = dmmf convertor.config = config diff --git a/src/util.ts b/src/util.ts index 9f44edc..2487ca9 100755 --- a/src/util.ts +++ b/src/util.ts @@ -89,3 +89,17 @@ export const writeTSFile = ( export const prettierFormat = (content: string, options: Options = {}) => { return format(content, { ...options, parser: 'typescript' }) } + +export const rmdir = async ( + dirPath: string, + rewrite: boolean = false, +) => { + if (fs.existsSync(dirPath) && rewrite) { + const deletePromises = fs.readdirSync(dirPath).map(async (file) => { + const filePath = path.join(dirPath, file) + log(`Remove ${filePath}`) + return fs.unlinkSync(filePath) + }) + await Promise.all(deletePromises) + } +}