@notadd/cli
Version:
notadd core none dependence
333 lines (326 loc) • 12.2 kB
text/typescript
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';
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}
>;
export class ${addName} {
constructor(
private readonly entityService: EntityService,
private readonly validator: ClassValidatorService,
private readonly ${usedEntity}: ${domainName}
) {}
/**
* 添加
*/
async ${usedEntity}Add(
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}
>
>;
export class ${listName} {
constructor(private readonly ${usedEntity}: ${domainName}) {}
/**
* 列表
*/
async ${usedEntity}List(
where?: ${entityPre}ListInputWhere,
limit?: Limit,
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}
>
>;
export class ${updateName} {
constructor(
private readonly validator: ClassValidatorService,
private readonly ${usedEntity}: ${domainName}
) {}
/**
* 修改
*/
async ${usedEntity}UpdateById(
id: number,
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}';
export class ${deleteName} {
constructor(private readonly ${usedEntity}: ${domainName}) {}
/**
* 删除
*/
async ${usedEntity}DeleteById( 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}';
export class ${detailName} {
constructor(private readonly ${usedEntity}: ${domainName}) {}
/**
* 详情
*/
async ${usedEntity}DetailById(
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}
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,
};
}
}