proto2tsapi v1.1.8
用于把 proto 文件转换成 Typescript 的 api 文件
- 先把需要转换的 proto 文件确定好
- 依次遍历 proto 文件,然后转换成 ts 文件
注意事项:目前仅支持单个 proto 文件内存在单个 service,如单个 proto 文件存在多个 service,输出的 service 名称将会是最后一个 service 的名称
基于proto2api修改的 npm 包,在 proto2api 基础上拆分类型文件和 api 文件,将格式修改为自己需要的内容。
新版本特性
2024-03-14 v1.1.8: 更新了 config 文件对 depPath 和 protoDir 的支持
{
"files": {
...
},
"output": "./src/api",
"ignore": "google|swagger",
"protoDir": "./proto/", // 设置读取proto的根路径
"depPath": "./proto/" // 设置读取proto时依赖包的路径
}
2023-10-13 v1.1.7:customVariate 新增了文件名入参
interface ICustomVariateParams {
name: string;
comment?: string;
url: string;
redirectUrl?: string;
method: "get" | "post" | "put" | "patch" | "delete";
res: string;
req: string;
pkgName: string;
srvName: string;
fileName: string; // new!
}
const METHOD_NAME = (params: ICustomVariateParams) => {
const { pkgName, srvName, name, fileName } = params;
return `${fileName}/${pkgName}.${srvName}/${name}`;
};
module.exports = { METHOD_NAME };
2023-10-09 v1.1.6:修复互相依赖情况下的报错导致的中断
2023-7-28 v1.1.5:导出的 apiName 会自动带/
2023-7-28 v1.1.4:新增 excel 导出 API 的功能,如有需要请配置 config.expApiPath 路径
{
"files": {
"./": [
"example.proto"
]
},
...
"expApiPath":"./apiExport/apiExport.xlsx",
...
}
2023-3-10 v1.1.3:删除多余的 console.log
2023-3-10 v1.1.2:
- 更改了 enum 的转换方式,现在能正常转换成对应的数值,支持 proto 内断连的 enum 数值了。参考如下:
// 现在默认不会转换成旧版本的字符串值了,如有需要请在配置文件内设置 transEnum2String:true
export enum YesOrNo {
// 否
No = 0,
// 是
Yes = 1,
}
export enum Status {
// 草稿
Draft = 0,
// 已完成
Done = 3,
// 未提交
Todo = 4,
}
- 新增了自定义变量的功能,现在可以通过自定义变量插入模板代码中的任意部位。注意!!!模板代码使用自定义变量时需以$符号开始和结尾。 参考如下:
// proto2tsapi.json 在配置文件内新增了customVariate配置,接收自定义变量的文件路径
{
"files": {
"./": [
"example.proto"
]
},
"output": "./src/api/example",
"ignore": "google|swagger",
"FORMAT_URL_METHOD": "./formatUrlMethod.ts", // 此变量依然保留,以兼容旧版本
"customVariate": "./customVariate.ts", // 现在可以通过使用自定义变量来实现FORMAT_URL_METHOD的功能
"transEnum2String":false, // 如需转换成key值字符串的enum请设置成true
"defaultTemplate": [
"$COMMENT",
"export const $API_NAME = ($REQ_KEY: Types.$REQ_TYPE) => {",
"return request<RspStructure<Types.$RSP_TYPE>>({",
"url:'$FORMAT_URL_METHOD',",
"method: '$API_METHOD',",
"$REQ_KEY,",
"} as AxiosConfig<Types.$REQ_TYPE, Types.$REQ_TYPE>);",
"};"
"// $METHOD_NAME1$" // 使用自定义变量请以$开头和结尾,根据下面的文件内容配置,这里的结果会转换成 // 13
],
...
}
// customVariate.ts 新增的[自定义变量格式化函数]文件内
interface ApiFunction {
name: string;
comment?: string;
req: PropertyType;
url: string;
redirectUrl?: string;
res: PropertyType;
method: "get" | "post" | "put" | "patch" | "delete";
}
interface ICustomVariateParams extends Omit<ApiFunction, "req" | "res"> {
res: string;
req: string;
pkgName: string;
srvName: string;
}
interface ICustomVariate {
[k: string]: (parms: ICustomVariateParams) => string;
}
const METHOD_NAME = (p: ICustomVariate) => {
return p.req;
};
const METHOD_NAME1 = () => {
return "13";
};
const request = () => {
return "6666";
};
// 自定义变量名可以自己取,但是建议与模板内其他变量和代码段字符区分开来,推荐全大写的下划线写法
module.exports = { METHOD_NAME, METHOD_NAME1, request };
2022-11-29 v1.1.1:
- 修复了 customTemplate 和 templateConfig 匹配不上的问题,现在可以正常使用 customTemplate 了。
2022-9-02 v1.1.0:
新增了 printRoot 配置项,值为 Boolean,可在项目根目录输出解析 proto 文件生成的 root 对象的 json 文件,非必填;
新增了预处理规则,pretreatRules 配置项,可用于替换 proto 文件内的部分内容,解决一些不兼容的语法问题
新增了 proto3 中配置了 validate 规则的类型输出支持,现在可以在配置了 validate 规则的 proto 文件中区分是否必填项;※默认所有字段均为可选※,只有配置了 validate 选项的字段会输出必填项的类型;参考如下:
config 文件:
"pretreatRules": { // 用于替换proto文件内的部分匹配内容,如配置了此项,会使用此项规则修改后的proto文件进行转换;不会修改原proto文件; 非必填项
"./proto/example/example.proto": [ // key名是配置的路径,可配置多个规则,均会应用到该文件上
{
"searchValue": "{ in: [ \\\"未处理\\\", \\\"已处理\\\" ] }", // 被替代的内容,注意:此内容是匹配JSON.stringify后的文本信息,按照json的规则,对特殊的符号匹配需进行转义,例如 "" 和 \ 等等;
"replaceValue": "0" // 需要替换成的内容
}
],
"./proto/hello.proto":[] // 可为多个文件配置多个规则
}
proto 文件:
import "validate.proto";
message Example {
uint64 id = 1; // 这种默认会转换成可选项的类型
string username = 1 [(validate.rules).string.min_len = 2]; // 这种配置了validate.rules的会转换成必填项的类型
string status = 4 [(validate.rules).string = { in: [ "未处理", "已处理" ] }]; // 这种配合插件使用的情况无法解析,会报错,需配合新增的pretreatRules配置使用
}
转换后的 types 文件:
export interface Example {
todo_id?: string;
username: string;
status: string; // 需配置pretreatRules解决语法问题,否则会报错,后面的内容都不会被转换
}
2022-8-31 v1.0.6:
- 修复了生产多个文件的 api 时,$API_URL变量中自动拼接的serviceName只为最后一个的bug,现在已废弃$API_URL 变量;
- 新增了$PKG_NAME和$SRV_NAME 两个变量,用于在 FORMAT_URL_METHOD 的格式化函数中使用
- 修复了配置 files 里的*全选项时,默认生成根目录下所有 proto 文件的 bug,现在能正常按 files 配置里的文件夹路径单个文件夹生效了
- 修复了部分非必填配置项如不存在仍然报错的 bug,修复的配置项如下:REQ_KEY、templateConfig、customTemplate
快速开始
npm install -g proto2tsapi
cd proto2api
proto2tsapi -c examples/config.json
命令行说明
Usage: proto2tsapi [options]
Convert proto file to api file
Options:
Options:
-V, --version output the version number
--debug load code with ts-node for debug
-c, --config <path> config.json path
--depPath <type> the address of the external dependency proto library.
eq: /common/proto3 (default: "")
-h, --help display help for command
配置文件
参考配置项如下
{
"files": {
// 此处配置需转换的proto文件的路径,key是路径,value是文件名的数组集合;**必填项**
"./proto/examples": ["hello.proto"],
"./proto": [
"*" // 如果数组的首项是 * ,则会转换该文件夹下的所有proto文件
]
},
"output": "./dist", // 输出文件的路径; **必填项**
"printRoot": false, // 可在项目根目录输出解析proto文件生成的root对象的json文件; 非必填
"ignore": "google|swagger", // proto文件可被忽略的部分,例如"google|swagger" , 可参考proto2api; 非必填
"FORMAT_URL_METHOD": "./formatUrlMethod.ts", // 配置格式化函数的文件路径,需返回字符串;非必填
"REQ_KEY": {
// 配置不同请求方式下,请求参数的key名,将会作为变量用在生成api代码的片段上;默认值为data; 非必填
"get": "params",
"post": "data",
"put": "put",
"delete": "del"
},
"templateConfig": {
// 配置接口与代码片段模板的对应关系,非必填;通过这个可以配置不同接口使用不同模板生成
"pageLoading": [
"hello/GetGame" // 匹配规则是 `${文件名}/${service里的rpc方法名}`
],
"unPageLoading": ["hello/BatchGetGame"]
},
"defaultTemplate": [
// 默认代码片段的模板; **必填项**
"$COMMENT",
"export const $API_NAME = ($REQ_KEY: $REQ_TYPE) => {",
"return request<ResponseStructure<$RSP_TYPE>>({",
"url:'$FORMAT_URL_METHOD',",
"method: '$API_METHOD',",
"$REQ_KEY,",
"} as AxiosConfig<$REQ_TYPE, $REQ_TYPE>);",
"};"
],
"customTemplate": {
// 自定义不同代码片段的模板,非必填; 需搭配templateConfig项使用
"pageLoading": [
"$COMMENT",
"export const $API_NAME = ($REQ_KEY: $REQ_TYPE) => {",
"return request<ResponseStructure<$RSP_TYPE>>({",
"url:'$PKG_NAME.$SRV_NAME/$API_NAME',",
"method: '$API_METHOD',",
"$REQ_KEY,",
"pageLoading:'pageLoading'",
"} as AxiosConfig<$REQ_TYPE, $REQ_TYPE>);",
"};"
],
"unPageLoading": [
"$COMMENT",
"export const $API_NAME = ($REQ_KEY: $REQ_TYPE) => {",
"return request<ResponseStructure<$RSP_TYPE>>({",
"url:'$PKG_NAME.$SRV_NAME/$API_NAME',",
"method: '$API_METHOD',",
"$REQ_KEY,",
"pageLoading:'none'",
"} as AxiosConfig<$REQ_TYPE, $REQ_TYPE>);",
"};"
]
},
"importTemplate": [
// 导入依赖相关的代码片段模板,可根据自己需求定义,非必填
"import * as Types from './types';",
"const { request } = useAxios();"
],
"pretreatRules": {
// 用于替换proto文件内的部分匹配内容,如配置了此项,会使用此项规则修改后的proto文件进行转换;不会修改原proto文件; 非必填项
"./proto/example/example.proto": [
// key名是配置的路径,可配置多个规则,均会应用到该文件上
{
"searchValue": "{ in: [ \\\"未处理\\\", \\\"已处理\\\" ] }", // 被替代的内容,注意:此内容是匹配JSON.stringify后的文本信息,按照json的规则,对特殊的符号匹配需进行转义,例如 "" 和 \ 等等;
"replaceValue": "0" // 需要替换成的内容
}
],
"./proto/hello.proto": [] // 可为多个文件配置多个规则
},
"printRoot": false // 可在项目根目录输出解析proto文件生成的root对象的json文件,调试用,非必填;
}
代码片段变量说明
"$COMMENT": proto文件的注释,
"$API_NAME": proto文件的api名称,
"$REQ_KEY": 不同请求方式下,请求参数的key名; 默认值是:'data',
"$REQ_TYPE": proto文件的请求参数类型,
"$RSP_TYPE": proto文件的相应数据类型,
"$PKG_NAME": proto文件的package名称,
"$SRV_NAME": proto文件接口的service名称,
"$API_METHOD": proto文件接口的方法名称,
"$FORMAT_URL_METHOD": 格式化函数的返回结果
格式化函数示例
const formatUrlMethod = (PKG_NAME, SRV_NAME, API_NAME) => {
// 参数1可以取到$PKG_NAME的值,参数2可以取到$SRV_NAME的值,参数3可以取到$API_NAME的值
return `prefix ${PKG_NAME}.${SRV_NAME} conjunctions ${API_NAME} suffix`; // 可以根据入参自由拼接,返回的结果会体现到模板的$FORMAT_URL_METHOD变量上
};
exports.FORMAT_URL_METHOD = formatUrlMethod; // 此处导出的时候必须使用FORMAT_URL_METHOD命名
转换示例
proto 文件
syntax = "proto3";
package hello;
import "google/protobuf/empty.proto";
import "google/api/annotations.proto";
enum Status {
UNKNOWN = 0;
// 新创建
NEW = 1;
}
message InfoReq {
int32 id = 1 [proto3_optional = true]; // id
string user_name = 2 ; // optional
}
message InfoResp {
int32 ret_code = 1 [json_name = "retCode"];
string ret_msg = 2 [json_name = "retMsg"];
Status status = 3;
}
service API {
rpc GetDemo(google.protobuf.Empty) returns (google.protobuf.Empty) {
option (google.api.http) = {
get: "/get"
body: "*"
};
}
rpc PostDemo(InfoReq) returns (InfoResp) {
option (google.api.http) = {
post: "/post"
};
}
}
message GetRequest {
int64 id = 1;
int64 external_id = 2;
int32 external_type = 3;
}
service API2 {
// @method get
// @redirect api/get-game
rpc GetGame(GetRequest) returns (InfoResp);
rpc BatchGetGame(GetRequest) returns (InfoResp);
}
转换后的 api 文件
/* eslint-disable */
/** @format */
// This is code generated automatically by the proto2api, please do not modify
import * as Types from "./types";
const { request } = useAxios();
// null
// API
export const GetDemo = (params: {}) => {
return request<ResponseStructure<{}>>({
url: "prefix /hello.API2 conjunctions GetDemo suffix",
method: "get",
params,
} as AxiosConfig<{}, {}>);
};
export const PostDemo = (data: InfoReq) => {
return request<ResponseStructure<InfoResp>>({
url: "prefix /hello.API2 conjunctions PostDemo suffix",
method: "post",
data,
} as AxiosConfig<InfoReq, InfoResp>);
};
// null
// API2
// @method get
// @originUrl:
export const GetGame = (params: GetRequest) => {
return request<ResponseStructure<InfoResp>>({
url: "prefix /hello.API2 conjunctions GetGame suffix",
method: "get",
params,
} as AxiosConfig<GetRequest, InfoResp>);
};
export const BatchGetGame = (data: GetRequest) => {
return request<ResponseStructure<InfoResp>>({
url: "/hello.API2/BatchGetGame",
method: "post",
data,
pageLoading: "none",
} as AxiosConfig<GetRequest, InfoResp>);
};
转换后的 types 文件
/* eslint-disable */
/** @format */
// This is code generated automatically by the proto2api, please do not modify
export enum Status {
UNKNOWN = "UNKNOWN",
// 新创建
NEW = "NEW",
}
export interface InfoReq {
// id @int32
id?: number;
// optional
user_name?: string;
}
export interface InfoResp {
// @int32
retCode: number;
retMsg: string;
status: Status;
}
export interface GetRequest {
// @int64
id: string;
// @int64
external_id: string;
// @int32
external_type: number;
}
参考文档
Google Protobuf 语法指南 https://developers.google.com/protocol-buffers/docs/proto3
proto2api 参考链接https://www.npmjs.com/package/proto2api