Swagger
@vafast/swagger 为 Vafast 提供 OpenAPI 文档 UI 与 OpenAPI JSON 端点。UI 可选 Scalar(默认)或经典 Swagger UI。
不会自动扫描路由
当前实现只响应配置的 path(UI 页面)与 specPath(JSON 规范)。规范内容完全来自你传入的 documentation(尤其是 documentation.paths),不会从 defineRoute 自动生成。
先搞清几个概念(给新用户)
OpenAPI 文档长什么样?
中间件最终产出一份 OpenAPI 3.0.3 JSON,结构固定为:
typescript
{
openapi: '3.0.3',
info: { title, description, version },
paths: { /* 各接口 */ },
components: { /* 可复用 schema / 安全方案等 */ },
tags: [ /* 分组标签 */ ],
}documentation.info 字段(拆开说明)
| 字段 | 作用 | 缺省值(源码) |
|---|---|---|
info.title | API 名称,显示在 UI 标题等处 | 'Vafast API' |
info.description | 简短说明,介绍这套 API 做什么 | 'API documentation' |
info.version | 你的 API 版本号(不是 Swagger UI CDN 版本) | '1.0.0' |
注意区分:
documentation.info.version→ OpenAPI 里的 API 版本- 配置项
version→ Swagger UI 的swagger-ui-distCDN 版本(默认'4.18.2') scalarVersion→ Scalar CDN 版本(默认'latest')
paths / components / tags 是什么?
| 字段 | 白话 |
|---|---|
paths | 核心:每个 URL 路径下有哪些 HTTP 方法、参数、响应。UI 里看到的接口列表就来自这里。不写就空白。 |
components | 可复用零件:如 schemas(数据模型)、securitySchemes(Bearer / API Key 等)。在 path 里用 $ref 引用。 |
tags | 给接口分组的标签元数据(名称 + 可选描述)。各 operation 上的 tags: ['users'] 与之对应,UI 会按组折叠。 |
provider:Scalar vs Swagger UI
provider | 体验 | 主要相关配置 |
|---|---|---|
'scalar'(默认) | 现代阅读体验,适合浏览与试调用 | scalarVersion、scalarCDN、scalarConfig |
'swagger-ui' | 经典 Swagger UI,「Try it out」习惯用户多 | version、swaggerOptions、autoDarkMode |
两者都从相对路径 ./json 拉取规范(相对 UI 页面路径)。自定义 path / specPath 时注意相对关系。
哪些配置目前没用?
类型 VafastSwaggerConfig 里仍有 theme、excludeStaticFile、exclude、excludeMethods、excludeTags,但 swagger() 中间件主路径未用它们做换肤、扫描或过滤(详见下方 API 表)。请以手写 documentation 为准。
安装
bash
npm install @vafast/swagger快速开始
typescript
import { Server, defineRoute, defineRoutes, serve } from 'vafast'
import { swagger } from '@vafast/swagger'
const routes = defineRoutes([
defineRoute({
method: 'GET',
path: '/users',
handler: () => [{ id: 1, name: 'Ada' }],
}),
])
const server = new Server(routes)
server.use(
swagger({
path: '/swagger',
provider: 'scalar',
documentation: {
info: {
title: 'My API',
version: '1.0.0',
description: '示例 API',
},
paths: {
'/users': {
get: {
summary: '用户列表',
responses: {
'200': {
description: 'OK',
content: {
'application/json': {
schema: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'number' },
name: { type: 'string' },
},
},
},
},
},
},
},
},
},
},
},
}),
)
serve({ fetch: server.fetch, port: 3000 })- UI:
http://localhost:3000/swagger - JSON:
http://localhost:3000/swagger/json(默认specPath = ${path}/json)
用法
手写完整 documentation(含 components 最小示例)
路由增加后,必须同步维护 paths,否则 UI 里看不到:
typescript
documentation: {
info: {
title: 'API',
description: '业务 API',
version: '1.0.0',
},
tags: [{ name: 'users', description: '用户相关' }],
paths: {
'/users/{id}': {
get: {
tags: ['users'],
summary: '用户详情',
parameters: [
{
name: 'id',
in: 'path',
required: true,
schema: { type: 'string' },
},
],
responses: {
'200': {
description: 'OK',
content: {
'application/json': {
schema: { $ref: '#/components/schemas/User' },
},
},
},
},
security: [{ bearerAuth: [] }],
},
},
},
components: {
schemas: {
User: {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' },
},
required: ['id'],
},
},
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
},
},
},
}源码里 components / schemas 结构较宽松(属性多为 any),上表是常见、可用的最小写法。
切换 Swagger UI
typescript
swagger({
provider: 'swagger-ui',
version: '4.18.2', // swagger-ui-dist CDN 版本
autoDarkMode: true,
swaggerOptions: {
persistAuthorization: true,
},
documentation: { /* ... */ },
})Scalar 自定义
typescript
swagger({
provider: 'scalar',
scalarVersion: 'latest',
scalarCDN: '', // 空则用 jsDelivr;可换成自建 URL
scalarConfig: { theme: 'default' },
documentation: { /* ... */ },
})自定义路径
typescript
swagger({
path: '/docs',
specPath: '/docs/openapi.json',
documentation: { paths: { /* ... */ } },
})API
swagger(config?)
typescript
swagger(config?: VafastSwaggerConfig): Middleware中间件逻辑:
pathname === path→ 返回 UI HTML(htmlResponse)pathname === specPath→ 返回createOpenAPISpec(documentation)JSON- 其它 →
next()
VafastSwaggerConfig
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
provider | 'scalar' | 'swagger-ui' | 'scalar' | UI 提供方 |
path | string | '/swagger' | UI 路径 |
specPath | string | `${path}/json` | OpenAPI JSON 路径 |
documentation | 见下表 | {} | 手写规范片段 |
scalarVersion | string | 'latest' | Scalar CDN 版本 |
scalarCDN | string | '' | 自定义 Scalar script URL;空则用 jsDelivr |
scalarConfig | Record<string, any> | {} | 写入 Scalar data-configuration |
version | string | '4.18.2' | Swagger UI dist 版本 |
swaggerOptions | Record<string, any> | {} | 注入 SwaggerUIBundle({...})(函数类选项不支持) |
autoDarkMode | boolean | true | Swagger UI 暗色媒体查询 |
documentation 字段
| 字段 | 说明 |
|---|---|
info.title | API 标题;缺省 'Vafast API' |
info.description | API 描述;缺省 'API documentation' |
info.version | API 版本;缺省 '1.0.0' |
paths | OpenAPI paths(需手写);缺省 {} |
components | 如 schemas、securitySchemes;缺省 {} |
tags | { name, description? }[];缺省 [] |
配置了但当前未使用的选项
类型里仍有以下字段,当前 swagger() 实现未用于过滤、扫描或换肤:
| 参数 | 默认 | 说明 |
|---|---|---|
theme | unpkg swagger-ui.css URL | 传入 renderSwaggerUI 形参但未使用;CSS 写死 unpkg |
excludeStaticFile | true | 未参与中间件分支逻辑 |
exclude | [] | 未用于排除 path |
excludeMethods | ['OPTIONS'] | 未用于过滤 methods |
excludeTags | [] | 未用于过滤 tags |
请以手写 documentation 为准,不要假设这些选项会自动改规范。
最佳实践
- 把
documentation抽到独立模块(如openapi.ts),与路由变更一起 review - 需要从代码生成 OpenAPI 时,另见 OpenAPI 集成 或自建生成器,再把结果传入
documentation - 生产可把 UI 限内网,或仅暴露
specPath给网关聚合 - Scalar 适合现代阅读;需要经典 Try-it-out 时用
swagger-ui components.schemas+$ref避免在每个 path 里重复贴同一份模型
注意事项
- 不会自动发现
defineRoute;漏写paths= UI 空白 theme/exclude*/excludeStaticFile在中间件路径上基本无效- UI 通过相对路径
./json拉规范;自定义path时注意与specPath的相对关系,必要时显式设specPath - CDN 依赖外网(unpkg / jsDelivr);内网需自备静态资源并改
scalarCDN(Scalar)。Swagger UI 的 CSS/JS URL 当前写死 unpkg,内网需自行改源码或反代