ts-proto-client
v1.1.2
Published
基于 Proto 文件自动生成 TypeScript 类型声明和 API 请求函数的 CLI 工具。
Readme
ts-proto-client
基于 Proto 文件自动生成 TypeScript 类型声明和 API 请求函数的 CLI 工具。
功能
- init — 初始化项目:创建配置文件
proto.config.json+ 从模板复制 runtime 运行时代码(插件架构,支持 Axios / Fetch) - generate — 解析 Proto 中的
service定义及 HTTP 注解(google.api.http),自动生成类型安全的 API 请求函数 + TypeScript 类型声明 - 自动识别 Proto 根目录 — 从文件路径中自动定位
protos目录,无需手动配置
原理
工具将 .proto 文件拆分为两个产物:
| 产物 | 生成方式 | 说明 |
| --- | --- | --- |
| TypeScript 类型 (.ts) | 调用 protoc + ts-proto 插件 | 将 proto message 编译为 TS interface/type |
| API 请求函数 (.ts) | 使用 protobufjs 解析 proto,提取 service + HTTP 注解 | 生成调用 service() 的函数,入参与返回值均有类型约束 |
生成的 API 函数依赖 runtime 中的 service 工具函数(由 init 命令生成),函数签名示例:
import { service } from "../axios";
import type {
HelloRequest,
HelloResponse,
} from "../type/xishan-guiyuan/ruralVisualization";
// 获取用户信息
export function GetUser(data: HelloRequest) {
return service<HelloResponse["data"]>({
url: "/api/user/{id}",
method: "get",
params: data,
})
}环境要求
- Node.js >= 18
- protoc >= 3.15(需支持
--ts_proto_out) - pnpm(推荐,也可使用 npm / yarn)
安装
# 安装本工具
pnpm add -D ts-proto-client
# 安装 ts-proto 依赖(本工具通过 protoc 调用 ts-proto 插件)
pnpm add -D ts-protoprotoc 安装
本工具依赖 protoc(Protocol Buffers 编译器),请先安装。
macOS
brew install protobuf
protoc --version # 验证安装Windows
- 从 Protocol Buffers Releases 下载
protoc-<version>-win64.zip - 解压到目标目录(如
D:\protoc) - 将
D:\protoc\bin添加到系统环境变量PATH - 验证:
protoc --version
快速开始
1. 初始化项目
npx proto-gen init交互式引导:
? HTTP client: Axios / Fetch
? API Base URL: /api
? Runtime 目录路径: src/protos/axios
? Api 文件生成路径: src/protos/api
? Type 文件生成路径: src/protos/type
? 是否强制替换已有的 Runtime 文件: No完成后会生成:
proto.config.json— 项目配置文件src/protos/axios/— runtime 运行时代码(插件架构):
src/protos/axios/
├── index.ts # 导出入口
├── type.ts # RuntimePlugin 接口定义
├── runtime.ts # service 请求封装(含拦截器)
└── plugins/
├── index.ts # setupRuntime / getPlugins
├── auth.ts # 鉴权插件(注入 AccessToken)
└── permission.ts # 权限插件(校验接口权限)2. 注册插件(可选)
import { setupRuntime, authPlugin, permissionPlugin } from "src/protos/axios"
setupRuntime(
authPlugin(() => localStorage.getItem("token") ?? undefined),
permissionPlugin(() => JSON.parse(localStorage.getItem("permissions") ?? "[]")),
)3. 生成 API 代码
npx proto-gen generate交互式输入 proto 文件路径后,自动生成 TS 类型和 API 请求函数。
命令说明
init — 初始化项目
npx proto-gen init| 交互项 | 默认值 | 说明 |
| --- | --- | --- |
| HTTP client | — | Axios 或 Fetch,选择 runtime 使用的请求库 |
| API Base URL | /api | API 基础路径,写入 runtime.ts 的 baseURL |
| Runtime 目录路径 | src/protos/axios | runtime 代码的输出目录 |
| Api 文件生成路径 | src/protos/api | API 请求函数的输出目录 |
| Type 文件生成路径 | src/protos/type | TypeScript 类型的输出目录 |
| 强制替换 | No | 设为 Yes 可覆盖已有的 runtime 文件 |
注意:
init生成的 runtime 文件你可以自由修改其中的拦截器、请求头、错误处理等逻辑。再次运行init不会覆盖已有文件(除非选择强制替换)。
generate — 生成代码
npx proto-gen generate读取 proto.config.json,交互式输入 proto 文件路径,自动生成:
- TypeScript 类型声明(通过
protoc+ts-proto) - API 请求函数(解析 proto 中的 HTTP 注解)
配置文件 (proto.config.json)
由 init 命令生成,也可手动创建:
{
"client": "axios",
"baseURL": "/api",
"runtimePath": "src/protos/axios",
"apiPath": "src/protos/api",
"typePath": "src/protos/type"
}| 字段 | 说明 |
| --- | --- |
| client | 请求库类型:"axios" 或 "fetch" |
| baseURL | API 基础路径,写入 runtime.ts 的 baseURL 字段 |
| runtimePath | runtime 代码的输出目录,生成的 API 代码会计算到此目录的相对导入路径 |
| apiPath | API 请求函数的输出目录 |
| typePath | TypeScript 类型的输出目录 |
Runtime 说明
Runtime 采用插件架构,核心由 service() 函数 + 可插拔的 RuntimePlugin 组成。
文件结构
| 文件 | 说明 |
| --- | --- |
| type.ts | RuntimePlugin 接口:onRequest / onResponse / onError / hasPermission |
| runtime.ts | Axios 实例 + service() 函数,通过插件链处理请求/响应 |
| extensions/index.ts | 插件注册中心:setupRuntime() 注册插件,getPlugins() 获取已注册插件 |
| extensions/auth.ts | authPlugin(getToken) — 请求拦截器自动注入 AccessToken 请求头 |
| extensions/permission.ts | permissionPlugin(getPermissions) — 校验 requiredPermissions,无权限直接拒绝请求 |
请求生命周期
service(config) 调用
→ 检查 requiredPermissions → hasPermission 校验(所有插件依次判断)
→ 发起请求
→ 请求拦截器 → onRequest(所有插件依次执行)
→ 发送 HTTP 请求
→ 响应拦截器 → onResponse(所有插件依次执行)
→ 检查 result.code === 0 → 返回 result.data
→ 出错 → onError(所有插件依次执行)响应格式约定
Runtime 假定后端返回统一格式:
{
"code": 0,
"data": { ... },
"message": "ok"
}code !== 0 时 service() 会 reject,你可以在 onError 插件中统一处理(如 Toast 提示)。
自定义插件
实现 RuntimePlugin 接口并通过 setupRuntime() 注册即可:
import type { RuntimePlugin } from "./type"
export function myPlugin(): RuntimePlugin {
return {
onRequest(config) {
// 修改请求配置
return config
},
onResponse(response) {
// 处理响应数据
return response
},
onError(error) {
// 统一错误处理
console.error(error)
},
hasPermission(permissions) {
// 自定义权限校验逻辑
return true
},
}
}目录约定
工具会在 proto 文件路径中自动查找 protos 目录,并将其作为 Proto 根目录。
示例目录结构
src
└─ data
└─ protos ← 工具自动识别此目录为 Proto Root
├─ hospital
│ └─ account.proto
└─ xishan-guiyuan
└─ ruralVisualization.proto生成结果
执行 generate,输入 ../protos/xishan-guiyuan/ruralVisualization.proto:
src
└─ protos
├─ type ← TypeScript 类型
│ └─ xishan-guiyuan
│ └─ ruralVisualization.ts
├─ api ← API 请求函数
│ └─ xishan-guiyuan
│ └─ RuralVisualization.ts
└─ axios ← runtime 运行时代码(init 生成)
├─ index.ts
├─ runtime.ts
├─ type.ts
└─ extensions/
├─ index.ts
├─ auth.ts
└─ permission.ts生成的目录结构会保持 proto 文件在 protos 下的相对路径。
Proto 文件要求
工具依赖 Proto 文件中的 HTTP 注解来生成 API 函数,需要你的 .proto 文件包含:
google.api.http选项 — 定义 HTTP 方法和路径openapiv2_operation.summary选项 — 作为生成函数的注释(可选)
示例:
import "google/api/annotations.proto";
service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse) {
option (google.api.http) = {
get: "/api/user/{id}"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "获取用户信息"
};
}
}需要第三方 proto 文件(
google/api/annotations.proto等),请将它们放置在protos/third_party/googleapis/目录下。
本地开发
# 开发模式(直接运行 TS 源码)
pnpm dev generate
pnpm dev init
# 构建(打包 + 复制 templates 到 dist/)
pnpm build常见问题
protoc: command not found
protoc 未安装或未添加到 PATH,请参考上方 protoc 安装 章节。
protoc-gen-ts_proto: command not found
ts-proto 未安装,执行:
pnpm add -D ts-proto未找到 protos 根目录
工具通过查找路径中的 protos 目录来确定 Proto 根目录。如果你的目录名不是 protos(例如 protobuf),将无法自动识别。
正确示例:
../protos/hospital/account.proto ✅无法识别:
../protobuf/hospital/account.proto ❌License
MIT
