orval-gen-api
v1.0.0
Published
Generate API clients via Orval into a target repo
Readme
gen-api
gen-api 是一个基于 Orval 的 API 代码生成 CLI。它会读取远程或本地 OpenAPI JSON,按 tag 过滤接口,并在目标项目中生成符合当前项目约定的 src/api/<tag>/index.ts 和 src/api/<tag>/index.i.ts。
环境要求
- Node.js
>=20 - 目标项目中需要能正常安装和运行 npm 包
快速开始
在目标项目中安装:
npm i -D gen-api生成全部接口:
npx gen-api --target="https://example.com/v3/api-docs/all"只生成指定 tag:
npx gen-api --target="https://example.com/v3/api-docs/all" --tags="SOP内部接口,团队模板"查看帮助:
npx gen-api --help参数说明
--targetOpenAPI JSON 的 URL 或本地文件路径。必填,除非已经在配置文件中写了target。--tags只生成指定 tags 下的接口。可选,支持逗号或空格分隔,例如--tags="SOP内部接口,团队模板"或--tags="SOP内部接口 团队模板"。不传时生成 OpenAPI 中的全部 tag。--output-dir目标项目根目录。可选,默认是当前命令执行目录。--config外部配置文件路径。可选,相对--output-dir解析;也支持传绝对路径。支持.ts、.cjs、.js和.json。不传时会在目标项目根目录自动查找gen-api.config.ts、gen-api.config.cjs、gen-api.config.js和gen-api.config.json。--api-dirAPI 输出目录。可选,相对--output-dir解析,默认是src/api。--clean生成前清理 Orval 输出目录中的旧文件。可选,支持--clean或--clean=true。--help/-h打印帮助信息。
配置文件
当命令参数比较固定时,建议在目标项目根目录添加配置文件,把 OpenAPI 地址、tag、输出目录、请求封装等团队默认值固定下来。这样日常生成时可以直接执行:
npx gen-apiCLI 会按下面的规则读取配置:
- 不传
--config时,会在--output-dir下自动查找gen-api.config.ts、gen-api.config.cjs、gen-api.config.js和gen-api.config.json。 - 传
--config时,会读取指定文件;相对路径会基于--output-dir解析,也可以传绝对路径。 - 配置文件会和默认配置合并。
- CLI 参数优先级高于配置文件,例如命令行传了
--target,就会覆盖配置里的target。
推荐使用 gen-api.config.ts:
export default {
// OpenAPI JSON 地址或本地文件路径。
// 如果命令行传了 --target,会优先使用命令行参数。
target: "https://example.com/v3/api-docs/all",
// 只生成指定 tag。支持字符串或数组。
// 字符串支持逗号或空格分隔。
tags: "SOP内部接口,团队模板",
// API 代码输出目录,相对 --output-dir。
apiDir: "src/api",
// Orval mutator 配置,用来指定生成接口时调用哪个请求函数。
mutator: {
path: "src/api/https.ts",
name: "apiCaller",
ensure: true,
},
};参数说明
targetOpenAPI JSON 的 URL 或本地文件路径。可选;如果配置文件和命令行都没有提供,会报Missing --target。tagstag 过滤条件。可选;不配置时生成全部 tag。可以写成字符串或数组:
export default {
tags: "SOP内部接口,团队模板",
// 或
tags: ["SOP内部接口", "团队模板"],
};apiDirAPI 输出目录。相对--output-dir解析,默认src/api。例如设置为src/services/api后,会生成到目标项目的src/services/api下。mutator.path请求封装文件路径。相对--output-dir解析,默认src/api/https.ts。mutator.name请求封装函数的导出名,默认apiCaller。生成后的接口函数会从mutator.path导入这个函数并调用。mutator.ensure是否在mutator.path文件不存在时自动创建默认请求封装。默认true。如果项目已有请求封装,建议设为false,避免生成默认文件。
JSON 配置
如果不需要写注释或复杂逻辑,也可以使用 gen-api.config.json:
{
"target": "https://example.com/v3/api-docs/all",
"tags": ["SOP内部接口", "团队模板"],
"apiDir": "src/api",
"mutator": {
"path": "src/api/https.ts",
"name": "apiCaller",
"ensure": true
}
}使用指定配置文件
如果配置文件不在目标项目根目录,可以用 --config 指定:
npx gen-api --config="./config/gen-api.config.ts"上面的 --config 会解析为 /abs/path/to/your-repo/config/gen-api.config.ts。
默认配置
未配置时会使用下面的默认值:
{
apiDir: "src/api",
mutator: {
path: "src/api/https.ts",
name: "apiCaller",
ensure: true,
},
orval: {
output: {
namingConvention: "snake_case",
client: "axios-functions",
},
hooks: {},
},
}生成结果
默认输出目录结构如下:
src/api/
https.ts
<tag>/
index.ts
index.i.tshttps.ts是 Orval mutator,默认导出apiCaller。如果文件不存在且mutator.ensure !== false,CLI 会自动创建。<tag>/index.ts包含该 tag 下生成的接口函数。<tag>/index.i.ts包含当前 tag 实际用到的请求、响应和参数类型。
Mutator 用法
mutator 用来告诉 Orval:生成出来的接口函数应该调用哪个请求封装。也就是说,gen-api 只负责根据 OpenAPI 生成函数签名和入参结构,真正怎么发请求、怎么加 token、怎么处理响应、怎么处理错误,都应该放在 mutator.path 指向的文件里。
默认配置如下:
module.exports = {
mutator: {
path: "src/api/https.ts",
name: "apiCaller",
ensure: true,
},
};字段说明:
mutator.path:请求封装文件路径,相对--output-dir解析。例如src/api/https.ts。mutator.name:请求封装函数的导出名。Orval 会从mutator.path中导入这个函数。mutator.ensure:是否在文件不存在时自动创建默认 mutator。默认是true;如果要使用项目已有请求封装,建议设为false。
默认生成的 apiCaller 接收一个请求配置对象,并返回业务数据:
export const apiCaller = async <T = any>(config: {
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
url: string;
params?: Record<string, any>;
data?: any;
baseUrl?: string;
headers?: Record<string, string>;
}): Promise<T> => {
// 在这里接入 axios/fetch、token、错误处理、响应解包等逻辑。
};因此,自定义 mutator 时需要保证两点:
- 文件中必须导出与
mutator.name一致的函数。 - 函数需要能接收 Orval 传入的
config对象,并返回Promise<T>。
示例
export const apiCaller = async <T = any>(config: {
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
url: string;
params?: Record<string, any>;
data?: any;
baseUrl?: string;
headers?: Record<string, string>;
}): Promise<T> => {
const { method, url, params, data, baseUrl, headers } = config;
const requestConfig: AxiosRequestConfig = {
...(baseUrl && { baseURL: baseUrl }),
...(headers && { headers }),
};
if (method === 'GET') {
return axios.get<T>(url, { params, ...requestConfig }).then((res) => res.data);
}
return axios.post<T>(url, data, { params, ...requestConfig }).then((res) => res.data);
};Ï常见注意事项
- 不建议直接修改生成后的
src/api/<tag>/index.ts,重新生成时会被覆盖;请求逻辑应放在 mutator 中。 - 如果
mutator.ensure为true且mutator.path对应文件不存在,CLI 会创建默认https.ts;如果文件已存在,不会覆盖。 - 如果项目使用路径别名,例如
@/utils/request,需要确保目标项目的 TypeScript/Vite/Webpack 配置能解析该别名。 - 如果后端响应结构是
{ code, data, message },可以在 mutator 里统一返回response.data.data,但要确保 OpenAPI 中的响应类型和实际返回值保持一致。
常见问题
提示 Missing --target
需要传入 --target,或者在 gen-api.config.cjs / gen-api.config.json 中配置 target。
指定 tag 后没有生成接口
检查 --tags 是否和 OpenAPI 中的 tag 名完全一致。多个 tag 可以用逗号或空格分隔。
想使用项目已有的请求封装
把 mutator.path 指向已有文件,并把 mutator.name 设置为对应导出名。详细写法见上面的 Mutator 用法。
