UNPKG

@arianaprojects/prisma-nestjs-crud-generator

Version:
562 lines (514 loc) 18 kB
import { ReqNamesType } from './../interfaces'; import { DMMF } from '@prisma/generator-helper/dist/dmmf'; import { apiResponseInterface, functionFixConfig, generalConfig, ReqNames, ReqType } from '../interfaces'; import { classGenerator, constructorGenerator, decoratorGenerator, functionGenerator, functionPromiseGenerator, parameterGenerator, parameterPrivateGenerator } from '../templates'; import Model from './Model'; import fs from 'fs'; import { fixedConfig, UserDecoratorParam, UserParam, UserParamService } from './const'; import { prettierFormatFormat, tsTypes } from '../util'; export default class CRUD { parent: Model; config: generalConfig; controller: string; service: string; idGenerator: boolean = false; constructor(parent: Model) { this.parent = parent; this.config = this.configParser(this.parent.option.configPath); // console.log('here', this.parent.model.fields); this.generate(); } private generate() { // if id not automatically let conBody: string[] = []; let serBody: string[] = []; conBody.push(this.controllerClassConstructor()); serBody.push(this.serviceClassConstructor()); if (this.config.access && !this.config.accessBlackList.includes(this.parent.namePascal)) { serBody.push( functionPromiseGenerator( 'hasAccess', `${UserParamService}, ${this.parent.replace('query: FIND_DTO')}`, 'Boolean', this.parent.replace(` const ret = await this.prismaService.NAME_CAMEL.findMany({ where: { ...query, ...this.hasAccessData(user), ...this.isNotDeletedData(), }, }); return ret.length > 0; `), ), ); serBody.push( functionGenerator( 'hasAccessData', `${UserParamService}`, `Access${this.parent.namePascal}Dto`, ` return { userId:user.id }; `, ), ); } serBody.push( functionGenerator( 'isNotDeletedData', ``, `Deleted${this.parent.namePascal}Dto`, ` return { deletedAt:null }; `, ), ); serBody.push( functionGenerator( 'pseudonymisationData', ``, `Pseudonymisation${this.parent.namePascal}Dto`, ` return { }; `, ), ); this.parent.idsNoDefault.map((id) => { serBody.push( functionGenerator( `${id.name}Gen`, ``, tsTypes(id.type), `// TODO return null`, ), ); }); const keys = Object.keys(fixedConfig.functions); keys.map((f, i) => { const d = this.config && this.config.functions && this.config.functions[f] && this.config.functions[f].disable; if (!(this.config && this.config.functions && this.config.functions[f] && this.config.functions[f].disable)) { if (i == 12) { conBody.push('\n\n//\t------------------ ADMIN -------------------\n'); serBody.push('\n\n//\t------------------ ADMIN -------------------\n'); } const c = fixedConfig.functions[f]; // controller conBody.push(this.controllerFunction(ReqNames[f], c, true, true, true)); // service serBody.push(this.serviceFunction(ReqNames[f], c)); serBody.push('\n'); } }); this.controller = prettierFormatFormat(this.controllerGenerator(conBody.join('\n'))); this.service = prettierFormatFormat(this.serviceGenerator(serBody.join('\n'))); } private configParser(path?: string): generalConfig { if (!!path) return JSON.parse(fs.readFileSync(process.cwd() + '/' + path, 'utf-8')) as generalConfig; return null; } private functionControllerDecorator(type: ReqType, conf: functionFixConfig, name: string) { let res: string[] = []; let p: string[] = [conf.fixedPath]; if (conf.param) this.parent.idFields.map((id) => { if (this.parent.idFields.length > 1) p.push(`${id.name}/:${id.name}`); else p.push(`:${id.name}`); }); res.push(decoratorGenerator(String(type), p.join('/'))); if (this.config && this.config.functions && this.config.functions[name] && this.config.functions[name].additionalDecorator) res.push(this.config.functions[name].additionalDecorator.join('\n')); return res.join('\n'); } private apiOperationDecorator(name: ReqNames, conf: functionFixConfig) { let res: string[] = []; res.push('@ApiOperation({'); if (this.config && this.config.functions && this.config.functions[name] && !!this.config.functions[name].summary) res.push(`summary:"${this.parent.replace(this.config.functions[name].summary)}",`); if (this.config && this.config.functions && this.config.functions[name] && !!this.config.functions[name].description) res.push(`description:"${this.parent.replace(this.config.functions[name].description)}",`); res.push(`summary:"${this.parent.replace(conf.info)}",`); res.push('})'); return res.join('\n'); } private allApiResponseDecorators(conf: functionFixConfig) { return conf.responses.map((r) => this.apiResponseDecorator(r, conf)).join('\n'); } private apiResponseDecorator(option: apiResponseInterface, conf: functionFixConfig) { let res: string[] = []; res.push('@ApiResponse({'); res.push(`status:${this.parent.replace(option.status)},`); if (option.description) res.push(`description:"${this.parent.replace(option.description)}",`); if (option.type) res.push(`type:${this.parent.replace(option.type)},`); res.push('})'); return res.join('\n'); } private apiRequestDecorator(option: functionFixConfig) { let res: string[] = []; // // ApiQuery // if (option.query) { // res.push('@ApiQuery({'); // res.push('type:' + this.parent.replace(option.query)); // res.push('})'); // } // // ApiParam // if (option.param) { // res.push('@ApiParam({'); // if (option.bodyArray) res.push('isArray:true'); // res.push('type:' + this.parent.replace(option.param)); // res.push('})'); // } // // Header // if (option.header) { // res.push('@ApiHeader({'); // res.push('type:' + this.parent.replace(option.header)); // res.push('})'); // } // ApiBody if (option.body) { res.push('@ApiBody({'); if (option.bodyArray) res.push('isArray:true,'); res.push('type:' + this.parent.replace(option.body)); res.push('})'); } return res.join('\n'); } private paramController(option: functionFixConfig, access: boolean = false) { let res: string[] = []; if (access && !option.admin) { res.push(UserDecoratorParam); res.push(','); } // ApiQuery if (option.query) { res.push('@Query() query: '); res.push(this.parent.replace(option.query)); res.push(','); } // ApiParam if (option.param) { res.push('@Param() param: '); res.push(this.parent.replace(option.param)); if (option.paramArray) res.push('[]'); res.push(','); } // Header if (option.header) { res.push('@Header() header: '); res.push(this.parent.replace(option.header)); res.push(','); } // ApiBody if (option.body) { res.push('@Body() body: '); res.push(this.parent.replace(option.body)); if (option.bodyArray) res.push('[]'); res.push(','); } return res.join(' '); } private paramControllerToService(option: functionFixConfig, access: boolean = false) { let res: string[] = []; if (access && !option.admin) { res.push(UserParam); res.push(','); } // ApiQuery if (option.query) { res.push('query'); res.push(','); } // ApiParam if (option.param) { res.push('param'); res.push(','); } // Header if (option.header) { res.push('header'); res.push(','); } // ApiBody if (option.body) { res.push('body '); res.push(','); } // console.log(access, !option.admin, res); return res.join(' '); } private paramService(option: functionFixConfig, access: boolean = false) { let res: string[] = []; if (access && !option.admin) { res.push(UserParamService); res.push(','); } // ApiQuery if (option.query) { res.push(parameterGenerator('query', this.parent.replace(option.query))); res.push(','); } // ApiParam if (option.param) { res.push(parameterGenerator('param', this.parent.replace(option.param))); if (option.paramArray) res.push('[]'); res.push(','); } // Header if (option.header) { res.push(parameterGenerator('header', this.parent.replace(option.header))); res.push(','); } // ApiBody if (option.body) { res.push(parameterGenerator('body ', this.parent.replace(option.body))); if (option.bodyArray) res.push('[]'); res.push(','); } return res.join(' '); } private serviceClassDecorator() { let res: string[] = []; res.push('@Injectable()'); return res.join('\n'); } private controllerClassDecorator() { let res: string[] = []; res.push(``); res.push(`@Controller('${this.parent.nameCamel}')`); res.push('@ApiBearerAuth()'); res.push(`@ApiTags("${this.parent.namePascal}")`); return res.join('\n'); } private controllerFunctionComment(name: ReqNames) { let res: string[] = ['\n']; res.push('/********************************************************************'); res.push('* ' + ReqNames[name]); res.push(' ********************************************************************/'); return res.join('\n'); } private controllerFunctionBody(name: ReqNames, conf: functionFixConfig) { let res: string[] = []; const ENTITY = conf.responses.filter((r) => r.type == 'ENTITY').length >= 1; const ENTITYArray = conf.responses.filter((r) => r.type == '[ENTITY]').length >= 1; if (ENTITY || ENTITYArray) res.push(`return plainToInstance(${this.parent.namePascal}, (await this.${this.parent.nameCamel}Service.${name}(${this.paramControllerToService(conf, this.config.access)})))`); else res.push(`return await this.${this.parent.nameCamel}Service.${name}(${this.paramControllerToService(conf, this.config.access)})`); return res.join('\n'); } private controllerFunction(name: ReqNames, conf: functionFixConfig, apiOperator: boolean, apiReq: boolean, apiResp: boolean) { let res: string[] = []; const optionalConf = this.config && this.config.functions && this.config.functions[name]; res.push(this.controllerFunctionComment(name)); res.push(this.functionControllerDecorator(ReqType[ReqNamesType[name]], conf, name)); // TODO param if (apiOperator) res.push(this.apiOperationDecorator(name, conf)); if (apiResp) res.push(this.allApiResponseDecorators(conf)); if (apiReq) res.push(this.apiRequestDecorator(conf)); res.push(functionPromiseGenerator(ReqNames[name], this.paramController(conf, this.config.access), this.parent.replace(conf.resp), this.parent.replace(this.controllerFunctionBody(name, conf)))); return res.join('\n'); } private serviceFunction(name: ReqNames, conf: functionFixConfig) { let res: string[] = []; res.push(functionPromiseGenerator(ReqNames[name], this.parent.replace(this.paramService(conf, this.config.access)), this.parent.replace(conf.resp), this.parent.replace(this.serviceFunctionBody(conf, name)))); return res.join('\n\n'); } private serviceFunctionBody(conf: functionFixConfig, name: ReqNames) { let res: string[] = []; const service = this.config.access && !this.config.accessBlackList.includes(this.parent.namePascal) ? conf.serviceAccess : conf.service; // console.log(this.parent.namePascal, service); let fix = service; if (this.parent.idsNoDefault.length > 0) { if (fix.includes('createMany') && conf.bodyArray) { fix = service.replace( '...b ', ` ${this.parent.idsNoDefault .map((id) => { return `${id.name}:this.${id.name}Gen()`; }) .join(`,`)} , ...b `, ); // console.log(fix); } else if (fix.includes('create') && !conf.bodyArray) { fix = service.replace( '...body', ` ${this.parent.idsNoDefault .map((id) => { return `${id.name}:this.${id.name}Gen()`; }) .join(`,`)} , ...body `, ); // console.log(fix); } } res.push(fix); return res.join('\n'); } private controllerClassConstructor() { let res: string[] = []; // console.log('sad'); res.push(constructorGenerator(parameterPrivateGenerator(this.parent.nameCamel + 'Service', this.parent.namePascal + 'Service'), '')); return res.join('\n'); } private serviceClassConstructor() { let res: string[] = []; res.push(constructorGenerator(parameterPrivateGenerator('prismaService', 'PrismaService'), '')); return res.join('\n'); } private controllerImport() { let res: string[] = []; if (this.config.additionalImport) { this.config.additionalImport.map((i) => { res.push(i); }); } res.push( `import { ${this.parent.namePascal} } from './${this.parent.nameCamel}.entity';`, ); res.push( `import { Find${this.parent.namePascal}Dto, Create${this.parent.namePascal}Dto, Update${this.parent.namePascal}Dto, Connect${this.parent.namePascal}Dto, Find${this.parent.namePascal}AdminDto, Create${this.parent.namePascal}AdminDto, Update${this.parent.namePascal}AdminDto, Connect${this.parent.namePascal}AdminDto, Access${this.parent.namePascal}Dto, Deleted${this.parent.namePascal}Dto, Pseudonymisation${this.parent.namePascal}Dto } from './${this.parent.nameCamel}.dto';`, ); res.push( `import { Body, Controller, Delete, Get, HttpCode, HttpStatus,Query, NotFoundException, Param, Post, Patch, Put, UnauthorizedException, ForbiddenException, ConflictException, Req,Injectable } from '@nestjs/common'; import { ApiBearerAuth, ApiBody, ApiConflictResponse, ApiConsumes, ApiCreatedResponse, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiParam, ApiQuery, ApiResponse, ApiTags, ApiUnauthorizedResponse, } from '@nestjs/swagger';`, "import { Prisma } from '@prisma/client';", ); res.push(`import { UserGeneralDto } from 'src/shared/dtos/user.dto';`); res.push(`import { plainToInstance } from 'class-transformer';`); res.push(`import { User as UserDecorator } from 'src/shared/decorators/user.decorator'; `); res.push( `import { ${this.parent.namePascal}Service } from './${this.parent.nameCamel}.service';`, ); return res.join('\n'); } private serviceImport() { let res: string[] = []; if (this.config.additionalImport) { this.config.additionalImport.map((i) => { res.push(i); }); } res.push( `import { ${this.parent.namePascal} } from './${this.parent.nameCamel}.entity';`, ); res.push(`import { plainToInstance } from 'class-transformer';`); res.push(`import { PrismaService } from 'src/shared/services/prisma.service';`); res.push(`import { UserGeneralDto } from 'src/shared/dtos/user.dto';`); res.push(`import { User as UserDecorator } from 'src/shared/decorators/user.decorator'; `); res.push( `import { Find${this.parent.namePascal}Dto, Create${this.parent.namePascal}Dto, Update${this.parent.namePascal}Dto, Connect${this.parent.namePascal}Dto, Find${this.parent.namePascal}AdminDto, Create${this.parent.namePascal}AdminDto, Update${this.parent.namePascal}AdminDto, Connect${this.parent.namePascal}AdminDto, Access${this.parent.namePascal}Dto, Deleted${this.parent.namePascal}Dto, Pseudonymisation${this.parent.namePascal}Dto } from './${this.parent.nameCamel}.dto';`, ); res.push( `import { Body, Controller, Delete, Get, HttpCode, HttpStatus,Query, NotFoundException, Param, Post, Patch, Put, UnauthorizedException, ForbiddenException, ConflictException, Req,Injectable } from '@nestjs/common'; import { ApiBearerAuth, ApiBody, ApiConflictResponse, ApiConsumes, ApiCreatedResponse, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiParam, ApiQuery, ApiResponse, ApiTags, ApiUnauthorizedResponse, } from '@nestjs/swagger';`, "import { Prisma } from '@prisma/client';", ); let prismaImport = []; this.parent.enumFields.map((f) => { prismaImport.push(` ${f.type},`); }); res.push('import { ' + prismaImport.join('\n') + "} from '@prisma/client'"); return res.join('\n'); } private controllerGenerator(body: string) { let res: string[] = []; res.push(this.controllerImport()); res.push(classGenerator(this.parent.namePascal + 'Controller', body, this.controllerClassDecorator())); return res.join('\n'); } private serviceGenerator(body: string) { let res: string[] = []; res.push(this.serviceImport()); res.push(classGenerator(this.parent.namePascal + 'Service', body, this.serviceClassDecorator())); return res.join('\n'); } }