nswag-ts

📖 介绍
nswag-ts 是一个强大的 VS Code 扩展,能够根据 Swagger/OpenAPI 文档自动生成 TypeScript 客户端调用代码。它支持自定义模板、代码格式化、Mock 数据生成等功能,让前端开发更加高效。
✨ 主要特性
- 🚀 一键生成:根据 Swagger 文档自动生成 TypeScript 接口代码
- 🎨 模板定制:支持自定义 EJS 模板,满足不同项目需求
- 📝 代码格式化:集成 Prettier,自动格式化生成的代码
- 🎭 Mock 数据:自动生成模拟数据,支持自定义格式化规则
- 🔧 灵活配置:支持多 API 配置,可自定义命名规则
- 📊 进度显示:实时显示代码生成进度,支持取消操作
- 📋 日志记录:详细的日志记录,便于调试和问题排查
🛠️ 安装
- 在 VS Code 中打开扩展面板 (
Ctrl+Shift+X 或 Cmd+Shift+X)
- 搜索
nswag-ts
- 点击安装
或者直接从 VS Code Marketplace 安装。
🚀 快速开始
第一步:初始化模板
- 在项目根目录右键
- 选择
nswag-ts.init 初始化模板
- 等待模板文件复制完成
这将自动创建 nswag 文件夹,包含配置文件和代码模板。
第二步:配置 API
编辑项目根目录下的 nswag.js 文件:
module.exports = {
Name: 'nswag-ts',
Description: '根据swagger文档生成typescript客户端调用代码',
Apis: [
{
SwaggerUrl: 'https://your-api.com/swagger.json', // 接口文档地址(必填)
ApiBase: 'https://your-api.com/api', // 接口根节点(必填)
ApiName: 'UserService', // 接口名称(必填)
OutPath: 'src/api', // 输出目录(可选,默认:src/api/{ApiName})
TplPath: 'nswag/template', // 模板路径(可选,默认:内部默认模板)
Mock: true, // 是否启用模拟数据(可选,默认:false)
Int64ToString: true // 是否将int64类型转换为string类型,避免导致前端精度丢失(可选,默认:true)
}
],
prettier: {
parser: 'babel-ts',
singleQuote: true,
printWidth: 180,
tabWidth: 2,
semi: false,
trailingComma: 'none'
}
}
第三步:生成代码
- 选中
nswag.js 配置文件
- 右键选择
nswag-ts.run 生成代码
- 等待代码生成完成
⚙️ 配置详解
API 配置参数
| 参数 |
类型 |
必填 |
默认值 |
说明 |
SwaggerUrl |
string |
✅ |
- |
Swagger 文档地址 |
ApiBase |
string |
✅ |
- |
API 基础地址 |
ApiName |
string |
✅ |
- |
API 服务名称 |
OutPath |
string |
❌ |
src/api/{ApiName} |
代码输出目录 |
TplPath |
string |
❌ |
内部默认模板 |
自定义模板路径 |
Mock |
boolean |
❌ |
false |
是否生成 Mock 数据 |
Int64ToString |
boolean |
❌ |
true |
是否将 int64 类型转换为 string,避免精度丢失 |
FormatControllerName |
Function |
❌ |
接口名称+Api |
格式化模块/控制器名称 |
FormatMethodName |
Function |
❌ |
小驼峰命名 |
格式化接口方法名称 |
FormatModelName |
Function |
❌ |
去除特殊字符 |
格式化数据模型/枚举名称 |
FormatMock |
Function |
❌ |
默认格式化规则 |
自定义 Mock 数据格式化函数 |
代码格式化配置
支持 Prettier 的所有配置选项,参考 Prettier 官方文档:
prettier: {
parser: 'babel-ts', // 解析器
singleQuote: true, // 使用单引号
printWidth: 180, // 行宽
tabWidth: 2, // 缩进
semi: false, // 不使用分号
trailingComma: 'none' // 尾随逗号
}
🎨 模板定制
模板文件说明
base.ejs.t - 接口调用基类模板,默认使用 axios
method.ejs.t - 接口函数生成模板
model.ejs.t - 数据模型生成模板
mock.ejs.t - Mock 数据调用模板
mock-method.ejs.t - Mock 数据接口模板
模板辅助函数
在模板中可以使用以下辅助函数:
// 1. 格式化参数对象,获取指定类型的参数
this.getParameter(参数对象, ['query', 'body'], callback)
// 2. 获取指定控制器依赖的模块
this.getTagModels(tag)
// 3. 格式化返回对象
this.getResponses(m.responses)
// 4. 获取全部类型和枚举对象
this.getModelsAndEnums()
// 5. 根据返回对象,生成Mock数据
this.mock(responses, data.Models)
// 6. 获取全部控制器,swagger里面对应tag标签
this.getTags()
自定义格式化函数
支持自定义命名和格式化规则,所有格式化函数都是可选的,不设置则使用默认规则。
用于格式化生成的 API 控制器类名,对应 Swagger 中的 tag 标签。
函数签名:
FormatControllerName: (name: string) => string
参数说明:
name: Swagger 中的 tag 名称(如:User、Order)
返回值:
- 格式化后的控制器名称(如:
UserApi、OrderApi)
默认行为:
- 如果名称已包含
Api,则直接返回;否则在名称后添加 Api
使用示例:
{
// 示例1:默认行为(接口名称+Api)
FormatControllerName: (name) => {
return name.indexOf('Api') !== -1 ? name : name + 'Api'
},
// 示例2:统一添加 Service 后缀
FormatControllerName: (name) => {
return name + 'Service'
},
// 示例3:转换为大驼峰命名并添加 Controller
FormatControllerName: (name) => {
const formatted = name.charAt(0).toUpperCase() + name.slice(1)
return formatted + 'Controller'
}
}
用于格式化生成的 API 方法名,对应 Swagger 中的接口路径。
函数签名:
FormatMethodName: (url: string) => string
参数说明:
url: Swagger 中的接口路径(如:/api/user/list、/api/order/{id})
返回值:
- 格式化后的方法名称(如:
getUserList、getOrderById)
默认行为:
- 提取路径最后一段,转换为小驼峰命名(如:
/api/user/list → list)
使用示例:
{
// 示例1:默认行为(小驼峰命名)
FormatMethodName: (name) => {
if (name === '/' || name === '') return ''
const fnName = name.substring(name.lastIndexOf('/'))
return _.camelCase(fnName)
},
// 示例2:根据 HTTP 方法添加前缀
FormatMethodName: (name, method) => {
const prefix = method === 'get' ? 'get' : method === 'post' ? 'create' : 'update'
const fnName = name.substring(name.lastIndexOf('/'))
return prefix + _.upperFirst(_.camelCase(fnName))
},
// 示例3:完整路径转换为方法名
FormatMethodName: (name) => {
return _.camelCase(name.replace(/^\/api\//, '').replace(/\//g, '_'))
}
}
用于格式化生成的 TypeScript 类型/接口名称,对应 Swagger 中的 definitions 或 components.schemas。
函数签名:
FormatModelName: (ref: string) => string
参数说明:
ref: Swagger 中的类型引用路径(如:#/definitions/UserDto、#/components/schemas/OrderInfo)
返回值:
- 格式化后的类型名称(如:
UserDto、OrderInfo)
默认行为:
使用示例:
{
// 示例1:默认行为(去除特殊字符)
FormatModelName: (name) => {
return name.substring(name.lastIndexOf('/') + 1).replace(/[^\w]/g, '')
},
// 示例2:去除特殊字符并转换为大驼峰
FormatModelName: (name) => {
const baseName = name.substring(name.lastIndexOf('/') + 1)
const cleaned = baseName.replace(/[^\w]/g, '')
return cleaned.charAt(0).toUpperCase() + cleaned.slice(1)
},
// 示例3:统一添加 Model 后缀
FormatModelName: (name) => {
const baseName = name.substring(name.lastIndexOf('/') + 1).replace(/[^\w]/g, '')
return baseName + 'Model'
}
}
用于自定义生成的 Mock 数据格式,支持 Mock.js 语法。
函数签名:
FormatMock: (val: any, property: Propertie, mock: any) => any
参数说明:
val: 默认格式化后的值(Mock.js 表达式)
property: 属性对象,包含 name、type、description、format、required 等
mock: 当前正在构建的 Mock 数据对象
返回值:
默认行为:
- 根据属性类型和名称生成相应的 Mock.js 表达式
使用示例:
{
// 示例1:根据属性名称自定义 Mock 数据
FormatMock: (val, property, mock) => {
switch (property.type) {
case 'string':
switch (property.name) {
case 'name':
val = '@cname' // 中文姓名
break
case 'email':
val = '@email' // 邮箱
break
case 'mobile':
val = '@natural(10000000000, 19999999999)' // 手机号
break
case 'address':
val = '@county(true)' // 地址
break
case 'idCard':
val = '@id' // 身份证号
break
default:
val = '@ctitle(10, 20)' // 默认中文标题
break
}
break
case 'number':
switch (property.name) {
case 'result_code':
val = 0 // 成功状态码
break
case 'page_index':
val = 1 // 页码
break
case 'page_size':
val = 15 // 每页数量
break
case 'total_count':
val = 30 // 总数
break
default:
val = '@integer(0, 100)' // 默认整数
break
}
break
case 'boolean':
val = '@boolean' // 布尔值
break
case 'array':
// 数组类型,生成指定数量的元素
mock[property.name + '|20'] = val
break
}
mock[property.name] = val
return mock
},
// 示例2:根据属性描述自定义
FormatMock: (val, property, mock) => {
if (property.description) {
if (property.description.includes('时间') || property.description.includes('日期')) {
val = '@datetime("yyyy-MM-dd HH:mm:ss")'
} else if (property.description.includes('图片') || property.description.includes('头像')) {
val = '@image("200x200", "#50a3ff", "#fff", "avatar")'
} else if (property.description.includes('URL') || property.description.includes('链接')) {
val = '@url("http")'
}
}
mock[property.name] = val
return mock
}
}
完整配置示例:
module.exports = {
Name: 'nswag-ts',
Description: '根据swagger文档生成typescript客户端调用代码',
Apis: [
{
SwaggerUrl: 'https://your-api.com/swagger.json',
ApiBase: 'https://your-api.com/api',
ApiName: 'UserService',
OutPath: 'src/api',
TplPath: 'nswag/template',
Mock: true,
Int64ToString: true,
// 自定义格式化函数
FormatControllerName: name => name + 'Api',
FormatMethodName: name => {
if (name === '/' || name === '') return ''
const fnName = name.substring(name.lastIndexOf('/'))
return _.camelCase(fnName)
},
FormatModelName: name => {
return name.substring(name.lastIndexOf('/') + 1).replace(/[^\w]/g, '')
},
FormatMock: (val, property, mock) => {
// 自定义 Mock 数据格式化逻辑
if (property.type === 'string' && property.name === 'name') {
val = '@cname'
}
mock[property.name] = val
return mock
}
}
],
prettier: {
parser: 'babel-ts',
singleQuote: true,
printWidth: 180,
tabWidth: 2,
semi: false,
trailingComma: 'none'
}
}
📁 项目结构
your-project/
├── nswag/ # 配置和模板目录
│ ├── nswag.js # 配置文件
│ └── template/ # 代码模板
│ ├── base.ejs.t # 基类模板
│ ├── method.ejs.t # 方法模板
│ ├── model.ejs.t # 模型模板
│ ├── mock.ejs.t # Mock模板
│ └── mock-method.ejs.t # Mock方法模板
├── src/
│ └── api/ # 生成的API代码
│ └── UserService/ # 按API名称分类
└── package.json
🔧 高级用法
多 API 配置
支持同时配置多个 API 服务:
Apis: [
{
SwaggerUrl: 'https://user-api.com/swagger.json',
ApiBase: 'https://user-api.com/api',
ApiName: 'UserService',
OutPath: 'src/api/user'
},
{
SwaggerUrl: 'https://order-api.com/swagger.json',
ApiBase: 'https://order-api.com/api',
ApiName: 'OrderService',
OutPath: 'src/api/order'
}
]
条件生成
在模板中使用条件判断:
<% if (this.hasProperty(model, 'required')) { %>
required: true,
<% } %>
自定义类型映射
// 在模板中处理特殊类型
<% if (property.type === 'integer' && property.format === 'int64') { %>
type: 'string' // 将 long 类型转换为 string
<% } else { %>
type: '<%= property.type %>'
<% } %>
🐛 故障排除
常见问题
模板初始化失败
- 确保在项目根目录执行初始化
- 检查 VS Code 权限设置
代码生成失败
- 验证 Swagger 文档地址是否可访问
- 检查配置文件格式是否正确
- 查看输出面板的详细错误信息
生成的代码格式不正确
- 检查 Prettier 配置
- 确保项目已安装 Prettier 依赖
日志查看
生成的代码会显示在 VS Code 的输出面板中,选择 "nswag-ts" 输出源查看详细日志。
🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可证
本项目采用 MIT 许可证。
💭 作者感言
大家好,我是何泽长,开发这个插件的初衷,源于我在日常前端开发中遇到的痛点。每次对接后端 API 时,都需要手动编写大量的 TypeScript 接口代码,这个过程既繁琐又容易出错。特别是在处理 Swagger 文档时,重复性的工作让我意识到,应该有一个工具来自动化这个过程。
nswag-ts 从想法到实现,经历了多次迭代和优化。我希望通过这个工具,能够帮助更多的开发者提高开发效率,减少重复劳动,让大家有更多时间专注于业务逻辑的实现。
这个项目是开源的,我欢迎所有开发者提出建议、反馈问题,或者贡献代码。每一个 Issue、每一个 Star、每一次使用,都是对我最大的支持和鼓励。
如果这个插件能够帮助到您,让您的前端开发变得更加高效和愉悦,那就是我最大的收获!
感谢所有使用和支持 nswag-ts 的开发者们!🙏