@zpeak/openapi-adapter
v1.0.11
Published
OpenAPI adapter
Readme
@zpeak/openapi-adapter
OpenAPI适配器,用于将OpenAPI 3.0/3.1规范转换为约定的标准格式。
1. 项目概述
@zpeak/openapi-adapter 是一个用于将 OpenAPI 3.0/3.1 规范转换为内部标准格式的工具库。它提供了完整的处理管道,支持从读取 OpenAPI 规范文件到生成标准格式输出的全流程自动化处理。
2. 核心功能
2.1 完整的处理管道
Reader → Parser → Transformer → Validator → Writer- Reader: 读取 OpenAPI 规范文件(支持本地文件和 HTTP URL)
- Parser: 解析 JSON 格式的 OpenAPI 规范,处理 $ref 引用
- Transformer: 将 OpenAPI 格式转换为内部标准格式
- Validator: 验证转换后的标准格式是否符合要求
- Writer: 将转换结果写入输出文件(支持 JSON 和带注释的 JSONC 格式)
2.2 模块化设计
- 各组件通过接口定义实现松耦合
- 支持替换单个组件的实现
- 便于扩展和维护
2.3 灵活的配置
- 支持多种分组策略
- 可配置类型映射规则
- 支持自定义输出格式
3. 安装
# 推荐使用pnpm
pnpm add @zpeak/openapi-adapter
# 或使用yarn
yarn add @zpeak/openapi-adapter
# 或使用npm
npm install @zpeak/openapi-adapter4. API 参考
4.1 主要函数
processOpenAPIToStandard(config: PipelineConfig): Promise<StandardGroup[]>
核心处理管道函数,将 OpenAPI 规范转换为标准格式。
参数:
config: 管道配置对象(详见 4.2 配置选项)
返回值:
Promise<StandardGroup[]>: 转换后的标准格式分组数组
4.2 配置选项
PipelineConfig 接口支持以下配置选项:
| 选项名 | 类型 | 必填 | 默认值 | 描述 |
| -------- | ------ | ------ | -------- | ------ |
| inputPath | string | 是 | - | 输入文件路径(支持本地文件和 HTTP URL) |
| outputPath | string | 否 | - | 输出文件路径,不填则不生成文件 |
| groupBy | "tag" "path" | 否 | "tag" | 分组策略 |
分组策略详解
tag: 按 OpenAPI 接口的 tag 进行分组- 取每个接口的第一个 tag
- 若接口无 tag,则回退到顶层 tags[0]
- 若顶层也无 tags,则使用 "default"
- 适合严格维护 tags 的项目,便于跨路径聚合业务域
path: 按 URL 路径的第一个段进行分组- 例如
/role/xx→role - 根路径
/→root - 适合未规范 tags 或希望按 URL 资源层次组织代码的项目
- 例如
类型映射偏好
TypePreference 接口:
| 选项名 | 类型 | 默认值 | 描述 |
| -------- | ------ | -------- | ------ |
| integerAs | "number" | - | 控制如何处理 OpenAPI 中的 integer 类型 |
| unionPrefer | "string" "number" "boolean" | "string" | 遇到联合类型时优先选择的类型 |
5. 数据结构定义
5.1 标准格式数据结构
StandardGroup
API 分组信息:
interface StandardGroup {
name: string; // 分组名
description: string; // 分组描述
controllerName: string; // 控制器名
services: StandardService[]; // 该分组下的服务列表
}StandardService
单个 API 服务定义:
interface StandardService {
path: string; // API 路径
method: HttpMethod; // HTTP 方法
summary: string; // 接口摘要
description: string; // 接口详细描述
tag: string; // 默认第一个标签
controllerName: string; // 控制器名
auth: boolean; // 是否需要认证
contentType: string; // 请求体 Content-Type
respContentType: string; // 响应体 Content-Type
request: {
header?: StandardField[]; // 请求头字段
query?: StandardField[]; // 查询参数字段
path?: StandardField[]; // 路径参数字段
body?: StandardBody; // 请求体字段
};
response: StandardBody; // 响应体字段
}StandardField
请求/响应字段定义:
interface StandardField {
name: string; // 字段名
type: StandardFieldType; // 字段类型
description?: string; // 字段描述
required?: boolean; // 是否必填
default?: any; // 默认值
items?: StandardField[]; // 当类型为 array/object 时,定义元素或属性
}StandardBody
请求/响应体结构:
interface StandardBody {
type: StandardFieldType; // 体类型
items?: StandardField[]; // 当类型为 array/object 时,定义元素或属性
}类型枚举
type HttpMethod = "get" | "post" | "put" | "patch" | "delete" | "options" | "head";
type StandardFieldType = "string" | "number" | "boolean" | "object" | "array";5.2 组件接口
各组件通过以下接口定义实现松耦合:
interface Reader {
read(path: string): Promise<string>;
}
interface Parser<I, O> {
parse(input: I): Promise<O>;
}
interface Transformer<I, O> {
transform(input: I): Promise<O>;
}
interface Validator<T> {
validate(data: T): Promise<void>;
}
interface Writer<T> {
write(path: string, data: T): Promise<void>;
}6. 使用示例
6.1 基本用法
import { processOpenAPIToStandard } from '@zpeak/openapi-adapter';
async function main() {
const result = await processOpenAPIToStandard({
inputPath: './swagger/blog.openapi.json',
outputPath: './standard/blog.openapi.result.generated.tag.json'
});
console.log('转换完成:', result);
}
main().catch(console.error);6.2 使用远程 OpenAPI 规范
import { processOpenAPIToStandard } from '@zpeak/openapi-adapter';
async function main() {
const result = await processOpenAPIToStandard({
inputPath: 'http://localhost:3000/api-docs.json',
outputPath: './standard/remote-api.json',
groupBy: 'path'
});
console.log('转换完成:', result);
}
main().catch(console.error);6.3 自定义类型映射
import { processOpenAPIToStandard } from '@zpeak/openapi-adapter';
async function main() {
const result = await processOpenAPIToStandard({
inputPath: './swagger/blog.openapi.json',
outputPath: './standard/blog.openapi.custom.json',
groupBy: 'tag'
});
console.log('转换完成:', result);
}
main().catch(console.error);7. 控制器命名规则
自动生成的控制器名称遵循以下规则:
7.1 服务控制器名
req + Method + PathSegmentreq: 固定前缀Method: HTTP 方法的 Pascal 命名(如 Get、Post)PathSegment: 路径段的 Pascal 命名(如/role/list→ RoleList)
示例:
GET /role/list→reqGetRoleListPOST /user→reqPostUserPUT /user/{id}→reqPutUser(忽略路径参数)
7.2 分组控制器名
req + GroupNamereq: 固定前缀GroupName: 分组名的 Pascal 命名
示例:
- 分组名
blog→reqBlog - 分组名
user-management→reqUserManagement
8. 开发指南
8.1 项目结构
packages/openapi-adapter/
├── src/
│ ├── modules/ # 核心模块
│ │ ├── reader.ts # 文件读取器
│ │ ├── parser.ts # JSON 解析器
│ │ ├── transformer.ts # 转换核心
│ │ ├── validator.ts # 验证器
│ │ └── writer.ts # 文件写入器
│ ├── types/ # 类型定义
│ │ ├── index.ts # 公共类型
│ │ ├── standard.ts # 标准格式类型
│ │ └── v3.ts # OpenAPI v3 类型
│ ├── utils/ # 工具函数
│ ├── errors.ts # 错误定义
│ └── index.ts # 主入口
├── examples/ # 示例脚本
├── swagger/ # 示例 OpenAPI 规范
├── standard/ # 转换结果示例
├── package.json
├── tsconfig.json
└── tsup.config.ts8.2 构建项目
# 使用 TypeScript 编译
pnpm run build
# 或使用 tsup 构建
pnpm run build:tsup8.3 运行示例
# 构建后运行示例
pnpm run test8.4 代码检查
pnpm run lint9. 待实现功能
- 读取
- [ ] 支持多入口、多出口配置
- 解析&转换
- [ ] 支持 OpenAPI 2.x 版本
10. 许可证
ISC
