# nswag-ts **Repository Path**: money-code/nswag-ts ## Basic Information - **Project Name**: nswag-ts - **Description**: 根据swagger文档生成typescript客户端调用代码 - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 7 - **Forks**: 6 - **Created**: 2020-09-16 - **Last Updated**: 2026-08-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # nswag-ts [![npm](https://img.shields.io/npm/v/nswag-ts.svg)](https://www.npmjs.com/package/nswag-ts) [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) [![Gitee](https://img.shields.io/badge/Gitee-money--code%2Fnswag--ts-red.svg)](https://gitee.com/money-code/nswag-ts) 根据 **Swagger / OpenAPI** 文档生成 **TypeScript** 客户端调用代码。同一套核心逻辑支持四种使用方式: | 方式 | 适用场景 | 入口 | |------|----------|------| | **CLI** | 终端、npm scripts、CI | `nswag` | | **VS Code / Cursor 扩展** | 编辑器右键、进度条、日志面板 | Marketplace / vsix | | **MCP** | Agent / AI 对话调工具 | `nswag-mcp` 或扩展自动注册 | | **编程 API** | Node 脚本、构建工具二次封装 | `require('nswag-ts')` | - Node.js **≥ 18** - 配置文件:`nswag.js`(`module.exports`) - 模板:`nswag/template/*.ejs.t` --- ## 目录 - [安装](#安装) - [方式一:CLI](#方式一cli) - [方式二:VS Code / Cursor 扩展](#方式二vs-code--cursor-扩展) - [方式三:MCP](#方式三mcp) - [方式四:编程 API](#方式四编程-api) - [配置说明(nswag.js)](#配置说明nswagjs) - [模板定制](#模板定制) - [生成结果结构](#生成结果结构) - [常见问题](#常见问题) - [开源与作者](#开源与作者) - [License](#license) --- ## 安装 ### 项目依赖(推荐) ```bash npm i nswag-ts -D # 或 pnpm add -D nswag-ts yarn add -D nswag-ts ``` 在 `package.json` 中增加脚本: ```json { "scripts": { "nswag-init": "nswag init", "nswag-run": "nswag run" } } ``` 然后: ```bash npm run nswag-init npm run nswag-run ``` ### 全局安装 ```bash npm i -g nswag-ts ``` 全局安装后,可在任意项目目录执行 `nswag` / `nswag-mcp`。 **读写的始终是当前工作目录**(`process.cwd()`),不是全局包安装目录。 ### VS Code / Cursor 扩展 在扩展市场搜索安装 **nswag-ts**,或通过「从 VSIX 安装」加载已发布的 `.vsix` 包。 --- ## 方式一:CLI ### 命令一览 ```text nswag init [目标目录] 复制内置模板到「目标目录/nswag/」(默认当前目录) nswag run [nswag.js路径] 读取配置并生成代码 nswag -v, --version 显示版本 nswag -h, --help 显示帮助 ``` ### 完整示例 ```bash # 进入你的前端项目 cd /path/to/your-project # 1. 初始化(生成 nswag/nswag.js 与 nswag/template/) nswag init # 等价:nswag init . # 2. 编辑配置 # 文件:./nswag/nswag.js # 填写 SwaggerUrl、ApiBase、ApiName 等 # 3. 生成代码 nswag run # 会按顺序查找:./nswag.js → ./nswag/nswag.js # 也可显式指定配置文件 nswag run ./nswag/nswag.js nswag run /abs/path/to/nswag.js ``` ### `nswag run` 如何找配置 未传路径时,在**当前目录**解析: 1. 若存在 `./nswag.js` → 使用它 2. 否则若存在 `./nswag/nswag.js` → 使用它(`init` 的默认产物) 3. 都不存在 → 报错「配置文件不存在」 ### 路径约定(重要) 配置文件里的相对路径(`OutPath`、`TplPath`)相对于 **该 `nswag.js` 所在目录**。 以 `init` 默认产物为例,配置在 `项目根/nswag/nswag.js`: | 配置 | 推荐值 | 实际解析到 | |------|--------|------------| | `TplPath: 'template'` 或留空默认 | `template` | `项目根/nswag/template` | | `OutPath: '../src/api'` 或留空默认 | `../src/api` | `项目根/src/api/{ApiName}` | 若把配置放到项目根 `./nswag.js`,则应相应调整,例如: ```js OutPath: 'src/api', TplPath: 'nswag/template', ``` ### CI 示例 ```yaml # GitHub Actions 片段 - run: npm ci - run: npx nswag run ./nswag/nswag.js ``` --- ## 方式二:VS Code / Cursor 扩展 ### 初始化模板 1. 在资源管理器中对**项目根目录**(文件夹)右键 2. 选择 **`nswag-ts.init 初始化模板`** 3. 等待完成,项目下会出现 `nswag/`(含 `nswag.js` 与 `template/`) 也可通过命令面板(`Cmd/Ctrl + Shift + P`)搜索 `nswag-ts.init`。 ### 生成代码 1. 编辑 `nswag/nswag.js`,填写接口地址等 2. 选中任意名为 **`nswag.js`** 的文件(如 `nswag/nswag.js`) 3. 右键 → **`nswag-ts.run 生成代码`** 4. 支持进度通知与**取消**;详情见输出面板 **「NSwag TypeScript Generator」** ### 与 CLI 的关系 扩展与 CLI 共用同一套生成引擎与内置模板;配置、输出路径规则完全一致。可在团队里混用:有人用右键,有人用 `npm run nswag-run`。 --- ## 方式三:MCP 将「初始化模板」「按配置生成代码」暴露为 MCP 工具,供支持工具调用的 Agent(如 VS Code Copilot Agent、Cursor Agent)在对话中调用。 ### 工具一览 | 工具名 | 作用 | 参数 | |--------|------|------| | `nswag_ts_init` | 将内置模板复制到目标项目的 `nswag/` | **`targetFolder`**:项目根目录**绝对路径** | | `nswag_ts_run` | 读取 `nswag.js` 并生成 TS 客户端代码 | **`nswagJsPath`**:`nswag.js` 的**绝对路径** | > 两个工具都会**写入磁盘**;部分客户端会在调用前要求确认。 ### A. 安装扩展后自动注册(推荐) 1. 安装 **nswag-ts** 扩展 2. 在编辑器中启用 MCP,并在工具列表中允许 **nswag-ts** 3. 使用支持工具调用的对话模式(Agent 模式) - **VS Code 1.110+**:扩展通过官方 `registerMcpServerDefinitionProvider` 注册 - **Cursor**:扩展尝试通过 `vscode.cursor.mcp.registerServer` 自动注册 ### B. 全局 / 项目安装后手动配置 若已 `npm i -g nswag-ts` 或项目内安装了依赖: ```json { "mcpServers": { "nswag-ts": { "command": "nswag-mcp" } } } ``` 使用本地 `node_modules`: ```json { "mcpServers": { "nswag-ts": { "command": "node", "args": ["./node_modules/nswag-ts/dist/mcp/server.js"] } } } ``` 使用扩展目录中的 MCP(扩展安装路径请按本机修改): ```json { "mcpServers": { "nswag-ts": { "command": "node", "args": [ "/你的用户目录/.vscode/extensions/hezechang.nswag-ts-2.0.0/dist/mcp/server.js" ], "env": { "NSWAG_TS_EXTENSION_PATH": "/你的用户目录/.vscode/extensions/hezechang.nswag-ts-2.0.0" } } } } ``` `NSWAG_TS_EXTENSION_PATH` 可选:用于指定包根目录(含 `nswag/` 模板)。未设置时,进程会根据自身安装位置自动解析。 ### 对话提示示例 - 「请在 `/Users/me/my-app` 初始化 nswag 模板」→ `nswag_ts_init` - 「请根据 `/Users/me/my-app/nswag/nswag.js` 生成 TypeScript 接口代码」→ `nswag_ts_run` - 「调用 `nswag_ts_run`,`nswagJsPath` 为 `/Users/me/my-app/nswag/nswag.js`」 路径请使用**绝对路径**。 ### MCP 故障排除 | 现象 | 处理 | |------|------| | 工具未出现 | 检查 MCP 总开关、扩展是否启用、是否处于 Agent/工具模式 | | 初始化失败「内置模板不存在」 | 确认包完整安装,或设置 `NSWAG_TS_EXTENSION_PATH` 指向含 `nswag/` 的包根 | | 生成失败 | 确认 `nswag.js` 绝对路径正确,且 `SwaggerUrl` 可访问 | --- ## 方式四:编程 API 适用于自定义脚本、脚手架或构建流水线。 ### 基础示例(CommonJS) ```js const path = require('path') const { runInit, runGenerateFromConfigPath, createConsoleLogger } = require('nswag-ts') async function main() { const logger = createConsoleLogger() const projectRoot = process.cwd() // 1. 初始化模板到项目根(生成 nswag/) runInit(projectRoot, logger) // 2. 生成代码(请先编辑好配置) const configPath = path.join(projectRoot, 'nswag', 'nswag.js') await runGenerateFromConfigPath(configPath, logger, { report: (u) => { if (u.message) logger.progress(u.message) } }) } main().catch((err) => { console.error(err) process.exit(1) }) ``` ### 带取消(AbortSignal) ```js const { runGenerateFromConfigPath, createConsoleLogger } = require('nswag-ts') const logger = createConsoleLogger() const ac = new AbortController() // 超时取消示例 setTimeout(() => ac.abort(), 60_000) await runGenerateFromConfigPath( '/abs/path/to/nswag.js', logger, { report: () => {} }, ac.signal ) ``` ### 使用自定义模板目录初始化 ```js const { runInitTemplate, createConsoleLogger } = require('nswag-ts') runInitTemplate('/path/to/custom-nswag-dir', '/path/to/project', createConsoleLogger()) ``` ### 主要导出 | 导出 | 说明 | |------|------| | `runInit(targetFolder, logger)` | 用包内置模板初始化 `targetFolder/nswag` | | `runInitTemplate(templateDir, targetFolder, logger)` | 用指定模板目录初始化 | | `runGenerateFromConfigPath(configPath, logger, progress?, signal?)` | 按配置生成代码 | | `createConsoleLogger()` | 控制台日志实现 | | `getBuiltinNswagDir()` | 内置模板目录绝对路径 | | `getPackageRoot()` | 包根目录 | | `NswagLogger` | 日志接口类型(TypeScript) | | `NswagOptions` / `SwaggerApi` | 配置类型 | 自定义日志只需实现 `NswagLogger`: ```ts interface NswagLogger { info(message: string, ...args: unknown[]): void warn(message: string, ...args: unknown[]): void error(message: string, ...args: unknown[]): void debug(message: string, ...args: unknown[]): void success(message: string, ...args: unknown[]): void failure(message: string, ...args: unknown[]): void progress(message: string, ...args: unknown[]): void } ``` --- ## 配置说明(nswag.js) ### 完整配置示例 ```js module.exports = { Name: 'nswag-ts', Description: '根据swagger文档生成typescript客户端调用代码', Apis: [ { // —— 必填 —— SwaggerUrl: 'https://your-api.com/swagger/v1/swagger.json', ApiBase: 'https://your-api.com/api', ApiName: 'UserService', // —— 可选(路径相对本配置文件所在目录)—— // init 默认配置在 nswag/nswag.js 时: OutPath: '../src/api', // → 项目根/src/api/UserService TplPath: 'template', // → 项目根/nswag/template Mock: false, Int64ToString: true, // —— 可选:自定义命名 / Mock —— FormatControllerName: null, FormatMethodName: null, FormatModelName: null, FormatMock: null } // 可配置多个 API,一次 run 全部生成 ], // 不需要 Prettier 时删除整个 prettier 节点 prettier: { parser: 'babel-ts', singleQuote: true, printWidth: 180, tabWidth: 2, semi: false, trailingComma: 'none' } } ``` ### API 参数表 | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `SwaggerUrl` | string | ✅ | — | Swagger / OpenAPI JSON 地址 | | `ApiBase` | string | ✅ | — | 接口根地址(写入请求基类) | | `ApiName` | string | ✅ | — | 服务名,参与输出子目录命名 | | `OutPath` | string | ❌ | `../src/api`(相对配置目录) | 输出根目录,最终为 `OutPath/ApiName` | | `TplPath` | string | ❌ | `template` | EJS 模板目录 | | `Mock` | boolean | ❌ | `false` | 是否生成 Mock | | `Int64ToString` | boolean | ❌ | `true` | `int64` 转成 `string`,避免 JS 精度问题 | | `FormatControllerName` | Function | ❌ | 名称 + `Api` | 控制器/模块文件名 | | `FormatMethodName` | Function | ❌ | 路径末段小驼峰 | 方法名 | | `FormatModelName` | Function | ❌ | 去特殊字符 | DTO / 枚举名 | | `FormatMock` | Function | ❌ | 内置 Mock.js 规则 | 自定义 Mock | ### 多 API 示例 ```js module.exports = { Apis: [ { SwaggerUrl: 'https://api.example.com/user/swagger.json', ApiBase: 'https://api.example.com/user', ApiName: 'User', OutPath: '../src/api', TplPath: 'template' }, { SwaggerUrl: 'https://api.example.com/order/swagger.json', ApiBase: 'https://api.example.com/order', ApiName: 'Order', OutPath: '../src/api', TplPath: 'template', Mock: true } ], prettier: { parser: 'babel-ts', singleQuote: true, printWidth: 180, tabWidth: 2, semi: false, trailingComma: 'none' } } ``` ### 自定义格式化函数示例 ```js module.exports = { Apis: [ { SwaggerUrl: 'https://your-api.com/swagger.json', ApiBase: 'https://your-api.com/api', ApiName: 'UserService', OutPath: '../src/api', TplPath: 'template', Mock: true, Int64ToString: true, // 控制器名:User → UserApi FormatControllerName: (name) => (name.includes('Api') ? name : name + 'Api'), // 方法名:取 URL 最后一段并小驼峰 FormatMethodName: (url) => { if (url === '/' || url === '') return '' const fnName = url.substring(url.lastIndexOf('/')) return fnName .replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase()) .replace(/^\//, '') .replace(/^./, (c) => c.toLowerCase()) }, // 模型名:取 $ref 末段并去掉非法字符 FormatModelName: (ref) => ref.substring(ref.lastIndexOf('/') + 1).replace(/[^\w]/g, ''), // Mock:按字段名定制 FormatMock: (val, property, 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' } } ``` `FormatMock` 签名:`(val, property, mock) => mock`,可配合 [Mock.js](http://mockjs.com/) 语法。 --- ## 模板定制 内置模板基于 **axios**。更完整的说明见 init 后项目内的: **[`nswag/template/README.md`](./nswag/template/README.md)**(本仓库同源文件,会随 `nswag init` 复制到业务项目)。 ### 依赖 ```bash npm i axios # Mock: true 时 npm i mockjs -D ``` ### 模板文件 | 文件 | 生成产物 | 说明 | |------|----------|------| | `base.ejs.t` | `base/index.ts` | axios 实例、拦截器、`httpRequest` / `httpDownload` | | `method.ejs.t` | `{Controller}Api.ts` | 按 Tag 生成的接口方法 | | `model.ejs.t` | `model/index.ts` | DTO / 枚举 | | `mock.ejs.t` | `mock/index.ts` | Mock 入口(需 `mockjs`) | | `mock-method.ejs.t` | `mock/{Controller}Api.ts` | 各模块 Mock | ### 生成后调用示例 ```ts import UserApi from '@/api/UserService/UserApi' import { setRequestInterceptor } from '@/api/UserService/base' // 应用入口挂一次 Token setRequestInterceptor((config) => { const token = localStorage.getItem('token') if (token) config.headers.set('Authorization', `Bearer ${token}`) return config }) // 调用接口(方法名以实际生成为准) const user = await UserApi.id('1') ``` ### 改模板 1. 编辑 `nswag/template/*.ejs.t` 2. 重新 `nswag run` 3. 生成目录每次会重建,不要在输出目录长期手写代码 模板内可用 `apiConfig`、`swaggerData`、`tag`,以及 `this.getParameter` / `this.getResponses` / `this.getTagModels` 等(详见 [`nswag/template/README.md`](./nswag/template/README.md))。 --- ## 生成结果结构 以 `ApiName: 'UserService'`、`OutPath: '../src/api'`(配置在 `nswag/nswag.js`)为例: ```text src/api/UserService/ base/index.ts # 请求基类 model/index.ts # 模型与枚举 XxxApi.ts # 各 Controller / Tag 对应文件 mock/ # 仅 Mock: true 时生成 index.ts XxxApi.ts ``` 每次生成会**清理并重建**该 `OutPath/ApiName` 目录,请勿在生成目录里手写需长期保留的代码。 --- ## 常见问题 **Q: 全局安装后,会不会改到全局包里的模板?** A: 不会。`init` 是把内置模板**复制**到当前项目;`run` 只读当前项目的 `nswag.js` 与项目内模板。 **Q: `SwaggerUrl` 需要登录 / 内网证书?** A: 请保证运行环境能访问该 URL。证书、鉴权需在网络侧解决(或先下载 JSON 到本地再改用 `file://` / 本地静态服务——视运行环境而定)。 **Q: 生成代码格式报错?** A: 引擎会尽量用 Prettier 格式化;失败时会回退写入未格式化内容,便于排查模板或语法问题。 **Q: 与旧版 CLI(`nswag/config.js` + `tpl/*.ejs`)兼容吗?** A: **2.x 不兼容**。请改用 `nswag.js` + `template/*.ejs.t`,重新 `nswag init` 后迁移自定义模板内容。 --- ## 开源与作者 ### 开源地址 | 资源 | 链接 | |------|------| | 源码仓库 | [https://gitee.com/money-code/nswag-ts](https://gitee.com/money-code/nswag-ts) | | 问题反馈 | [Issues](https://gitee.com/money-code/nswag-ts/issues) | | npm 包 | [nswag-ts](https://www.npmjs.com/package/nswag-ts) | | VS Code 扩展 | [Marketplace](https://marketplace.visualstudio.com/items?itemName=hezechang.nswag-ts) | 欢迎提交 Issue 与 Pull Request;Star 也是对本项目最大的支持。 ### 作者介绍 **何泽长(hezechang)**,资深全栈研发,Gitee 开源组织 [赚钱码(money-code)](https://gitee.com/money-code) 成员。在前端技术领域有丰富的实战经验,并在前端、后端与 AI 方向均有持续积累。 开发 nswag-ts 的初衷,来自日常对接后端 API 时的痛点:每次都要对照 Swagger 手写大量 TypeScript 接口代码,既繁琐又容易出错。希望通过这套工具帮更多开发者减少重复劳动,把时间留给业务逻辑。 联系方式: - Gitee:[hezechang](https://gitee.com/hezechang) / 组织 [money-code](https://gitee.com/money-code) - npm:[hezechang](https://www.npmjs.com/~hezechang) - Email:hezechang@gmail.com --- ## License MIT