venom-generator
Version:
In the way of code generation, complete the storage model->computation model (business API) transformation to achieve the goal of design and implementation
277 lines • 14.4 kB
JavaScript
;
//指令解析模块
Object.defineProperty(exports, "__esModule", { value: true });
const modelSchema_1 = require("./modelSchema");
const fs_1 = require("fs");
const path_1 = require("path");
const Operation = require("./operation");
const util = require("./util");
const code = require("./code");
// 静态参数值,用以判断使用
const QUERY = 'Query';
const MUTATION = 'Mutation';
// query计算模型(业务 API)生成Query.ts文件数据
function querys(server, prismaPath, output, common, dev) {
return categoryModelResolver(server, prismaPath, QUERY, output, common, dev);
}
exports.querys = querys;
// mutation计算模型(业务 API)生成Mutation.ts文件数据
function mutations(server, prismaPath, output, common, dev) {
return categoryModelResolver(server, prismaPath, MUTATION, output, common, dev);
}
exports.mutations = mutations;
// 存储模型->计算模型(业务 API)转换生成API文件所需数据
function categoryModelResolver(server, prismaPath, category, output, common, dev) {
const model = modelResolver(prismaPath);
const types = model.datamodel.types;
const typeArr = types.filter(type => type.directives.length !== 0);
const len = typeArr.length;
if (len === 0 && category === MUTATION)
return { apiData: '', againCommon: false };
// 暴露接口
let prismaField = '';
// 自定义接口
let fields = '';
// 导入方法
let imports = '';
// 是否依赖公共服务
let poclicy = '';
// 是否需要检查权限
let importCalcAuthorization = '';
// 是否为基本数据类型
// let databaseType: boolean = true
// 需要过滤掉api字段
let filters = '';
// nexus内部参数导入
let argNexus = '';
// 是否存在内部再次依赖公共服务
let againCommon = false;
// 模型文件解析
types.forEach(type => {
// 当前自定义指令默认不需要检查权限
let checkCalcAuthorization = false;
// 判断当前自定义指令是否需要检查权限[暂支持一种权限后续陆续添加]
const CalcAuth = type.directives.filter(Calc => Calc.name === 'CalcAuthorization');
// 权限方法名
let methodName = '';
// 权限拥有者,用于解析代码实现
let aud = '';
// 权限拥有者,用于传参
let authAud = '';
// 自定义权限名称
let calcAuthorization = '';
CalcAuth.forEach(auth => {
// 当前指令
checkCalcAuthorization = true;
// 获取的CalcAuthorization自定义指令中,只提取aud(非空),其它规则固定,如方法名=用当前type名
methodName = type.name;
aud = checkCalcAuthorization === true && (auth.arguments.aud === undefined || auth.arguments.aud === '') ? '' : auth.arguments.aud;
authAud = aud === '' ? `''` : aud;
calcAuthorization = auth.name;
});
// 非公共服务是否需要过掉字段
filters += common === false ? Operation.filter(category, type) : '';
// 自定义指令解析
type.directives.forEach(directive => {
const del = directive.arguments.delete;
if (dev)
console.log(`directive--->`, directive, '\n');
const argumentsArgs = directive.arguments.args !== undefined && directive.arguments.args !== '' ? directive.arguments.args.split(',') : [];
// 获取自定义指令名称
const directiveName = directive.name;
// 如果需要依赖公共权限方法 则导入公共类
if (directiveName === 'Include') {
poclicy = directive.arguments.value;
againCommon = common ? true : false;
}
// 生成api业务接口数据
switch (directiveName) {
// 如果为 Query或Mutation 则暴露出去
case category:
// create独有
let ctauthAud = "''";
if (argumentsArgs.length !== 0) {
if (authAud !== "''")
authAud = util.basicDataType(argumentsArgs[0].split(':')[1]) ? `args.${util.underlineToCamel(aud)}` : `args.${aud.replace('_', '.')}`;
if (authAud !== "''")
ctauthAud = util.basicDataType(argumentsArgs[0].split(':')[1]) ? `args.${util.underlineToCamel(aud)}` : `args.${aud.replace('where', 'data').replace('_', '.')}`;
}
// 当前自定义是否需要权限
const authorization = code.calcAuthorizationMethodCode(checkCalcAuthorization, calcAuthorization, authAud, methodName);
const ctauthorization = code.calcAuthorizationMethodCode(checkCalcAuthorization, calcAuthorization, ctauthAud, methodName);
const up = directive.arguments.update;
const ct = directive.arguments.create;
// 是否需要权限控制
if (checkCalcAuthorization) {
// 是否需要导入权限文件
importCalcAuthorization = code.calcAuthorizationCode(againCommon, calcAuthorization);
argNexus += util.improtAgrs(category, argumentsArgs);
if (category === QUERY) {
fields += Operation.publicMethod(category, server, type.name, directive, authorization);
}
else {
// Mutation中是否暴露增删改
fields += up == true ? Operation.updateMethod(server, type.name, directive, authorization) : '';
fields += del == true ? Operation.deleteMethod(server, type.name, directive, authorization) : '';
fields += ct == true ? Operation.publicMethod(category, server, type.name, directive, ctauthorization) : '';
}
}
else {
if (category === QUERY) {
prismaField += Operation.publicMethods(category, type.name);
}
else {
// Mutation中是否暴露增删改
prismaField += up == true ? Operation.publicMethods(category, `update${type.name}`) : '';
prismaField += del == true ? Operation.publicMethods(category, `delete${type.name}`) : '';
prismaField += ct == true ? Operation.publicMethods(category, `create${type.name}`) : '';
}
}
break;
// 如果需要查询唯一,则生成唯一api接口
case `${category}Unique`:
if (argumentsArgs.length !== 0) {
if (authAud !== "''")
authAud = util.basicDataType(argumentsArgs[0].split(':')[1]) ? `args.${util.underlineToCamel(aud)}` : `args.${aud.replace('_', '.')}`;
// console.log('authAud-->', argumentsArgs[0].split(':')[1], authAud)
}
// 当前自定义是否需要权限
const authorizationUnique = code.calcAuthorizationMethodCode(checkCalcAuthorization, calcAuthorization, authAud, methodName);
// 是否需要导入权限文件
importCalcAuthorization = code.calcAuthorizationCode(againCommon, calcAuthorization);
// nexus内部参数导入
argNexus += util.improtAgrs(`${category}Unique`, argumentsArgs);
fields += Operation.privateMethod(server, type.name, directive, authorizationUnique, aud);
break;
// 如果使用自定义指令导出自定义方法,则根据自定义指令生成api接口
case `${category}Resolve`:
if (argumentsArgs.length !== 0) {
if (authAud !== "''")
authAud = util.basicDataType(argumentsArgs[0].split(':')[1]) ? `args.${util.underlineToCamel(aud)}` : `args.${aud.replace('_', '.')}`;
// console.log('authAud-->', argumentsArgs[0].split(':')[1], authAud)
}
// 当前自定义是否需要权限
const authorizationResolve = code.calcAuthorizationMethodCode(checkCalcAuthorization, calcAuthorization, authAud, methodName);
// 是否需要导入权限文件
importCalcAuthorization = code.calcAuthorizationCode(againCommon, calcAuthorization);
// nexus内部参数导入
argNexus += util.improtAgrs(`${category}Resolve`, argumentsArgs);
const name = util.initialCase(type.name);
imports += `${name}Resolve,`;
fields += Operation.customMethod(`${category}Resolve`, type.name, directive, authorizationResolve);
break;
}
});
});
// index.ts生成(参数dev为true时使用)
if (category === QUERY && dev)
index(server, poclicy);
// context.ts生成
if (category === QUERY)
context(server, output, poclicy, common);
// schema.ts生成
if (category === QUERY)
schema(output, server, typeArr);
// resolvers文件夹下的index.ts文件生成
resolversIndex(output, category, prismaField, fields, len);
// 需要暴露的公共无权限api字段[当模型文件没有任何指令时默认关闭api对外的暴露]
const prismaFields = prismaField !== '' ? `t.prismaFields({ pick:[${util.trim(prismaField, ',', 'right')}]})` : `t.prismaFields([])`;
// 是否需要导入自定义方法文件
imports = imports !== '' ? `import { ${util.trim(imports, ',', 'right')} } from './${server}'\n` : '';
// api文件数据生成
const apiData = Operation.operationApiCode(category, importCalcAuthorization, imports, prismaFields, fields, filters, argNexus);
return { apiData: apiData, againCommon: againCommon };
}
// resolvers文件夹下的index.ts文件生成
function resolversIndex(output, category, prismaField, fields, len) {
let importIndex = '';
// console.log('resolversIndex--->', prismaField, '--', fields, '--', (category === MUTATION && prismaField === '' && fields === '') || len === 0)
if ((category === MUTATION && prismaField === '' && fields === '') || len === 0) {
importIndex = `export * from './Query'`;
}
else {
importIndex = `export * from './Query'
export * from './Mutation'`;
}
// 生成index.ts文件
const index = path_1.join(`${output}/resolvers`, 'index.ts');
fs_1.writeFileSync(index, importIndex);
}
// 生成上下文context.ts文件
function context(server, output, ptype, common) {
// 解析公共服务方法
let importPoclicy = '';
let importServer = '';
ptype
.split(',')
.filter(p => p !== '')
.forEach(p => {
const P = `P${util.initialUpperCase(p)}`;
importPoclicy += common ? `import { Prisma as ${P} } from '../${p}/prisma-client'\n` : `import { Prisma as ${P} } from './common/${p}/prisma-client'\n`;
importServer += ` p${p}: ${P}\n`;
});
const imports = importPoclicy !== '' ? importPoclicy : '';
const poclicy = importServer !== '' ? importServer : '';
const contextData = `import { Prisma } from './prisma-client'
${imports}
export interface Context {
token?: string
currentService: string
accountId?: string
p${server}: Prisma
${poclicy}
}`;
const cxt = path_1.join(output, 'context.ts');
fs_1.writeFileSync(cxt, contextData);
}
// 生成上下文schema.ts文件
function schema(output, server, types) {
let schemas = { importServer: '', serversgSchema: '', resolvers: '', typeDefs: '' };
let typeNameArr = [];
let imServer = '';
let gSchema = '';
let resolver = '';
let typeDef = '';
let len = 0;
// 判断当前自定义指令是否需要内嵌其它服务[暂支持一种查询后续陆续添加]
types.forEach(t => {
const queryLinks = t.directives.filter(q => q.name === 'QueryLink');
len = queryLinks.length;
queryLinks.forEach(q => {
typeNameArr.push(t.name);
schemas = Operation.queryLinkMethod(t.name, q);
imServer += schemas.importServer;
gSchema += schemas.serversgSchema;
resolver += schemas.resolvers;
typeDef += schemas.typeDefs;
});
});
const schemaData = len === 0 ? code.SCHEMACODE : code.schemaCode(server, imServer, typeDef, gSchema, resolver);
const cxt = path_1.join(output, 'schema.ts');
fs_1.writeFileSync(cxt, schemaData);
}
// 得到转换后的模型对象
function modelResolver(prismaPath) {
const config = modelSchema_1.readPrismaYml(prismaPath);
const model = modelSchema_1.findDatamodelAndComputeSchema(config.configPath, config.config);
return model;
}
// index.ts文件生成(开发时生成)
function index(server, ptype) {
// 解析公共服务方法
let importPoclicy = '';
let importServer = '';
ptype
.split(',')
.filter(p => p !== '')
.forEach(p => {
importPoclicy += `import { prisma as p${p} } from './generated/common/${p}/prisma-client'\n`;
importServer += `p${p},`;
});
const poclicy = importPoclicy !== '' ? importPoclicy : '';
const context = importServer !== '' ? `${importServer} p${server}, token, currentService: '${server}',accountId: ''` : `p${server},token, currentService: '${server}',accountId: ''`;
const file = path_1.join('./src', 'index.ts');
if (!fs_1.existsSync(file))
fs_1.writeFileSync(file, code.indexCode(server, poclicy, context));
}
//# sourceMappingURL=resolver.js.map