UNPKG

@notadd/cli

Version:

notadd core none dependence

333 lines (326 loc) 12.2 kB
import { join } from 'path'; import { writeFileSync, ensureDirSync, pathExistsSync } from 'fs-extra'; import { upperFirst, lowerFirst } from 'lodash'; import { UtilService, GetPackageJsonsResult } from './util'; import { ReadEntitiesResult } from './readEntities'; import { Injectable } from '@notadd/core'; @Injectable() export class CreateApiService { constructor(private util: UtilService) {} private _packageJsons: GetPackageJsonsResult; createApi(entities: ReadEntitiesResult[]) { const dirName = entities[0].dirName; // 获取不同层的package.json this._packageJsons = this.util.getPackageJsons(entities); const { apiDir } = this._packageJsons; ensureDirSync(apiDir); //创建api文件 entities.forEach((it) => { const { entityFileName } = this._entityFormat(it); const addContent = this._createAddContent(it); if (!pathExistsSync(apiDir + `/${entityFileName}-add.api.ts`)) { writeFileSync(apiDir + `/${entityFileName}-add.api.ts`, addContent); } const listContent = this._createListContent(it); if (!pathExistsSync(apiDir + `/${entityFileName}-list.api.ts`)) { writeFileSync(apiDir + `/${entityFileName}-list.api.ts`, listContent); } const updateContent = this._createUpdateContent(it); if (!pathExistsSync(apiDir + `/${entityFileName}-update.api.ts`)) { writeFileSync(apiDir + `/${entityFileName}-update.api.ts`, updateContent); } const deleteContent = this._createDeleteContent(it); if (!pathExistsSync(apiDir + `/${entityFileName}-delete.api.ts`)) { writeFileSync(apiDir + `/${entityFileName}-delete.api.ts`, deleteContent); } const detailContent = this._createDetailContent(it); if (!pathExistsSync(apiDir + `/${entityFileName}-detail.api.ts`)) { writeFileSync(apiDir + `/${entityFileName}-detail.api.ts`, detailContent); } }); // 导入文件 导入文件名 导出文件 const imports = this._createApiImports(entities); // 创建.module.ts const moduleContent = this._createModuleContent(entities, imports); const apiModuleName = `${dirName}.module.ts`; const apiModuleUrl = join(apiDir, apiModuleName); if (pathExistsSync(apiModuleUrl)) { console.log(`api层已存在${apiModuleName}文件,所以未生成`); } else { writeFileSync(apiModuleUrl, moduleContent); } //创建此模块的index.ts 和修改模块的导出 this.util.createIndexTs(dirName, apiDir, imports.exportFile); } private _createAddContent(it: ReadEntitiesResult) { const { pickList, domainName, usedEntity, entityPre, addName } = this._entityFormat(it); const { entitiesPakcageJson, domainPakcageJson } = this._packageJsons; return ` import { Mutation } from '@notadd/graphql'; import { Args, Controller, EntityService } from '@notadd/core'; import { ClassValidatorService } from '@notadd/class-validator'; import { GraphqlError, TypeError } from '@ganker/error'; import { ${domainName} } from '${domainPakcageJson.name}'; import { ${it.entityName} } from '${entitiesPakcageJson.name}'; export type ${entityPre}AddInput = Pick< ${it.entityName}, ${pickList} >; @Controller() export class ${addName} { constructor( private readonly entityService: EntityService, private readonly validator: ClassValidatorService, private readonly ${usedEntity}: ${domainName} ) {} /** * 添加 */ @Mutation() async ${usedEntity}Add( @Args('entity') entity: ${entityPre}AddInput ): Promise<any> { try { const created = await this.entityService.createType(${it.entityName}, entity); const errMessage = await this.validator.validateOrMessage(created, ${it.entityName}); if (errMessage) throw new TypeError('02', errMessage); return await this.${usedEntity}.add(created); } catch (e) { throw new GraphqlError(\`B200101\${e.code}\`, e.message); } } } `; } private _createListContent(it: ReadEntitiesResult) { const { pickList, domainName, usedEntity, entityPre, listName } = this._entityFormat(it); const { entitiesPakcageJson, domainPakcageJson } = this._packageJsons; return ` import { Query, Limit, ListCount } from '@notadd/graphql'; import { Args, Controller } from '@notadd/core'; import { GraphqlError } from '@ganker/error'; import { ${domainName} } from '${domainPakcageJson.name}'; import { ${it.entityName} } from '${entitiesPakcageJson.name}'; interface ${entityPre}ListInputWhere { ids?: number[] } interface ${entityPre}ListInputOrder { createDate?: string; } type ${entityPre}ListResult = Partial< Pick< ${it.entityName}, ${pickList} > >; @Controller() export class ${listName} { constructor(private readonly ${usedEntity}: ${domainName}) {} /** * 列表 */ @Query() async ${usedEntity}List( @Args('where') where?: ${entityPre}ListInputWhere, @Args('limit') limit?: Limit, @Args('order') order?: ${entityPre}ListInputOrder ): Promise<ListCount<${entityPre}ListResult>> { try { return await this.${usedEntity}.list(where, limit, order); } catch (e) { throw new GraphqlError(\`B200103\${e.code}\`, e.message); } } } `; } private _createUpdateContent(it: ReadEntitiesResult) { const { pickList, domainName, usedEntity, entityPre, updateName } = this._entityFormat(it); const { entitiesPakcageJson, domainPakcageJson } = this._packageJsons; return ` import { Mutation } from '@notadd/graphql'; import { Args, Controller } from '@notadd/core'; import { ClassValidatorService } from '@notadd/class-validator'; import { GraphqlError, TypeError } from '@ganker/error'; import { ${domainName} } from '${domainPakcageJson.name}'; import { ${it.entityName} } from '${entitiesPakcageJson.name}'; type ${entityPre}UpdateInputEntity = Partial< Pick< ${it.entityName}, ${pickList} > >; @Controller() export class ${updateName} { constructor( private readonly validator: ClassValidatorService, private readonly ${usedEntity}: ${domainName} ) {} /** * 修改 */ @Mutation() async ${usedEntity}UpdateById( @Args('id') id: number, @Args('entity') entity: ${entityPre}UpdateInputEntity ): Promise<any> { try { const errMessage = await this.validator.validateOrMessage(entity, ${it.entityName}, { skipMissingProperties: true, }); if (errMessage) throw new TypeError('02', errMessage); return await this.${usedEntity}.updateById(id, entity); } catch (e) { throw new GraphqlError(\`B200104\${e.code}\`, e.message); } } } `; } private _createDeleteContent(it: ReadEntitiesResult) { const { domainName, usedEntity, deleteName } = this._entityFormat(it); const { domainPakcageJson } = this._packageJsons; return ` import { Mutation } from '@notadd/graphql'; import { Args, Controller } from '@notadd/core'; import { GraphqlError } from '@ganker/error'; import { ${domainName} } from '${domainPakcageJson.name}'; @Controller() export class ${deleteName} { constructor(private readonly ${usedEntity}: ${domainName}) {} /** * 删除 */ @Mutation() async ${usedEntity}DeleteById(@Args('id') id: number): Promise<any> { try { return await this.${usedEntity}.deleteById(id); } catch (e) { throw new GraphqlError(\`B200102\${e.code}\`, e.message); } } } `; } private _createDetailContent(it: ReadEntitiesResult) { const { domainName, usedEntity, detailName } = this._entityFormat(it); const { entitiesPakcageJson, domainPakcageJson } = this._packageJsons; return ` import { Query } from '@notadd/graphql'; import { Args, Controller } from '@notadd/core'; import { GraphqlError } from '@ganker/error'; import { ${domainName} } from '${domainPakcageJson.name}'; import { ${it.entityName} } from '${entitiesPakcageJson.name}'; @Controller() export class ${detailName} { constructor(private readonly ${usedEntity}: ${domainName}) {} /** * 详情 */ @Query() async ${usedEntity}DetailById( @Args('id') id: number ): Promise<${it.entityName}> { try { return await this.${usedEntity}.detailById(id); } catch (e) { throw new GraphqlError(\`B200105\${e.code}\`, e.message); } } } `; } private _createModuleContent(entities: ReadEntitiesResult[], imports: any) { const dirName = entities[0].dirName; const { domainPakcageJson } = this._packageJsons; return ` import { Module } from '@notadd/core'; import { ClassValidatorModule } from '@notadd/class-validator'; import { ${upperFirst(dirName)}DomainModule } from '${domainPakcageJson.name}';${imports.importFile} @Module({ imports: [ ${upperFirst(dirName)}DomainModule, ClassValidatorModule, ], controllers: [ ${imports.importNames} ] }) export class ${upperFirst(dirName)}ApiModule {} `; } private _createApiImports(entities: ReadEntitiesResult[]) { // 导入文件 导入文件名 导出文件 return entities .map((it) => { const { entityFileName, listName, updateName, deleteName, detailName, addName, } = this._entityFormat(it); // 导入文件 const importFile = ` import { ${addName} } from './${entityFileName}-add.api'; import { ${listName} } from './${entityFileName}-list.api'; import { ${updateName} } from './${entityFileName}-update.api'; import { ${deleteName} } from './${entityFileName}-delete.api'; import { ${detailName} } from './${entityFileName}-detail.api';`; // 导入文件名 const importNames = `${addName}, ${listName}, ${updateName}, ${deleteName}, ${detailName}, `; // 导出文件 const exportFile = ` export * from './${entityFileName}-add.api'; export * from './${entityFileName}-list.api'; export * from './${entityFileName}-update.api'; export * from './${entityFileName}-delete.api'; export * from './${entityFileName}-detail.api';`; return { importFile, importNames, exportFile }; }) .reduce( (acc, cur) => { acc.importFile += cur.importFile; acc.importNames += cur.importNames; acc.exportFile += cur.exportFile; return acc; }, { importFile: '', importNames: ``, exportFile: `` } ); } private _entityFormat(it: ReadEntitiesResult) { const filedNames: string[] = it.filedNames; const pickList = filedNames .map((filed, filedIndex) => { if (filedIndex == filedNames.length - 1) { return `'${filed}'`; } return `'${filed}' | `; }) .reduce((acc, cur) => (acc += cur), ''); const entityFileName = it.fileName.replace('.entity.ts', ''); const domainName = it.entityName.replace(/Entity$/, 'Service'); const usedEntity = lowerFirst(it.entityName.replace(/Entity$/, '')); const entityPre = it.entityName.replace(/Entity$/, ''); const addName = it.entityName.replace(/Entity$/, 'AddApiController'); const listName = it.entityName.replace(/Entity$/, 'ListApiController'); const updateName = it.entityName.replace(/Entity$/, 'UpdateApiController'); const deleteName = it.entityName.replace(/Entity$/, 'DeleteApiController'); const detailName = it.entityName.replace(/Entity$/, 'DetailApiController'); return { pickList, entityFileName, domainName, usedEntity, entityPre, listName, updateName, deleteName, detailName, addName, }; } }