UNPKG

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
"use strict"; //指令解析模块 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