关于 openapi-codegen
面向 TypeScript 开发者的编码技能,介绍如何从 OpenAPI 文档生成类型和 API 客户端,以及将 tRPC 路由导出为 OpenAPI。内容还涵盖规范验证、生成自动化和常见问题。
主要功能
- 01从 OpenAPI 生成 TypeScript 类型
- 02生成 fetch 或 axios API 客户端
- 03通过模板定制生成内容
- 04将 tRPC 路由导出为 OpenAPI
- 05验证并自动化代码生成
适用场景
- 01为 TypeScript 项目添加类型化 API 契约
- 02根据本地或远程规范生成客户端
- 03通过 OpenAPI 文档公开 tRPC 端点
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill openapi-codegen安装后在 Claude Code 中输入/openapi-codegen确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
quick-ref/openapi-generator.mdopenapi-typescript.mdswagger-typescript-api.mdtrpc-openapi.md详细介绍
OpenAPI 代码生成核心知识
深入了解:使用
mcp__documentation__fetch_docs并指定技术:openapi-codegen,获取完整文档。
openapi-typescript(仅类型)
从 OpenAPI 架构生成 TypeScript 类型。轻量,无运行时开销。
# Installation
npm install -D openapi-typescript
# Generate types
npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts
npx openapi-typescript https://api.example.com/openapi.json -o ./src/types/api.ts
生成类型的用法
import type { paths, components } from './types/api';
// Schema types
type User = components['schemas']['User'];
type CreateUserDto = components['schemas']['CreateUserDto'];
// Request/Response types
type CreateUserRequest = paths['/users']['post']['requestBody']['content']['application/json'];
type UserResponse = paths['/users/{id}']['get']['responses']['200']['content']['application/json'];
type UsersListResponse = paths['/users']['get']['responses']['200']['content']['application/json'];
// Path parameters
type UserPathParams = paths['/users/{id}']['get']['parameters']['path'];
与 openapi-fetch 配合使用
import createClient from 'openapi-fetch';
import type { paths } from './types/api';
const client = createClient<paths>({
baseUrl: 'https://api.example.com',
});
// Fully typed requests
const { data, error } = await client.GET('/users/{id}', {
params: { path: { id: '123' } },
});
const { data } = await client.POST('/users', {
body: { name: 'John', email: '[email protected]' },
});
// Query parameters
const { data } = await client.GET('/users', {
params: { query: { status: 'active', page: 1 } },
});
openapi-generator-cli(完整客户端)
生成包含 fetch/axios 实现的完整 API 客户端。
# Installation
npm install -D @openapitools/openapi-generator-cli
# Generate TypeScript Fetch client
npx @openapitools/openapi-generator-cli generate \
-i openapi.yaml \
-g typescript-fetch \
-o ./src/api-client
# Generate TypeScript Axios client
npx @openapitools/openapi-generator-cli generate \
-i openapi.yaml \
-g typescript-axios \
-o ./src/api-client
配置文件
# openapitools.json
{
"$schema": "https://raw.githubusercontent.com/OpenAPITools/openapi-generator-cli/master/apps/generator-cli/src/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "7.0.0",
"generators": {
"typescript-client": {
"generatorName": "typescript-fetch",
"output": "#{cwd}/src/api-client",
"inputSpec": "#{cwd}/openapi.yaml",
"additionalProperties": {
"supportsES6": true,
"npmName": "@myorg/api-client",
"typescriptThreePlus": true,
"withInterfaces": true
}
}
}
}
}
生成客户端的用法
import { Configuration, UsersApi } from './api-client';
const config = new Configuration({
basePath: 'https://api.example.com',
accessToken: () => localStorage.getItem('token') || '',
});
const usersApi = new UsersApi(config);
// Typed API calls
const users = await usersApi.listUsers({ status: 'active' });
const user = await usersApi.getUserById({ id: '123' });
const newUser = await usersApi.createUser({
createUserDto: { name: 'John', email: '[email protected]' },
});
swagger-typescript-api
快速、可定制并支持模板的生成器。
# Installation
npm install -D swagger-typescript-api
# Generate
npx swagger-typescript-api -p ./openapi.yaml -o ./src/api -n api.ts
配置
npx swagger-typescript-api \
-p ./openapi.yaml \
-o ./src/api \
-n api.ts \
--axios \ # Use axios instead of fetch
--modular \ # Separate files per tag
--route-types \ # Generate route types
--extract-request-body \ # Extract request body types
--extract-response-body # Extract response body types
生成客户端的用法
import { Api } from './api/api';
const api = new Api({
baseUrl: 'https://api.example.com',
securityWorker: () => ({
headers: { Authorization: `Bearer ${getToken()}` },
}),
});
// Typed API calls
const users = await api.users.usersList({ status: 'active' });
const user = await api.users.usersDetail('123');
const newUser = await api.users.usersCreate({
name: 'John',
email: '[email protected]',
});
trpc-openapi(将 tRPC 导出为 OpenAPI)
从 tRPC 路由器生成 OpenAPI 规范。适用于外部 API 使用者。
npm install trpc-openapi
定义 OpenAPI 端点
import { initTRPC } from '@trpc/server';
import { OpenApiMeta } from 'trpc-openapi';
import { z } from 'zod';
const t = initTRPC.meta<OpenApiMeta>().create();
export const appRouter = t.router({
getUser: t.procedure
.meta({
openapi: {
method: 'GET',
path: '/users/{id}',
tags: ['users'],
summary: 'Get user by ID',
},
})
.input(z.object({ id: z.string() }))
.output(z.object({
id: z.string(),
name: z.string(),
email: z.string(),
}))
.query(({ input }) => getUserById(input.id)),
createUser: t.procedure
.meta({
openapi: {
method: 'POST',
path: '/users',
tags: ['users'],
summary: 'Create a new user',
},
})
.input(z.object({
name: z.string(),
email: z.string().email(),
}))
.output(z.object({
id: z.string(),
name: z.string(),
email: z.string(),
}))
.mutation(({ input }) => createUser(input)),
});
生成 OpenAPI 文档
import { generateOpenApiDocument } from 'trpc-openapi';
import { appRouter } from './router';
const openApiDocument = generateOpenApiDocument(appRouter, {
title: 'My API',
version: '1.0.0',
baseUrl: 'https://api.example.com',
});
// Save to file
import fs from 'fs';
fs.writeFileSync('./openapi.json', JSON.stringify(openApiDocument, null, 2));
REST 处理程序
import { createOpenApiNextHandler } from 'trpc-openapi';
import { appRouter } from './router';
// Next.js API route: pages/api/[...trpc].ts
export default createOpenApiNextHandler({
router: appRouter,
createContext: () => ({}),
});
生产就绪
CI/CD 集成
# .github/workflows/generate-client.yml
name: Generate API Client
on:
push:
paths:
- 'openapi.yaml'
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Generate types
run: npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts
- name: Check for changes
id: check
run: |
if git diff --quiet src/types/api.ts; then
echo "changed=false" >> $GITHUB_OUTPUT
else
echo "changed=true" >> $GITHUB_OUTPUT
fi
- name: Commit and push
if: steps.check.outputs.changed == 'true'
run: |
git config --local user.email "[email protected]"
git config --local user.name "API Generator Bot"
git add src/types/api.ts
git commit -m "chore: regenerate API types"
git push
包脚本
{
"scripts": {
"generate:types": "openapi-typescript ./openapi.yaml -o ./src/types/api.ts",
"generate:client": "openapi-generator-cli generate -c openapitools.json",
"generate:all": "npm run generate:types && npm run generate:client",
"precommit": "npm run generate:types && git add src/types/api.ts"
}
}
监视模式开发
# openapi-typescript with watch
npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts --watch
# Or use nodemon
npx nodemon --watch openapi.yaml --exec "npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts"
生成前验证
# Validate spec first
npx @redocly/cli lint openapi.yaml
# Then generate
npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts
监控指标
| 指标 | 目标 |
|---|---|
| 生成类型覆盖率 | 100% 的端点 |
| 包含生成步骤的构建时间 | < 30s |
| 生成后的类型错误 | 0 |
| 规范验证错误 | 0 |
检查清单
- 在 CI 中验证 OpenAPI 规范
- 规范变更时自动生成类型
- 提交生成的代码或将其加入 gitignore
- 固定生成器 CLI 的版本
- 记录自定义模板
- 记录 API 客户端初始化方式
- 记录错误处理模式
- 在客户端中配置身份验证
- 检测破坏性变更
- 测试生成的代码
不要使用此技能的情况
- 编写 OpenAPI 规范(使用
openapi技能) - GraphQL 类型生成(使用
graphql-codegen技能) - tRPC 类型安全 API(使用
trpc技能) - 手动实现 API 客户端
- 可以通过手动定义类型满足需求的简单 API
反模式
| 反模式 | 问题所在 | 解决方案 |
|---|---|---|
| 将生成的代码提交到 git | 合并冲突、代码过时 | 添加到 .gitignore,在 CI/构建时生成 |
| 不固定生成器 CLI 版本 | 输出不一致 | 在 package.json 中固定生成器版本 |
| 手动编辑生成的文件 | 重新生成时更改会丢失 | 扩展或封装生成的代码 |
| 生成前不进行验证 | 生成无效类型 | 先使用 @redocly/cli 验证规范 |
| 团队成员使用不同生成器 | 类型不一致 | 统一使用一个生成器 |
| 从远程规范生成但不缓存 | 构建缓慢、依赖网络 | 在本地缓存规范或使用架构注册表 |
| 规范变更后未更新 | 类型与运行时不匹配 | 在 CI 中针对规范更新运行生成步骤 |
| 生成的代码缺少错误处理 | 错误体验不佳 | 为生成的客户端封装错误处理 |
快速故障排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 生成失败 | OpenAPI 规范无效 | 使用 @redocly/cli lint 验证 |
| 生成后出现类型错误 | 规范与 API 不匹配 | 确认规范与实际响应一致 |
| 缺少类型 | 规范不完整或引用损坏 | 检查所有 $refs 是否都能解析,并补充缺失的架构 |
| 生成了错误的 HTTP 客户端 | 生成器配置不匹配 | 检查 -g 标志或生成器设置 |
| 循环引用错误 | 架构自引用 | 使用判别器或扁平化架构 |
| 生成速度慢 | 规范文件过大 | 拆分规范或进行部分生成 |
| 身份验证不起作用 | 未配置安全方案 | 添加 securityWorker 或令牌配置 |
| “Cannot find module” 错误 | 生成未完成 | 检查生成错误,然后重新运行 |
| 类型冲突 | 多个生成器同时运行 | 只使用一个生成器,并移除其他生成器 |
Reference Documentation
评论
支持 Markdown