Socket
Socket
Sign inDemoInstall

tsrpc-cli

Package Overview
Dependencies
67
Maintainers
1
Versions
92
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.4 to 1.0.5

2

index.js
#!/usr/bin/env node
"use strict";function _interopDefault(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var glob=require("glob");require("colors");var minimist=_interopDefault(require("minimist")),tsbufferProtoGenerator=require("tsbuffer-proto-generator"),fs=require("fs"),path=require("path"),tsbuffer=require("tsbuffer"),ts=require("typescript");const i18n={welcome:"https://npmjs.com/tsrpc\n欢迎进入 TSRPC 实用工具 V${version}",help:'\n使用说明:\n\n tsrpc proto <options> 生成TSRPC Proto文件\n -i, --input <folder> 用来生成Proto的协议文件夹路径\n -o, --output <file> 输出的文件路径,不指定将直接输出到命令行\n -o XXX.ts 和 -o XXX.json 将对应输出两种不同的格式\n -c, --compatible <file> 兼容模式:要兼容的旧Proto文件的路径(默认同output)\n -n, --new 不兼容旧版,生成全新的Proto文件\n -u, --ugly 输出为可读性较差但体积更小压缩格式\n -v, --verbose 显示调试信息\n --ignore <glob> 从--input范围中要忽略的文件\n\n tsrpc api <options> 自动生成TSRPC API实现\n -i, --input <file> Proto文件的路径\n -o, --output <folder> 输出的API文件夹路径\n \n tsrpc encode <options> [exp] 编码JS表达式\n [exp] 要编码的值(JS表达式,例如"123" "new Uint8Array([1,2,3])")\n -p, --proto <file> 编码要使用的Proto文件\n -s, --schema <id> 编码要使用的SchemaID\n -i, --input <file> 输入为文件,不可与[exp]同用(文件内容为JS表达式)\n -o, --output <file> 输出的文件路径,不指定将直接输出到命令行\n -v, --verbose 显示调试信息\n \n tsrpc decode <options> [binstr] 解码二进制数据\n [binstr] 要解码的二进制数据的字符串表示,如"0F A2 E3 F2 D9"\n -p, --proto <file> 解码要使用的Proto文件\n -s, --schema <id> 解码要使用的SchemaID\n -i, --input <file> 输入为文件,不可与[binstr]同用\n -o, --output <file> 输出的文件路径,不指定将直接输出到命令行\n -v, --verbose 显示调试信息\n\n tsrpc validate <options> [exp] 验证JSON数据\n [exp] 要验证的值(JS表达式,例如"123" "new Uint8Array([1,2,3])")\n -p, --proto <file> 验证要使用的Proto文件\n -s, --schema <id> 验证要使用的SchemaID\n -i, --input <file> 输入为文件,不可与[exp]同用(文件内容为JS表达式)\n\n tsrpc show <file> 打印二进制文件内容\n'.trim(),example:'\n使用示例:\n\n tsrpc proto -i proto -o proto.ts\n\n tsrpc encode -p proto.ts -s a/b/c/TypeName -o buf.bin "{value: 1}"\n tsrpc decode -p proto.ts -s a/b/c/TypeName "01 0A 01"\n tsrpc validate -p proto.ts -s a/b/c/TypeName "{value: 1}"\n tsrpc show buf.bin\n'.trim(),errCmd:"命令格式有误,键入 tsrpc -h 以查看帮助。",missingParam:"缺少 ${param} 参数,键入 tsrpc -h 以查看更多信息。",inputMustBeFolder:"--input 参数应当为一个文件夹",protoSucc:"√ Proto已生成到:${output}",fileOpenError:"文件打开失败: ${file}",jsParsedError:"JS表达式解析失败: ${file}",protoParsedError:"旧Proto文件解析失败: ${file}",expParsedError:"表达式解析失败",or:"或",and:"和",encodeSucc:"√ 编码结果已生成到:${output}",decodeSucc:"√ 解码结果已生成到:${output}",apiSucc:"√ Api${apiName} 生成成功: ${apiPath}",validateSucc:"√ 验证通过",validateFail:"× 验证不通过: ${msg}",error:" 错误 ",helpGuide:"键入 tsrpc -h 查看更多帮助信息",compatibleError:"兼容旧Proto失败: \n\t|- ${innerError}"},i18n$1=i18n;require("node-json-color-stringify");let colorJson=e=>JSON.colorStringify(e,null,2);const version=require("./package.json").version,args=minimist(process.argv);let verbose=args.verbose||args.v;async function main(){2===args._.length&&(args.version||args.v)?console.log("TSBuffer "+version):args.h||args.help?showHelp():"proto"===args._[2]?await proto(args.input||args.i,args.output||args.o,args.compatible||args.c,args.ugly||args.u,args.new||args.n,args.ignore):"api"===args._[2]?await api(args.input||args.i,args.output||args.o):"encode"===args._[2]?encode(args.input||args.i,args._[3],args.output||args.o,args.proto||args.p,args.schema||args.s):"decode"===args._[2]?decode(args.proto||args.p,args.schema||args.s,args.input||args.i,args._[3],args.output||args.o):"validate"===args._[2]?validate(args.proto||args.p,args.schema||args.s,args.input||args.i,args._[3]):"show"===args._[2]?showBin():2===args._.length?(showLogo(),console.log(formatStr(i18n$1.welcome,{version:version}).green),console.log("\n"+i18n$1.example),console.log("\n"+i18n$1.helpGuide.yellow)):error(i18n$1.errCmd),process.exit(0)}function showLogo(){console.log(' \n88888888888 .d8888b. 8888888b. 8888888b. .d8888b. \n 888 d88P Y88b 888 Y88b 888 Y88b d88P Y88b \n 888 Y88b. 888 888 888 888 888 888 \n 888 "Y888b. 888 d88P 888 d88P 888 \n 888 "Y88b. 8888888P" 8888888P" 888 \n 888 "888 888 T88b 888 888 888 \n 888 Y88b d88P 888 T88b 888 Y88b d88P \n 888 "Y8888P" 888 T88b 888 "Y8888P" \n------------------------------------------------------------------------\n'.green)}function showHelp(){showLogo(),console.log(formatStr(i18n$1.welcome,{version:version}).green),console.log("\n"+i18n$1.help),console.log("\n"+i18n$1.example)}async function proto(input,output,compatible,ugly,newMode,ignore){if(input||(input="."),input=input.replace(/[\\\/]+$/,""),!fs.statSync(input).isDirectory())throw error(i18n$1.inputMustBeFolder);let oldProtoPath=compatible||output,oldProto;if(!newMode&&oldProtoPath)if(oldProtoPath.endsWith(".ts")){let e=fs.existsSync(oldProtoPath)&&fs.readFileSync(oldProtoPath,"utf-8");if(e){let r=e.match(/[\s\S]*:\s*ServiceProto<ServiceType>\s*=\s*(\{[\s\S]+\});?\s*/);if(!r)throw console.error(`Not invalid proto ts file: ${oldProtoPath}`),error(i18n$1.compatibleError);try{oldProto=JSON.parse(r[1])}catch(e){throw error(i18n$1.compatibleError,{innerError:e.message})}}}else try{if(oldProto=loadServiceProto(oldProtoPath),!oldProto&&compatible)throw new Error(formatStr(i18n$1.fileOpenError,{file:path.resolve(oldProtoPath)}))}catch(e){throw error(i18n$1.compatibleError,{innerError:e.message})}let fileList=glob.sync(input+"/**/{Ptl,Msg}*.ts",{ignore:ignore}).map(e=>path.relative(input,e).replace(/\\/g,"/")),originalCwd=process.cwd();process.chdir(input);let services=[];const exp=/^(.*\/)?(Ptl|Msg)([^\.\/\\]+)\.ts$/;let typeProto=await new tsbufferProtoGenerator.TSBufferProtoGenerator({verbose:verbose}).generate(fileList,{compatibleResult:oldProto?oldProto.types:void 0,filter:e=>{let r=e.path.replace(/\\/g,"/"),o=r.match(exp);if(/(\/|^)__/.test(r))return!1;if(!o)throw new Error("Error path (not Ptl nor Msg): "+e.path);return"Ptl"===o[2]?e.name==="Req"+o[3]||e.name==="Res"+o[3]:e.name==="Msg"+o[3]}});for(let filepath of fileList){filepath=filepath.replace(/^\.\//,"");let match=filepath.match(exp),typePath=filepath.replace(/\.ts$/,""),src=fs.readFileSync(filepath).toString(),compileResult=ts.transpileModule(src,{compilerOptions:{module:ts.ModuleKind.CommonJS,target:ts.ScriptTarget.ES2015}}),mod={};eval(`(function(exports){${compileResult.outputText}})`)(mod);let conf=mod?mod.conf:void 0;if("Ptl"===match[2]){let e=typePath+"/Req"+match[3],r=typePath+"/Res"+match[3];typeProto[e]&&typeProto[r]?services.push({id:services.length,name:(match[1]||"")+match[3],type:"api",req:e,res:r,conf:conf}):(!typeProto[e]&&console.warn("Missing Req: "+typePath),!typeProto[r]&&console.warn("Missing Res: "+typePath))}else{let e=typePath+"/Msg"+match[3];typeProto[e]?services.push({id:services.length,name:(match[1]||"")+match[3],type:"msg",msg:e,conf:conf}):console.warn("Missing Msg: "+typePath)}}let encodeIds=tsbufferProtoGenerator.EncodeIdUtil.genEncodeIds(services.map(e=>e.name),oldProto?oldProto.services.map(e=>({key:e.name,id:e.id})):void 0);for(let e of encodeIds)services.find(r=>r.name===e.key).id=e.id;let proto={services:services,types:typeProto};if(output){if(output.endsWith(".ts")){let e={},r=[],o=[],t={},n=e=>{for(;t[e];){let r=e.match(/(^.*)\_(\d+)$/);if(r){let o=parseInt(r[2])+1;e=r[1]+"_"+o}else e+="_1"}return t[e]=1,e},i=(r,o)=>{let t=o.map(e=>n(e));return e[r]=o.map((e,r)=>({srcName:e,asName:t[r]&&t[r]!==e?t[r]:void 0})),t};for(let e of services){let t=e.name.replace(/\\/g,"/").match(/^(.*\/)*([^\/]+)$/);if(!t)throw new Error(`Invalid svc name: ${e.name}`);let n=t[2],s=path.relative(path.dirname(path.resolve(originalCwd,output)),(t[1]||"")+("api"===e.type?"Ptl":"Msg")+n).replace(/\\/g,"/");if(s.startsWith(".")||(s="./"+s),"api"===e.type){let o=i(s,["Req"+n,"Res"+n]);r.push({name:e.name,importPath:s,req:o[0],res:o[1]})}else{let r=i(s,["Msg"+n]);o.push({name:e.name,importPath:s,msg:r[0]})}}let s=Object.entries(e).map(e=>`import { ${e[1].map(e=>e.asName?`${e.srcName} as ${e.asName}`:e.srcName).join(", ")} } from '${e[0]}'`).join("\n"),a=r.map(e=>` ${JSON.stringify(e.name)}: ${e.req}`).join(",\n"),p=r.map(e=>` ${JSON.stringify(e.name)}: ${e.res}`).join(",\n"),l=o.map(e=>` ${JSON.stringify(e.name)}: ${e.msg}`).join(",\n"),c=`\nimport { ServiceProto } from 'tsrpc-proto';\n${s}\n\nexport interface ServiceType {\n req: {\n${a}\n },\n res: {\n${p}\n },\n msg: {\n${l}\n }\n}\n\nexport const serviceProto: ServiceProto<ServiceType> = ${JSON.stringify(proto,null,4)};\n`.trim();process.chdir(originalCwd),fs.writeFileSync(output,c)}else process.chdir(originalCwd),fs.writeFileSync(output,ugly?JSON.stringify(proto):JSON.stringify(proto,null,2));console.log(formatStr(i18n$1.protoSucc,{output:path.resolve(output)}).green)}else console.log(colorJson(proto))}async function api(e,r){if(!e)throw error(i18n$1.missingParam,{param:"input"});if(!r)throw error(i18n$1.missingParam,{param:"output"});let o=loadServiceProto(e);if(!o)throw error(i18n$1.protoParsedError,{file:e});let t=o.services.filter(e=>"api"===e.type);for(let o of t){let t=o.name.match(/\w+$/)[0],n=path.join(r,o.name.substr(0,o.name.length-t.length)),i=path.join(n,`Api${t}.ts`),s=path.join(path.dirname(e),o.req.replace(/Ptl\w+\/Req\w+$/,""));fs.existsSync(i)||(fs.existsSync(n)||fs.mkdirSync(n,{recursive:!0}),fs.writeFileSync(i,`\nimport { ApiCall } from "tsrpc";\nimport { Req${t}, Res${t} } from "${path.relative(n,s).replace(/\\/g,"/")}/Ptl${t}";\n\nexport async function Api${t}(call: ApiCall<Req${t}, Res${t}>) {\n // TODO\n call.error('To be implemented');\n} \n `.trim(),{encoding:"utf-8"}),console.log(formatStr(i18n$1.apiSucc,{apiPath:i,apiName:t}).green))}}function loadServiceProto(e){let r,o;try{o=fs.readFileSync(e).toString()}catch(e){return}try{if(e.endsWith(".ts")){let t=o.match(/export const serviceProto: ServiceProto<ServiceType> = (\{[\s\S]+\});/);if(!t)throw new Error(formatStr(i18n$1.protoParsedError,{file:path.resolve(e)}));r=JSON.parse(t[1])}else r={services:[],types:JSON.parse(o)}}catch(r){throw new Error(formatStr(i18n$1.protoParsedError,{file:path.resolve(e)}))}return r}function encode(input,exp,output,proto,schemaId){let parsedProto=parseProtoAndSchema(proto,schemaId),inputValue;if(input){let fileContent;try{fileContent=fs.readFileSync(input).toString()}catch(e){throw error(i18n$1.fileOpenError,{file:path.resolve(input)})}try{inputValue=eval(fileContent)}catch(e){throw error(i18n$1.jsParsedError,{file:path.resolve(input)})}}else{if(!exp)throw error(i18n$1.missingParam,{param:`--input ${i18n$1.or} [expression]`});try{inputValue=eval(`()=>(${exp})`)()}catch(e){throw verbose&&(console.log("exp",exp),console.error(e)),error(i18n$1.expParsedError)}}try{verbose&&console.log("inputValue",inputValue);let e=new tsbuffer.TSBuffer(parsedProto.proto).encode(inputValue,parsedProto.schemaId);console.log("编码长度:"+e.byteLength),output?(fs.writeFileSync(output,e),console.log(formatStr(i18n$1.encodeSucc,{output:path.resolve(output)}).green)):console.log(buf2Hex(e).yellow)}catch(e){throw error("编码失败。\n "+e.message)}}function decode(e,r,o,t,n){let i,s,a=parseProtoAndSchema(e,r);if(o)try{i=fs.readFileSync(o)}catch(e){throw verbose&&console.error(e),error(i18n$1.fileOpenError,{file:path.resolve(o)})}else{if(!t)throw error(i18n$1.missingParam,{param:`--input ${i18n$1.or} [binstr]`});i=hex2Bin(t)}try{s=new tsbuffer.TSBuffer(a.proto).decode(new Uint8Array(i),a.schemaId)}catch(e){throw error("解码失败:\n "+e.message)}n?(fs.writeFileSync(n,JSON.stringify(s,null,2)),console.log(formatStr(i18n$1.decodeSucc,{output:n}).green)):console.log(colorJson(s))}function validate(proto,schemaId,input,expression){let parsedProto=parseProtoAndSchema(proto,schemaId),inputValue;if(input){let fileContent;try{fileContent=fs.readFileSync(input).toString()}catch(e){throw error(i18n$1.fileOpenError,{file:path.resolve(input)})}try{inputValue=eval(fileContent)}catch(e){throw error(i18n$1.jsParsedError,{file:path.resolve(input)})}}else{if(!expression)throw error(i18n$1.missingParam,{param:`--input ${i18n$1.or} [expression]`});try{inputValue=eval(`()=>(${expression})`)()}catch(e){throw verbose&&(console.log("exp",expression),console.error(e)),error(i18n$1.expParsedError)}}let vRes=new tsbuffer.TSBuffer(parsedProto.proto).validate(inputValue,parsedProto.schemaId);if(vRes.isSucc)console.log(i18n$1.validateSucc.green);else{let e=vRes.originalError;error(i18n$1.validateFail,{msg:vRes.originalError.message})}}function error(e,r){return r&&(e=formatStr(e,r)),console.error(i18n$1.error.bgRed.white,e.red),process.exit(-1),new Error}function formatStr(e,r){for(let o in r)for(;e.indexOf(o)>-1;)e=e.replace(`\${${o}}`,r[o]);return e}function buf2Hex(e){let r=[];return e.forEach(e=>{let o=e.toString(16).toUpperCase();1===o.length&&(o="0"+o),r.push(o)}),r.join(" ")}function hex2Bin(e){return Buffer.from(new Uint8Array(e.trim().split(/\s+/).map(e=>parseInt("0x"+e))))}function showBin(){if(args._.length<4)throw error(i18n$1.missingParam,{param:"<file>"});let e;try{e=new Uint8Array(fs.readFileSync(args._[3])),console.log("编码长度:"+e.byteLength)}catch(e){throw verbose&&console.error(e),error(i18n$1.fileOpenError,{file:path.resolve(args._[3])})}console.log(buf2Hex(e).yellow)}function parseProtoAndSchema(e,r){if(!e)throw error(i18n$1.missingParam,{param:"--proto"}),new Error;if(!r)throw error(i18n$1.missingParam,{param:"--schema"}),new Error;let o;try{o=loadServiceProto(e)}catch(e){throw error(e.message)}if(!o)throw error(i18n$1.fileOpenError,{file:path.resolve(e)});return{proto:o.types,schemaId:r}}main();
"use strict";function _interopDefault(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var glob=require("glob");require("colors");var minimist=_interopDefault(require("minimist")),tsbufferProtoGenerator=require("tsbuffer-proto-generator"),fs=require("fs"),path=require("path"),tsbuffer=require("tsbuffer"),ts=require("typescript");const i18n={welcome:"https://npmjs.com/tsrpc\n欢迎进入 TSRPC 实用工具 V${version}",help:'\n使用说明:\n\n tsrpc proto <options> 生成TSRPC Proto文件\n -i, --input <folder> 用来生成Proto的协议文件夹路径\n -o, --output <file> 输出的文件路径,不指定将直接输出到命令行\n -o XXX.ts 和 -o XXX.json 将对应输出两种不同的格式\n -c, --compatible <file> 兼容模式:要兼容的旧Proto文件的路径(默认同output)\n -n, --new 不兼容旧版,生成全新的Proto文件\n -u, --ugly 输出为可读性较差但体积更小压缩格式\n -v, --verbose 显示调试信息\n --ignore <glob> 从--input范围中要忽略的文件\n\n tsrpc api <options> 自动生成TSRPC API实现\n -i, --input <file> Proto文件的路径\n -o, --output <folder> 输出的API文件夹路径\n \n tsrpc encode <options> [exp] 编码JS表达式\n [exp] 要编码的值(JS表达式,例如"123" "new Uint8Array([1,2,3])")\n -p, --proto <file> 编码要使用的Proto文件\n -s, --schema <id> 编码要使用的SchemaID\n -i, --input <file> 输入为文件,不可与[exp]同用(文件内容为JS表达式)\n -o, --output <file> 输出的文件路径,不指定将直接输出到命令行\n -v, --verbose 显示调试信息\n \n tsrpc decode <options> [binstr] 解码二进制数据\n [binstr] 要解码的二进制数据的字符串表示,如"0F A2 E3 F2 D9"\n -p, --proto <file> 解码要使用的Proto文件\n -s, --schema <id> 解码要使用的SchemaID\n -i, --input <file> 输入为文件,不可与[binstr]同用\n -o, --output <file> 输出的文件路径,不指定将直接输出到命令行\n -v, --verbose 显示调试信息\n\n tsrpc validate <options> [exp] 验证JSON数据\n [exp] 要验证的值(JS表达式,例如"123" "new Uint8Array([1,2,3])")\n -p, --proto <file> 验证要使用的Proto文件\n -s, --schema <id> 验证要使用的SchemaID\n -i, --input <file> 输入为文件,不可与[exp]同用(文件内容为JS表达式)\n\n tsrpc show <file> 打印二进制文件内容\n'.trim(),example:'\n使用示例:\n\n tsrpc proto -i proto -o proto.ts\n\n tsrpc encode -p proto.ts -s a/b/c/TypeName -o buf.bin "{value: 1}"\n tsrpc decode -p proto.ts -s a/b/c/TypeName "01 0A 01"\n tsrpc validate -p proto.ts -s a/b/c/TypeName "{value: 1}"\n tsrpc show buf.bin\n'.trim(),errCmd:"命令格式有误,键入 tsrpc -h 以查看帮助。",missingParam:"缺少 ${param} 参数,键入 tsrpc -h 以查看更多信息。",inputMustBeFolder:"--input 参数应当为一个文件夹",protoSucc:"√ Proto已生成到:${output}",fileOpenError:"文件打开失败: ${file}",jsParsedError:"JS表达式解析失败: ${file}",protoParsedError:"旧Proto文件解析失败: ${file}",expParsedError:"表达式解析失败",or:"或",and:"和",encodeSucc:"√ 编码结果已生成到:${output}",decodeSucc:"√ 解码结果已生成到:${output}",apiSucc:"√ Api${apiName} 生成成功: ${apiPath}",validateSucc:"√ 验证通过",validateFail:"× 验证不通过: ${msg}",error:" 错误 ",helpGuide:"键入 tsrpc -h 查看更多帮助信息",compatibleError:"兼容旧Proto失败: \n\t|- ${innerError}"},i18n$1=i18n;require("node-json-color-stringify");let colorJson=e=>JSON.colorStringify(e,null,2);const version=require("./package.json").version,args=minimist(process.argv);let verbose=args.verbose||args.v;async function main(){2===args._.length&&(args.version||args.v)?console.log("TSBuffer "+version):args.h||args.help?showHelp():"proto"===args._[2]?await proto(args.input||args.i,args.output||args.o,args.compatible||args.c,args.ugly||args.u,args.new||args.n,args.ignore):"api"===args._[2]?await api(args.input||args.i,args.output||args.o):"encode"===args._[2]?encode(args.input||args.i,args._[3],args.output||args.o,args.proto||args.p,args.schema||args.s):"decode"===args._[2]?decode(args.proto||args.p,args.schema||args.s,args.input||args.i,args._[3],args.output||args.o):"validate"===args._[2]?validate(args.proto||args.p,args.schema||args.s,args.input||args.i,args._[3]):"show"===args._[2]?showBin():2===args._.length?(showLogo(),console.log(formatStr(i18n$1.welcome,{version:version}).green),console.log("\n"+i18n$1.example),console.log("\n"+i18n$1.helpGuide.yellow)):error(i18n$1.errCmd),process.exit(0)}function showLogo(){console.log(' \n88888888888 .d8888b. 8888888b. 8888888b. .d8888b. \n 888 d88P Y88b 888 Y88b 888 Y88b d88P Y88b \n 888 Y88b. 888 888 888 888 888 888 \n 888 "Y888b. 888 d88P 888 d88P 888 \n 888 "Y88b. 8888888P" 8888888P" 888 \n 888 "888 888 T88b 888 888 888 \n 888 Y88b d88P 888 T88b 888 Y88b d88P \n 888 "Y8888P" 888 T88b 888 "Y8888P" \n------------------------------------------------------------------------\n'.green)}function showHelp(){showLogo(),console.log(formatStr(i18n$1.welcome,{version:version}).green),console.log("\n"+i18n$1.help),console.log("\n"+i18n$1.example)}async function proto(input,output,compatible,ugly,newMode,ignore){if(input||(input="."),input=input.replace(/[\\\/]+$/,""),!fs.statSync(input).isDirectory())throw error(i18n$1.inputMustBeFolder);let oldProtoPath=compatible||output,oldProto;if(!newMode&&oldProtoPath)if(oldProtoPath.endsWith(".ts")){let e=fs.existsSync(oldProtoPath)&&fs.readFileSync(oldProtoPath,"utf-8");if(e){let r=e.match(/[\s\S]*:\s*ServiceProto<ServiceType>\s*=\s*(\{[\s\S]+\});?\s*/);if(!r)throw console.error(`Not invalid proto ts file: ${oldProtoPath}`),error(i18n$1.compatibleError);try{oldProto=JSON.parse(r[1])}catch(e){throw error(i18n$1.compatibleError,{innerError:e.message})}}}else try{if(oldProto=loadServiceProto(oldProtoPath),!oldProto&&compatible)throw new Error(formatStr(i18n$1.fileOpenError,{file:path.resolve(oldProtoPath)}))}catch(e){throw error(i18n$1.compatibleError,{innerError:e.message})}let fileList=glob.sync(input+"/**/{Ptl,Msg}*.ts",{ignore:ignore}).map(e=>path.relative(input,e).replace(/\\/g,"/")),originalCwd=process.cwd();process.chdir(input);let services=[];const exp=/^(.*\/)?(Ptl|Msg)([^\.\/\\]+)\.ts$/;let typeProto=await new tsbufferProtoGenerator.TSBufferProtoGenerator({verbose:verbose}).generate(fileList,{compatibleResult:oldProto?oldProto.types:void 0,filter:e=>{let r=e.path.replace(/\\/g,"/"),o=r.match(exp);if(/(\/|^)__/.test(r))return!1;if(!o)throw new Error("Error path (not Ptl nor Msg): "+e.path);return"Ptl"===o[2]?e.name==="Req"+o[3]||e.name==="Res"+o[3]:e.name==="Msg"+o[3]}});for(let filepath of fileList){filepath=filepath.replace(/^\.\//,"");let match=filepath.match(exp),typePath=filepath.replace(/\.ts$/,""),src=fs.readFileSync(filepath).toString(),compileResult=ts.transpileModule(src,{compilerOptions:{module:ts.ModuleKind.CommonJS,target:ts.ScriptTarget.ES2015}}),mod={};eval(`(function(exports){${compileResult.outputText}})`)(mod);let conf=mod?mod.conf:void 0;if("Ptl"===match[2]){let e=typePath+"/Req"+match[3],r=typePath+"/Res"+match[3];typeProto[e]&&typeProto[r]?services.push({id:services.length,name:(match[1]||"")+match[3],type:"api",req:e,res:r,conf:conf}):(!typeProto[e]&&console.warn("Missing Req: "+typePath),!typeProto[r]&&console.warn("Missing Res: "+typePath))}else{let e=typePath+"/Msg"+match[3];typeProto[e]?services.push({id:services.length,name:(match[1]||"")+match[3],type:"msg",msg:e,conf:conf}):console.warn("Missing Msg: "+typePath)}}let encodeIds=tsbufferProtoGenerator.EncodeIdUtil.genEncodeIds(services.map(e=>e.name),oldProto?oldProto.services.map(e=>({key:e.name,id:e.id})):void 0);for(let e of encodeIds)services.find(r=>r.name===e.key).id=e.id;let proto={services:services,types:typeProto};if(output){if(output.endsWith(".ts")){let e={},r=[],o=[],t={},n=e=>{for(;t[e];){let r=e.match(/(^.*)\_(\d+)$/);if(r){let o=parseInt(r[2])+1;e=r[1]+"_"+o}else e+="_1"}return t[e]=1,e},i=(r,o)=>{let t=o.map(e=>n(e));return e[r]=o.map((e,r)=>({srcName:e,asName:t[r]&&t[r]!==e?t[r]:void 0})),t};for(let e of services){let t=e.name.replace(/\\/g,"/").match(/^(.*\/)*([^\/]+)$/);if(!t)throw new Error(`Invalid svc name: ${e.name}`);let n=t[2],s=path.relative(path.dirname(path.resolve(originalCwd,output)),(t[1]||"")+("api"===e.type?"Ptl":"Msg")+n).replace(/\\/g,"/");if(s.startsWith(".")||(s="./"+s),"api"===e.type){let o=i(s,["Req"+n,"Res"+n]);r.push({name:e.name,importPath:s,req:o[0],res:o[1]})}else{let r=i(s,["Msg"+n]);o.push({name:e.name,importPath:s,msg:r[0]})}}let s=Object.entries(e).map(e=>`import { ${e[1].map(e=>e.asName?`${e.srcName} as ${e.asName}`:e.srcName).join(", ")} } from '${e[0]}'`).join("\n"),a=r.map(e=>` ${JSON.stringify(e.name)}: ${e.req}`).join(",\n"),p=r.map(e=>` ${JSON.stringify(e.name)}: ${e.res}`).join(",\n"),l=o.map(e=>` ${JSON.stringify(e.name)}: ${e.msg}`).join(",\n"),c=`\nimport { ServiceProto } from 'tsrpc-proto';\n${s}\n\nexport interface ServiceType {\n req: {\n${a}\n },\n res: {\n${p}\n },\n msg: {\n${l}\n }\n}\n\nexport const serviceProto: ServiceProto<ServiceType> = ${JSON.stringify(proto,null,4)};\n`.trim();process.chdir(originalCwd),fs.writeFileSync(output,c)}else process.chdir(originalCwd),fs.writeFileSync(output,ugly?JSON.stringify(proto):JSON.stringify(proto,null,2));console.log(formatStr(i18n$1.protoSucc,{output:path.resolve(output)}).green)}else console.log(colorJson(proto))}async function api(e,r){if(!e)throw error(i18n$1.missingParam,{param:"input"});if(!r)throw error(i18n$1.missingParam,{param:"output"});let o=loadServiceProto(e);if(!o)throw error(i18n$1.protoParsedError,{file:e});let t=o.services.filter(e=>"api"===e.type);for(let o of t){let t=o.name.match(/\w+$/)[0],n=path.join(r,o.name.substr(0,o.name.length-t.length)),i=path.join(n,`Api${t}.ts`),s=path.join(path.dirname(e),o.req.replace(/Ptl\w+\/Req\w+$/,""));fs.existsSync(i)||(fs.existsSync(n)||fs.mkdirSync(n,{recursive:!0}),fs.writeFileSync(i,`\nimport { ApiCall } from "tsrpc";\nimport { Req${t}, Res${t} } from "${path.relative(n,s).replace(/\\/g,"/")}/Ptl${t}";\n\nexport async function Api${t}(call: ApiCall<Req${t}, Res${t}>) {\n \n} \n `.trim(),{encoding:"utf-8"}),console.log(formatStr(i18n$1.apiSucc,{apiPath:i,apiName:t}).green))}}function loadServiceProto(e){let r,o;try{o=fs.readFileSync(e).toString()}catch(e){return}try{if(e.endsWith(".ts")){let t=o.match(/export const serviceProto: ServiceProto<ServiceType> = (\{[\s\S]+\});/);if(!t)throw new Error(formatStr(i18n$1.protoParsedError,{file:path.resolve(e)}));r=JSON.parse(t[1])}else r={services:[],types:JSON.parse(o)}}catch(r){throw new Error(formatStr(i18n$1.protoParsedError,{file:path.resolve(e)}))}return r}function encode(input,exp,output,proto,schemaId){let parsedProto=parseProtoAndSchema(proto,schemaId),inputValue;if(input){let fileContent;try{fileContent=fs.readFileSync(input).toString()}catch(e){throw error(i18n$1.fileOpenError,{file:path.resolve(input)})}try{inputValue=eval(fileContent)}catch(e){throw error(i18n$1.jsParsedError,{file:path.resolve(input)})}}else{if(!exp)throw error(i18n$1.missingParam,{param:`--input ${i18n$1.or} [expression]`});try{inputValue=eval(`()=>(${exp})`)()}catch(e){throw verbose&&(console.log("exp",exp),console.error(e)),error(i18n$1.expParsedError)}}try{verbose&&console.log("inputValue",inputValue);let e=new tsbuffer.TSBuffer(parsedProto.proto).encode(inputValue,parsedProto.schemaId);console.log("编码长度:"+e.byteLength),output?(fs.writeFileSync(output,e),console.log(formatStr(i18n$1.encodeSucc,{output:path.resolve(output)}).green)):console.log(buf2Hex(e).yellow)}catch(e){throw error("编码失败。\n "+e.message)}}function decode(e,r,o,t,n){let i,s,a=parseProtoAndSchema(e,r);if(o)try{i=fs.readFileSync(o)}catch(e){throw verbose&&console.error(e),error(i18n$1.fileOpenError,{file:path.resolve(o)})}else{if(!t)throw error(i18n$1.missingParam,{param:`--input ${i18n$1.or} [binstr]`});i=hex2Bin(t)}try{s=new tsbuffer.TSBuffer(a.proto).decode(new Uint8Array(i),a.schemaId)}catch(e){throw error("解码失败:\n "+e.message)}n?(fs.writeFileSync(n,JSON.stringify(s,null,2)),console.log(formatStr(i18n$1.decodeSucc,{output:n}).green)):console.log(colorJson(s))}function validate(proto,schemaId,input,expression){let parsedProto=parseProtoAndSchema(proto,schemaId),inputValue;if(input){let fileContent;try{fileContent=fs.readFileSync(input).toString()}catch(e){throw error(i18n$1.fileOpenError,{file:path.resolve(input)})}try{inputValue=eval(fileContent)}catch(e){throw error(i18n$1.jsParsedError,{file:path.resolve(input)})}}else{if(!expression)throw error(i18n$1.missingParam,{param:`--input ${i18n$1.or} [expression]`});try{inputValue=eval(`()=>(${expression})`)()}catch(e){throw verbose&&(console.log("exp",expression),console.error(e)),error(i18n$1.expParsedError)}}let vRes=new tsbuffer.TSBuffer(parsedProto.proto).validate(inputValue,parsedProto.schemaId);if(vRes.isSucc)console.log(i18n$1.validateSucc.green);else{let e=vRes.originalError;error(i18n$1.validateFail,{msg:vRes.originalError.message})}}function error(e,r){return r&&(e=formatStr(e,r)),console.error(i18n$1.error.bgRed.white,e.red),process.exit(-1),new Error}function formatStr(e,r){for(let o in r)for(;e.indexOf(o)>-1;)e=e.replace(`\${${o}}`,r[o]);return e}function buf2Hex(e){let r=[];return e.forEach(e=>{let o=e.toString(16).toUpperCase();1===o.length&&(o="0"+o),r.push(o)}),r.join(" ")}function hex2Bin(e){return Buffer.from(new Uint8Array(e.trim().split(/\s+/).map(e=>parseInt("0x"+e))))}function showBin(){if(args._.length<4)throw error(i18n$1.missingParam,{param:"<file>"});let e;try{e=new Uint8Array(fs.readFileSync(args._[3])),console.log("编码长度:"+e.byteLength)}catch(e){throw verbose&&console.error(e),error(i18n$1.fileOpenError,{file:path.resolve(args._[3])})}console.log(buf2Hex(e).yellow)}function parseProtoAndSchema(e,r){if(!e)throw error(i18n$1.missingParam,{param:"--proto"}),new Error;if(!r)throw error(i18n$1.missingParam,{param:"--schema"}),new Error;let o;try{o=loadServiceProto(e)}catch(e){throw error(e.message)}if(!o)throw error(i18n$1.fileOpenError,{file:path.resolve(e)});return{proto:o.types,schemaId:r}}main();
{
"name": "tsrpc-cli",
"version": "1.0.4",
"version": "1.0.5",
"description": "TSRPC CLI Tools",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc