Skip to content

Swagger

@vafast/swagger 为 Vafast 提供 OpenAPI 文档 UIOpenAPI 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.titleAPI 名称,显示在 UI 标题等处'Vafast API'
info.description简短说明,介绍这套 API 做什么'API documentation'
info.version你的 API 版本号(不是 Swagger UI CDN 版本)'1.0.0'

注意区分:

  • documentation.info.version → OpenAPI 里的 API 版本
  • 配置项 versionSwagger UIswagger-ui-dist CDN 版本(默认 '4.18.2'
  • scalarVersionScalar 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'(默认)现代阅读体验,适合浏览与试调用scalarVersionscalarCDNscalarConfig
'swagger-ui'经典 Swagger UI,「Try it out」习惯用户多versionswaggerOptionsautoDarkMode

两者都从相对路径 ./json 拉取规范(相对 UI 页面路径)。自定义 path / specPath 时注意相对关系。

哪些配置目前没用?

类型 VafastSwaggerConfig 里仍有 themeexcludeStaticFileexcludeexcludeMethodsexcludeTags,但 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

中间件逻辑:

  1. pathname === path → 返回 UI HTML(htmlResponse
  2. pathname === specPath → 返回 createOpenAPISpec(documentation) JSON
  3. 其它 → next()

VafastSwaggerConfig

参数类型默认说明
provider'scalar' | 'swagger-ui''scalar'UI 提供方
pathstring'/swagger'UI 路径
specPathstring`${path}/json`OpenAPI JSON 路径
documentation见下表{}手写规范片段
scalarVersionstring'latest'Scalar CDN 版本
scalarCDNstring''自定义 Scalar script URL;空则用 jsDelivr
scalarConfigRecord<string, any>{}写入 Scalar data-configuration
versionstring'4.18.2'Swagger UI dist 版本
swaggerOptionsRecord<string, any>{}注入 SwaggerUIBundle({...})(函数类选项不支持)
autoDarkModebooleantrueSwagger UI 暗色媒体查询

documentation 字段

字段说明
info.titleAPI 标题;缺省 'Vafast API'
info.descriptionAPI 描述;缺省 'API documentation'
info.versionAPI 版本;缺省 '1.0.0'
pathsOpenAPI paths(需手写);缺省 {}
componentsschemassecuritySchemes;缺省 {}
tags{ name, description? }[];缺省 []

配置了但当前未使用的选项

类型里仍有以下字段,当前 swagger() 实现未用于过滤、扫描或换肤

参数默认说明
themeunpkg swagger-ui.css URL传入 renderSwaggerUI 形参但未使用;CSS 写死 unpkg
excludeStaticFiletrue未参与中间件分支逻辑
exclude[]未用于排除 path
excludeMethods['OPTIONS']未用于过滤 methods
excludeTags[]未用于过滤 tags

请以手写 documentation 为准,不要假设这些选项会自动改规范。

最佳实践

  1. documentation 抽到独立模块(如 openapi.ts),与路由变更一起 review
  2. 需要从代码生成 OpenAPI 时,另见 OpenAPI 集成 或自建生成器,再把结果传入 documentation
  3. 生产可把 UI 限内网,或仅暴露 specPath 给网关聚合
  4. Scalar 适合现代阅读;需要经典 Try-it-out 时用 swagger-ui
  5. 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,内网需自行改源码或反代

相关链接