curl-to-api
v1.0.0
Published
从 curl / Apipost 接口文档一键生成 Vue API 代码或 TS 类型文件
Maintainers
Readme
curl-to-api
从 Apipost / Postman 复制的 curl 命令一键生成 Vue API 文件,或从 Apipost 接口文档 JSON 生成 TS 类型文件。
安装
# 全局安装,任意项目下都能直接用
npm install -g curl-to-api
# 或作为某个项目的开发依赖
npm install -D curl-to-api
# / pnpm add -D curl-to-api快速开始
- 在 Apipost / Postman 中复制接口的 curl 命令
- 把整段 curl 命令原样粘贴在
gen --后面直接执行(工具自身的参数如--comment、--output要写在--前面):
curl-to-api gen --comment="新增产品" -- \
curl --request POST --url 'https://api.example.com/epmp/product/add.do' \
--header 'Content-Type: application/json' \
--data '{"name": "xxx"}'- 终端会输出生成的 API 代码,复制到
src/api/对应文件即可,或直接用--output写入文件(见下文)
为什么要有这个
--?因为 curl 命令本身也用--request、--header、--data这类以--开头的参数,--是 shell/CLI 的标准写法,用来告诉工具"后面的内容原样透传,不要当成我自己的参数解析"(npm run x -- --foo、git diff -- <path>都是同样的用法)。注意:本工具不会读取系统剪贴板,必须显式传入 curl 命令(粘贴在
--后面,或使用-c/-f参数),这样在 CI、SSH 远程终端等没有剪贴板的环境下也能正常使用。
命令说明
| 命令 | 说明 |
|------|------|
| curl-to-api gen [选项] -- curl ... | 直接粘贴 curl 命令,生成 API 代码 |
| curl-to-api parse -- curl ... | 直接粘贴 curl 命令,输出解析后的 JSON(调试用) |
| curl-to-api interface-gen '{...}' | 直接粘贴 Apipost 接口 JSON(不需要 --,JSON 不以 - 开头),生成 TS 类型文件 |
| curl-to-api interface-parse '{...}' | 直接粘贴 Apipost 接口 JSON,输出解析结果(调试用) |
四个命令都支持用 -c/--curl、-f/--file(curl 场景)或 --json、-f/--file(interface 场景)显式传参,等价于上面的粘贴方式,适合脚本化调用:
curl-to-api gen -c "curl --request GET --url https://..."
curl-to-api gen -f ./my.curl
curl-to-api interface-gen --json '{"...":"..."}'
curl-to-api interface-gen -f ./api.json四种输入方式都没有提供时会直接报错,不会有任何隐式的默认行为。
生成 TS 类型(interface-gen)
快速开始
- 在 Apipost 中复制接口文档 JSON(接口详情里的完整 JSON)
- 执行(JSON 不需要
--分隔符,直接作为位置参数传入即可):
curl-to-api interface-gen '{...刚复制的 JSON...}'- 默认会在
src/api/types/下生成两个文件:
deviceTestPage.request.ts # 请求参数
deviceTestPage.response.ts # 返回值返回值哪怕是深层嵌套对象,也会递归拆分成多个具名 interface。
常用示例
# 仅输出到终端,不写文件
curl-to-api interface-gen '{...}' --stdout
# 指定输出前缀
curl-to-api interface-gen '{...}' --output=src/api/prodCenter/types/deviceTestPage
# 指定输出目录(自动按 URL 推导文件名)
curl-to-api interface-gen '{...}' --output-dir=src/api/types
# 从文件读取
curl-to-api interface-gen --file=fixtures/example.apipost.json
# 调试解析结果
curl-to-api interface-parse --file=fixtures/example.apipost.jsoninterface-gen 参数
| 参数 | 说明 | 默认值 |
|------|------|--------|
| --json | Apipost 接口 JSON 字符串(也可以直接作为位置参数传入) | - |
| -f, --file | 从文件读取 JSON | - |
| -o, --output | 输出文件前缀或路径 | 按 URL 自动命名 |
| --output-dir | 输出目录 | src/api/types |
| --name | 自定义类型基础名 | 从 URL 推导 |
| --comment | 接口注释 | 使用接口 name |
| --stdout | 仅输出到终端 | false |
常用示例
1. 直接粘贴生成(最常用)
curl-to-api gen --comment="查询设备充电状态" -- \
curl --request POST --url 'https://api.example.com/x' \
--header 'Content-Type: application/json' --data '{"a":1}'2. 输出到文件
# 新建文件
curl-to-api gen --output=src/api/evcs.js --comment="查询设备状态" -- \
curl --request GET --url 'https://api.example.com/evcs'
# 追加到已有文件(不会重复 import)
curl-to-api gen --output=src/api/order/getPincode.js --append -- \
curl --request POST --url 'https://api.example.com/pincode'3. 用 -c/-f 传入 curl(脚本化场景,不需要 --)
curl-to-api gen -c "curl --request POST --url https://..."
curl-to-api gen -f ./fixtures/example.curl4. 生成 TypeScript
curl-to-api gen --lang=ts --comment="查询设备状态" -- \
curl --request POST --url 'https://api.example.com/x' --data '{"a":1}'会额外生成请求参数 interface 类型。
5. Vue2 项目
curl-to-api gen --vue=2 -- curl --request GET --url 'https://api.example.com/x'6. 自定义函数名
curl-to-api gen --name=deleteProductAttribute --comment="删除产品模板" -- \
curl --request DELETE --url 'https://api.example.com/attr/delete/1.do'注意:
--name传入后按原样作为函数名使用,不会再自动追加Api后缀,如需要请自行在--name里带上后缀。
参数一览
gen / parse 命令
| 参数 | 说明 | 默认值 |
|------|------|--------|
| [curlParts...] | 直接粘贴的完整 curl 命令(位置参数,前面要加 -- 分隔符) | - |
| -c, --curl | curl 命令字符串 | - |
| -f, --file | 从文件读取 curl 命令 | - |
| -o, --output | 输出文件路径(仅 gen) | 输出到终端 |
| --append | 追加到已有文件末尾(仅 gen) | false |
| --vue | Vue 版本:2 / 3(仅 gen) | 3 |
| --lang | 输出语言:js / ts(仅 gen) | js |
| --comment | 接口注释(仅 gen) | - |
| --name | 自定义函数名,原样使用不追加后缀(仅 gen) | 从 URL 推导 |
| --bfLoading | 是否显示 loading(仅 gen) | - |
| --isParams | GET 是否使用 params(仅 gen) | - |
| --isFormData | 是否 form 表单提交(仅 gen) | - |
| --json | 同时输出解析 JSON(仅 gen) | false |
生成规则
POST / PUT(带 JSON body)
import request from '@/utils/axiosReq';
// 新增产品模板
export function addTemplateVerInfoApi(data) {
return request({
url: '/epmp/product/templateVerInfo/add.do',
method: 'post',
data,
});
}DELETE(路径含 ID,如 /delete/1.do)
// 删除产品模板版本信息
export function deleteTemplateVerInfoApi(id) {
return request({
url: `/epmp/product/templateVerInfo/delete/${id}.do`,
method: 'delete',
isParams: true,
});
}GET(无 body)
export function productInfoApi(data) {
return request({
url: '/epmp/product/info/productInfo.do?pageNo=1&pageSize=15',
method: 'get',
});
}追加模式
追加到已有文件时:
- 不会重复写入
import request from '@/utils/axiosReq' - 若指定路径不存在,会在
apiDir(默认src/api)下按文件名自动匹配已有文件
自动处理
| 场景 | 处理方式 |
|------|----------|
| GET 请求带 body | 警告并自动改为 POST |
| URL 含域名 | 只保留 path,baseURL 由项目自己的请求封装负责 |
| 函数名 | 从 URL 路径推导,如 query_equip_charge_status → queryEquipChargeStatusApi |
如何适配任意项目(baseURL / axios 封装 / Vue2 或 Vue3)
生成的代码只包含请求路径(path)和方法,不包含域名、不生成 axios 实例或拦截器代码。域名(baseURL)、请求拦截器、错误处理这些完全是使用方项目自己的事,工具只需要知道两件事就能对接任意项目:
requestImport:项目里请求方法从哪个文件 import,例如@/utils/axiosReq、@/utils/httprequestFn:请求方法叫什么名字,例如request、http
在项目根目录新建 .curlapirc.js:
module.exports = {
vue: 3,
lang: 'js',
requestImport: '@/utils/http', // 换成你项目自己的请求封装路径
requestFn: 'http', // 换成你项目自己的请求方法名
apiDir: 'src/api',
naming: {
suffix: 'Api',
},
url: {
usePathOnly: true, // 只保留 URL path,baseURL 走你项目自己的环境变量配置
},
method: {
getWithBodyAsPost: true, // GET 带 body 自动改 POST
},
interface: {
outputDir: 'src/api/types',
},
// Vue2 / Vue3 项目的默认 requestImport 通常不同,可以分别配置
templates: {
2: {
js: { requestImport: '@/utils/request' },
ts: { requestImport: '@/utils/request' },
},
3: {
js: { requestImport: '@/utils/axiosReq' },
ts: { requestImport: '@/utils/axiosReq' },
},
},
};不管项目用的是 axios、fetch 封装还是别的什么请求库,只要有一个统一的 request(options) 风格的方法,配置好 requestImport/requestFn 就能用。
函数命名规则
pathToFunctionName:取 URL path 最后一个有意义的路径片段(跳过 v1/v2/v3、api 这类无意义片段以及纯数字片段),转换成小驼峰后拼接后缀(默认 Api)。例如:
/epmp/product/info/productInfo.do→ 取productInfo→productInfoApi/epmp/product/templateVerInfo/delete/1.do(识别为删除 + 路径参数)→deleteTemplateVerInfoApi,数字1会被替换成模板参数${id}
也可以用 --name=xxx 完全自定义(原样使用,不会自动追加后缀)。
常见问题
Q: 为什么不能直接不传参数、默认读剪贴板了?
为了让工具在任何环境(本地终端、CI、SSH 远程会话)下都能确定性地工作,去掉了隐式读剪贴板的行为。改为把复制的 curl/JSON 直接粘贴在命令后面,或用 -c/-f/--json 显式传入。
Q: 如何查看 curl 解析结果?
curl-to-api parse -- curl --request GET --url 'https://api.example.com/x'Q: --append 没生效?
--append 必须配合 -o/--output 使用,且要写在 -- 前面:
# ❌ 错误:--append 写在了 -- 后面,会被当成 curl 的一部分
curl-to-api gen -- curl ... --append
# ✅ 正确
curl-to-api gen --output=src/api/order/getPincode.js --append -- curl ...目录结构
curl-to-api/
├── bin/cli.js # CLI 入口
├── lib/
│ ├── parseCurl.js # curl 解析
│ ├── parseApipost.js # Apipost JSON 解析
│ ├── generate.js # API 代码生成
│ ├── generateInterface.js # TS 类型生成
│ ├── config.js # 配置加载
│ ├── utils.js # 命名 / 类型推断
│ ├── resolveOutput.js # 输出路径解析
│ ├── resolveInterfaceOutput.js # 类型文件输出路径
│ └── npmOptions.js # npm/pnpm 参数兼容
├── fixtures/
│ ├── example.curl
│ └── example.apipost.json
├── test/ # node --test 单元测试
└── README.mdLicense
MIT
