swagger2api-v3 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,235 +1,243 @@
1
- # Swagger2API-v3
2
-
3
- English | [中文](./README_CN.md)
4
-
5
- A powerful command-line tool for automatically generating TypeScript interface code from Swagger (OAS3.0) documentation.
6
-
7
- ## ✨ Features
8
-
9
- - 🚀 **Fast Generation** - Quickly generate TypeScript interface code from Swagger JSON
10
- - 📁 **Smart Grouping** - Support automatic file grouping by Swagger tags
11
- - 📝 **Detailed Comments** - Automatically generate detailed comments including descriptions, parameters, and return values
12
- - 🎨 **Code Formatting** - Support custom formatting commands
13
- - ⚙️ **Environment Adaptation** - Automatically detect project environment and generate corresponding configuration files
14
- - 🔧 **CLI Tool** - Provide complete command-line tools
15
-
16
- ## 📦 Installation
17
-
18
- ```bash
19
- # Global installation
20
- npm install -g swagger2api-v3
21
-
22
- # Project dependency
23
- npm install swagger2api-v3
24
- ```
25
-
26
- ## 🚀 Quick Start
27
-
28
- ### 1. Initialize Configuration File
29
-
30
- ```bash
31
- npx swagger2api-v3 init
32
- ```
33
-
34
- ### 2. Configuration File Description
35
-
36
- The tool automatically generates configuration files in the corresponding format based on the project environment:
37
-
38
- **CommonJS Environment** (`"type": "commonjs"` or not set):
39
- ```javascript
40
- const config = {
41
- input: 'https://petstore.swagger.io/v2/swagger.json',
42
- output: './src/api',
43
- importTemplate: "import { request } from '@/utils/request';",
44
- generator: 'typescript',
45
- groupByTags: true,
46
- overwrite: true,
47
- prefix: '',
48
- lint: 'prettier --write',
49
- options: {
50
- addComments: true
51
- }
52
- };
53
-
54
- module.exports = config;
55
- ```
56
-
57
- **ES Module Environment** (`"type": "module"`):
58
- ```javascript
59
- const config = {
60
- // ... same configuration
61
- };
62
-
63
- export default config;
64
- ```
65
-
66
- ### 3. Generate Interface Code
67
-
68
- ```bash
69
- npx swagger2api-v3 generate
70
- ```
71
-
72
- ## ⚙️ Configuration Options
73
-
74
- | Option | Type | Default | Description |
75
- |--------|------|---------|-------------|
76
- | `input` | string | - | Swagger JSON file path or URL |
77
- | `output` | string | `'./src/api'` | Output directory for generated code |
78
- | `generator` | string | `'typescript'` | Code generator type. Supports `'typescript'` and `'javascript'`. `'javascript'` outputs `.js` files and skips type file generation |
79
- | `groupByTags` | boolean | `true` | Whether to group files by tags |
80
- | `overwrite` | boolean | `true` | Whether to overwrite existing files |
81
- | `prefix` | string | `''` | Common prefix for API paths |
82
- | `importTemplate` | string | - | Import statement template for request function |
83
- | `requestStyle` | 'method' \| 'generic' | `'generic'` | Request call style: `method` uses `request.get/post`, `generic` uses `request({ method })` |
84
- | `lint` | string | - | Code formatting command (optional) |
85
- | `methodNameIgnorePrefix` | string[] | `[]` | Array of prefixes to ignore when generating method names. For example, `['api', 'auth']` will transform `apiGetName` to `getName` and `authUserInfo` to `userInfo` |
86
- | `options.addComments` | boolean | `true` | Whether to add detailed comments |
87
-
88
- ## 📁 Generated File Structure
89
-
90
- ### Grouped by Tags (Recommended)
91
-
92
- ```
93
- src/api/
94
- ├── types.ts # Data type definitions (TypeScript mode only)
95
- ├── user/ # User-related APIs
96
- │ └── index.ts
97
- ├── auth/ # Auth-related APIs
98
- │ └── index.ts
99
- └── index.ts # Entry file
100
- ```
101
-
102
- ### JavaScript Output
103
-
104
- When `generator: 'javascript'` is set:
105
-
106
- - Outputs `.js` files (`index.js`, `api.js`, `user/index.js`, etc.)
107
- - Does not generate a `types.ts` file
108
- - Removes TypeScript-specific syntax (types, `import type`, generics like `<T>`)
109
-
110
- Example generated API function (method style):
111
-
112
- ```javascript
113
- export const codeAuth = (data, config) => {
114
- return request.post({ url: '/api/auth/codeAuth', data, ...config });
115
- };
116
- ```
117
-
118
- Example generated API function (generic style):
119
-
120
- ```javascript
121
- export const codeAuth = (data, config) => {
122
- return request({ url: '/api/auth/codeAuth', method: 'POST', data, ...config });
123
- };
124
- ```
125
-
126
- ### Not Grouped
127
-
128
- ```
129
- src/api/
130
- ├── types.ts # Data type definitions
131
- ├── api.ts # All API interfaces
132
- └── index.ts # Entry file
133
- ```
134
-
135
- ## 💡 Usage Examples
136
-
137
- ### Generated Type Definitions
138
-
139
- ```typescript
140
- // types.ts
141
- export interface LoginDto {
142
- /** Account */
143
- account: string;
144
- /** Password */
145
- password: string;
146
- }
147
-
148
- export interface UserInfo {
149
- /** User ID */
150
- id: string;
151
- /** Username */
152
- username: string;
153
- }
154
- ```
155
-
156
- ### Generated API Interfaces
157
-
158
- ```typescript
159
- // authController/index.ts
160
- import { request } from '@/utils/request';
161
- import type { LoginDto, LoginRespDto } from '../types';
162
-
163
- /**
164
- * Login
165
- * @param data Login parameters
166
- * @param config Optional request configuration
167
- */
168
- export const authControllerLoginPost = (data: LoginDto, config?: any) => {
169
- return request.post<LoginRespDto>({
170
- url: '/admin/auth/login',
171
- data,
172
- ...config
173
- });
174
- };
175
-
176
- // When requestStyle is set to 'generic':
177
- export const authControllerLoginPost2 = (data: LoginDto, config?: any) => {
178
- return request<LoginRespDto>({
179
- url: '/admin/auth/login',
180
- data,
181
- method: 'POST',
182
- ...config
183
- });
184
- };
185
- ```
186
-
187
- ## 🔧 CLI Commands
188
-
189
- ```bash
190
- # Initialize configuration file
191
- npx swagger2api-v3 init [--force]
192
-
193
- # Generate interface code
194
- npx swagger2api-v3 generate [--config <path>]
195
-
196
- # Validate configuration file
197
- npx swagger2api-v3 validate [--config <path>]
198
-
199
- # Show help
200
- npx swagger2api-v3 --help
201
- ```
202
-
203
- ## 📝 NPM Scripts
204
-
205
- Add to `package.json`:
206
-
207
- ```json
208
- {
209
- "scripts": {
210
- "api:generate": "swagger2api-v3 generate",
211
- "api:init": "swagger2api-v3 init",
212
- "api:validate": "swagger2api-v3 validate"
213
- }
214
- }
215
- ```
216
-
217
- ## 🎨 Code Formatting
218
-
219
- Support automatic execution of formatting commands after generation:
220
-
221
- ```javascript
222
- // In configuration file
223
- const config = {
224
- // ... other configurations
225
- lint: 'prettier --write' // or 'eslint --fix', etc.
226
- };
227
- ```
228
-
229
- ## 🤝 Contributing
230
-
231
- Issues and Pull Requests are welcome!
232
-
233
- ## 📄 License
234
-
235
- MIT License
1
+ # Swagger2API-v3
2
+
3
+ English | [中文](./README_CN.md)
4
+
5
+ A powerful command-line tool for automatically generating TypeScript interface code from Swagger (OAS3.0) documentation.
6
+
7
+ ## ✨ Features
8
+
9
+ - 🚀 **Fast Generation** - Quickly generate TypeScript interface code from Swagger JSON
10
+ - 📁 **Smart Grouping** - Support automatic file grouping by Swagger tags
11
+ - 📝 **Detailed Comments** - Automatically generate detailed comments including descriptions, parameters, and return values
12
+ - 🎨 **Code Formatting** - Support custom formatting commands
13
+ - ⚙️ **Environment Adaptation** - Automatically detect project environment and generate corresponding configuration files
14
+ - 🔧 **CLI Tool** - Provide complete command-line tools
15
+
16
+ ## 📦 Installation
17
+
18
+ ```bash
19
+ # Global installation
20
+ npm install -g swagger2api-v3
21
+
22
+ # Project dependency
23
+ npm install swagger2api-v3
24
+ ```
25
+
26
+ ## 🚀 Quick Start
27
+
28
+ ### 1. Initialize Configuration File
29
+
30
+ ```bash
31
+ npx swagger2api-v3 init
32
+ ```
33
+
34
+ ### 2. Configuration File Description
35
+
36
+ The tool automatically generates configuration files in the corresponding format based on the project environment:
37
+
38
+ **CommonJS Environment** (`"type": "commonjs"` or not set):
39
+
40
+ ```javascript
41
+ const config = {
42
+ input: 'https://petstore.swagger.io/v2/swagger.json',
43
+ output: './src/api',
44
+ importTemplate: "import { request } from '@/utils/request';",
45
+ generator: 'typescript',
46
+ groupByTags: true,
47
+ overwrite: true,
48
+ prefix: '',
49
+ lint: 'prettier --write',
50
+ options: {
51
+ addComments: true
52
+ }
53
+ };
54
+
55
+ module.exports = config;
56
+ ```
57
+
58
+ **ES Module Environment** (`"type": "module"`):
59
+
60
+ ```javascript
61
+ const config = {
62
+ // ... same configuration
63
+ };
64
+
65
+ export default config;
66
+ ```
67
+
68
+ ### 3. Generate Interface Code
69
+
70
+ ```bash
71
+ npx swagger2api-v3 generate
72
+ ```
73
+
74
+ ## ⚙️ Configuration Options
75
+
76
+ | Option | Type | Default | Description |
77
+ | ------------------------ | --------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
78
+ | `input` | string | - | Swagger JSON file path or URL |
79
+ | `output` | string | `'./src/api'` | Output directory for generated code |
80
+ | `generator` | string | `'typescript'` | Code generator type. Supports `'typescript'` and `'javascript'`. `'javascript'` outputs `.js` files and skips type file generation |
81
+ | `groupByTags` | boolean | `true` | Whether to group files by tags |
82
+ | `overwrite` | boolean | `true` | Whether to overwrite existing files |
83
+ | `prefix` | string | `''` | Common prefix for API paths |
84
+ | `importTemplate` | string | - | Import statement template for request function |
85
+ | `requestStyle` | 'method' \| 'generic' | `'generic'` | Request call style: `method` uses `request.get/post`, `generic` uses `request({ method })` |
86
+ | `lint` | string | - | Code formatting command (optional) |
87
+ | `methodNameIgnorePrefix` | string[] | `[]` | Array of prefixes to ignore when generating method names. For example, `['api', 'auth']` will transform `apiGetName` to `getName` and `authUserInfo` to `userInfo` |
88
+ | `addMethodSuffix` | boolean | `true` | Whether to add HTTP method suffix to generated function names. `true` generates `userListPost`, `false` generates `userList` |
89
+ | `options.addComments` | boolean | `true` | Whether to add detailed comments |
90
+
91
+ ## 📁 Generated File Structure
92
+
93
+ ### Grouped by Tags (Recommended)
94
+
95
+ ```
96
+ src/api/
97
+ ├── types.ts # Data type definitions (TypeScript mode only)
98
+ ├── user/ # User-related APIs
99
+ └── index.ts
100
+ ├── auth/ # Auth-related APIs
101
+ │ └── index.ts
102
+ └── index.ts # Entry file
103
+ ```
104
+
105
+ ### JavaScript Output
106
+
107
+ When `generator: 'javascript'` is set:
108
+
109
+ - Outputs `.js` files (`index.js`, `api.js`, `user/index.js`, etc.)
110
+ - Does not generate a `types.ts` file
111
+ - Removes TypeScript-specific syntax (types, `import type`, generics like `<T>`)
112
+
113
+ Example generated API function (method style):
114
+
115
+ ```javascript
116
+ export const codeAuth = (data, config) => {
117
+ return request.post({ url: '/api/auth/codeAuth', data, ...config });
118
+ };
119
+ ```
120
+
121
+ Example generated API function (generic style):
122
+
123
+ ```javascript
124
+ export const codeAuth = (data, config) => {
125
+ return request({
126
+ url: '/api/auth/codeAuth',
127
+ method: 'POST',
128
+ data,
129
+ ...config
130
+ });
131
+ };
132
+ ```
133
+
134
+ ### Not Grouped
135
+
136
+ ```
137
+ src/api/
138
+ ├── types.ts # Data type definitions
139
+ ├── api.ts # All API interfaces
140
+ └── index.ts # Entry file
141
+ ```
142
+
143
+ ## 💡 Usage Examples
144
+
145
+ ### Generated Type Definitions
146
+
147
+ ```typescript
148
+ // types.ts
149
+ export interface LoginDto {
150
+ /** Account */
151
+ account: string;
152
+ /** Password */
153
+ password: string;
154
+ }
155
+
156
+ export interface UserInfo {
157
+ /** User ID */
158
+ id: string;
159
+ /** Username */
160
+ username: string;
161
+ }
162
+ ```
163
+
164
+ ### Generated API Interfaces
165
+
166
+ ```typescript
167
+ // authController/index.ts
168
+ import { request } from '@/utils/request';
169
+ import type { LoginDto, LoginRespDto } from '../types';
170
+
171
+ /**
172
+ * Login
173
+ * @param data Login parameters
174
+ * @param config Optional request configuration
175
+ */
176
+ export const authControllerLoginPost = (data: LoginDto, config?: any) => {
177
+ return request.post<LoginRespDto>({
178
+ url: '/admin/auth/login',
179
+ data,
180
+ ...config
181
+ });
182
+ };
183
+
184
+ // When requestStyle is set to 'generic':
185
+ export const authControllerLoginPost2 = (data: LoginDto, config?: any) => {
186
+ return request<LoginRespDto>({
187
+ url: '/admin/auth/login',
188
+ data,
189
+ method: 'POST',
190
+ ...config
191
+ });
192
+ };
193
+ ```
194
+
195
+ ## 🔧 CLI Commands
196
+
197
+ ```bash
198
+ # Initialize configuration file
199
+ npx swagger2api-v3 init [--force]
200
+
201
+ # Generate interface code
202
+ npx swagger2api-v3 generate [--config <path>]
203
+
204
+ # Validate configuration file
205
+ npx swagger2api-v3 validate [--config <path>]
206
+
207
+ # Show help
208
+ npx swagger2api-v3 --help
209
+ ```
210
+
211
+ ## 📝 NPM Scripts
212
+
213
+ Add to `package.json`:
214
+
215
+ ```json
216
+ {
217
+ "scripts": {
218
+ "api:generate": "swagger2api-v3 generate",
219
+ "api:init": "swagger2api-v3 init",
220
+ "api:validate": "swagger2api-v3 validate"
221
+ }
222
+ }
223
+ ```
224
+
225
+ ## 🎨 Code Formatting
226
+
227
+ Support automatic execution of formatting commands after generation:
228
+
229
+ ```javascript
230
+ // In configuration file
231
+ const config = {
232
+ // ... other configurations
233
+ lint: 'prettier --write' // or 'eslint --fix', etc.
234
+ };
235
+ ```
236
+
237
+ ## 🤝 Contributing
238
+
239
+ Issues and Pull Requests are welcome!
240
+
241
+ ## 📄 License
242
+
243
+ MIT License
package/dist/cli/index.js CHANGED
@@ -110,51 +110,56 @@ program
110
110
  console.warn('⚠️ 无法读取package.json,使用默认ES Module格式');
111
111
  }
112
112
  }
113
- const configContent = `/**
114
- * Swagger2API 配置文件
115
- * 用于配置从 Swagger JSON 生成前端接口的参数
116
- */
117
- const config = {
118
- // Swagger JSON 文件路径或 URL
119
- input: 'http://localhost:3000/admin/docs/json',
120
-
121
- // 输出目录
122
- output: './src/api',
123
-
124
- // request 导入路径模板
125
- importTemplate: "import { request } from '@/utils/request';",
126
-
127
- // 生成器类型
128
- generator: 'typescript', // 可选 'javascript'(JS 模式输出 .js 文件且不生成类型文件)
129
-
130
- // 请求调用风格:'method' 使用 request.get/post;'generic' 使用 request({ method })
131
- requestStyle: 'generic',
132
-
133
- // 按标签分组生成文件
134
- groupByTags: true,
135
-
136
- // 是否覆盖更新,默认为true。为true时会先删除输出目录下的所有文件
137
- overwrite: true,
138
-
139
- // 接口路径公共前缀,默认为空字符串
140
- prefix: '',
141
-
142
- // 代码格式化命令(可选)
143
- lint: 'prettier --write',
144
-
145
- // 生成方法名时需要忽略的前缀(可选)
146
- // 例如:配置 ['api', 'auth'] 后,apiGetName 会变成 getName,authUserInfo 会变成 userInfo
147
- // 如果方法名是 apiAuthGetName,会依次移除所有匹配的前缀,最终变成 getName
148
- methodNameIgnorePrefix: [],
149
-
150
- // 生成选项
151
- options: {
152
- // 是否添加注释
153
- addComments: true
154
- }
155
- };
156
-
157
- ${isESModule ? 'export default config;' : 'module.exports = config;'}
113
+ const configContent = `/**
114
+ * Swagger2API 配置文件
115
+ * 用于配置从 Swagger JSON 生成前端接口的参数
116
+ */
117
+ const config = {
118
+ // Swagger JSON 文件路径或 URL
119
+ input: 'http://localhost:3000/admin/docs/json',
120
+
121
+ // 输出目录
122
+ output: './src/api',
123
+
124
+ // request 导入路径模板
125
+ importTemplate: "import { request } from '@/utils/request';",
126
+
127
+ // 生成器类型
128
+ generator: 'typescript', // 可选 'javascript'(JS 模式输出 .js 文件且不生成类型文件)
129
+
130
+ // 请求调用风格:'method' 使用 request.get/post;'generic' 使用 request({ method })
131
+ requestStyle: 'generic',
132
+
133
+ // 按标签分组生成文件
134
+ groupByTags: true,
135
+
136
+ // 是否覆盖更新,默认为true。为true时会先删除输出目录下的所有文件
137
+ overwrite: true,
138
+
139
+ // 接口路径公共前缀,默认为空字符串
140
+ prefix: '',
141
+
142
+ // 代码格式化命令(可选)
143
+ lint: 'prettier --write',
144
+
145
+ // 生成方法名时需要忽略的前缀(可选)
146
+ // 例如:配置 ['api', 'auth'] 后,apiGetName 会变成 getName,authUserInfo 会变成 userInfo
147
+ // 如果方法名是 apiAuthGetName,会依次移除所有匹配的前缀,最终变成 getName
148
+ methodNameIgnorePrefix: [],
149
+
150
+ // 是否在生成的方法名中添加 HTTP method 后缀,默认为 true
151
+ // true: userListPost, userDetailGet
152
+ // false: userList, userDetail
153
+ addMethodSuffix: true,
154
+
155
+ // 生成选项
156
+ options: {
157
+ // 是否添加注释
158
+ addComments: true
159
+ }
160
+ };
161
+
162
+ ${isESModule ? 'export default config;' : 'module.exports = config;'}
158
163
  `;
159
164
  try {
160
165
  fs.writeFileSync(configPath, configContent, 'utf-8');
@@ -64,6 +64,7 @@ export declare class CodeGenerator {
64
64
  /**
65
65
  * 收集API数组中实际使用的类型
66
66
  * @param apis API接口数组
67
+ * @param definedTypes 已定义的类型数组
67
68
  * @returns 使用的类型名称数组
68
69
  */
69
70
  private collectUsedTypes;
@@ -166,7 +166,7 @@ class CodeGenerator {
166
166
  importTemplate + ';'
167
167
  ];
168
168
  // 收集当前文件实际使用的类型
169
- const usedTypes = this.collectUsedTypes(apis);
169
+ const usedTypes = this.collectUsedTypes(apis, types); // 传入 types
170
170
  // 添加类型导入(仅在 TypeScript 且生成类型文件时)
171
171
  if (this.config.generator === 'typescript' &&
172
172
  this.config.options?.generateModels !== false &&
@@ -307,9 +307,10 @@ class CodeGenerator {
307
307
  /**
308
308
  * 收集API数组中实际使用的类型
309
309
  * @param apis API接口数组
310
+ * @param definedTypes 已定义的类型数组
310
311
  * @returns 使用的类型名称数组
311
312
  */
312
- collectUsedTypes(apis) {
313
+ collectUsedTypes(apis, definedTypes) {
313
314
  const usedTypes = new Set();
314
315
  apis.forEach((api) => {
315
316
  // 收集响应类型
@@ -334,6 +335,13 @@ class CodeGenerator {
334
335
  }
335
336
  });
336
337
  });
338
+ // 如果提供了 definedTypes,则只保留已定义的类型
339
+ if (definedTypes) {
340
+ const definedTypeNames = new Set(definedTypes.map((t) => t.name));
341
+ return Array.from(usedTypes)
342
+ .filter((name) => definedTypeNames.has(name))
343
+ .sort();
344
+ }
337
345
  return Array.from(usedTypes).sort();
338
346
  }
339
347
  /**
@@ -70,11 +70,21 @@ class SwaggerParser {
70
70
  }
71
71
  // 生成函数名
72
72
  let functionName = operation.operationId || (0, utils_1.pathToFunctionName)(method, path);
73
- // 如果使用了operationId,需要手动添加HTTP方法后缀
73
+ // 根据配置决定是否添加/保留 HTTP method 后缀
74
+ const shouldAddMethodSuffix = this.config.addMethodSuffix !== false; // 默认为 true
74
75
  if (operation.operationId) {
75
- // HTTP方法转换为首字母大写的形式并添加到末尾
76
- const methodSuffix = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
77
- functionName = functionName + methodSuffix;
76
+ // 如果使用了 operationId,根据配置决定是否添加 HTTP 方法后缀
77
+ if (shouldAddMethodSuffix) {
78
+ const methodSuffix = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
79
+ functionName = functionName + methodSuffix;
80
+ }
81
+ }
82
+ else {
83
+ // 如果没有 operationId,pathToFunctionName 已经包含了 method 后缀
84
+ // 如果配置为 false,需要移除后缀
85
+ if (!shouldAddMethodSuffix) {
86
+ functionName = (0, utils_1.removeMethodSuffix)(functionName, method);
87
+ }
78
88
  }
79
89
  // 应用前缀忽略规则
80
90
  functionName = (0, utils_1.stripMethodNamePrefixes)(functionName, this.config.methodNameIgnorePrefix);
@@ -116,17 +126,29 @@ class SwaggerParser {
116
126
  */
117
127
  parseTypes() {
118
128
  const types = [];
129
+ // Debug log
130
+ console.log('解析类型定义...');
131
+ console.log('Has definitions:', !!this.document.definitions);
132
+ console.log('Has components:', !!this.document.components);
133
+ if (this.document.components) {
134
+ console.log('Has schemas:', !!this.document.components.schemas);
135
+ if (this.document.components.schemas) {
136
+ console.log('Schema keys:', Object.keys(this.document.components.schemas));
137
+ }
138
+ }
119
139
  // 解析 Swagger 2.0 definitions
120
140
  if (this.document.definitions) {
121
141
  for (const [name, schema] of Object.entries(this.document.definitions)) {
122
- const typeInfo = this.parseTypeDefinition(name, schema);
142
+ const sanitizedName = (0, utils_1.sanitizeTypeName)(name); // Use it
143
+ const typeInfo = this.parseTypeDefinition(sanitizedName, schema);
123
144
  types.push(typeInfo);
124
145
  }
125
146
  }
126
147
  // 解析 OpenAPI 3.0 components.schemas
127
148
  if (this.document.components?.schemas) {
128
149
  for (const [name, schema] of Object.entries(this.document.components.schemas)) {
129
- const typeInfo = this.parseTypeDefinition(name, schema);
150
+ const sanitizedName = (0, utils_1.sanitizeTypeName)(name); // Use it
151
+ const typeInfo = this.parseTypeDefinition(sanitizedName, schema);
130
152
  types.push(typeInfo);
131
153
  }
132
154
  }
@@ -31,6 +31,8 @@ export interface SwaggerConfig {
31
31
  lint?: string;
32
32
  /** 生成方法名时需要忽略的前缀数组,如 ['api', 'auth'] */
33
33
  methodNameIgnorePrefix?: string[];
34
+ /** 是否在生成的方法名中添加 HTTP method 后缀,默认为 true。true: userListPost, false: userList */
35
+ addMethodSuffix?: boolean;
34
36
  }
35
37
  /**
36
38
  * 标签分组配置
@@ -1,4 +1,4 @@
1
- import { SwaggerDocument, SwaggerSchema, SwaggerParameter } from '../types';
1
+ import { SwaggerDocument, SwaggerParameter } from '../types';
2
2
  /**
3
3
  * 工具函数集合
4
4
  */
@@ -34,12 +34,19 @@ export declare function toCamelCase(str: string): string;
34
34
  * @returns 移除前缀后的方法名
35
35
  */
36
36
  export declare function stripMethodNamePrefixes(methodName: string, prefixes?: string[]): string;
37
+ /**
38
+ * 从函数名中移除 HTTP method 后缀
39
+ * @param functionName 函数名
40
+ * @param method HTTP 方法
41
+ * @returns 移除后缀后的函数名
42
+ */
43
+ export declare function removeMethodSuffix(functionName: string, method: string): string;
37
44
  /**
38
45
  * 将Swagger类型转换为TypeScript类型
39
46
  * @param schema Swagger模式
40
47
  * @returns TypeScript类型字符串
41
48
  */
42
- export declare function swaggerTypeToTsType(schema?: SwaggerSchema): string;
49
+ export declare function swaggerTypeToTsType(schema: any): string;
43
50
  /**
44
51
  * 从Swagger参数生成TypeScript参数类型
45
52
  * @param parameters Swagger参数数组
@@ -87,3 +94,4 @@ export declare function sanitizeFilename(filename: string): string;
87
94
  * @returns TypeScript类型字符串
88
95
  */
89
96
  export declare function getResponseType(responses: any): string;
97
+ export declare function sanitizeTypeName(name: string): string;
@@ -41,6 +41,7 @@ exports.toKebabCase = toKebabCase;
41
41
  exports.toPascalCase = toPascalCase;
42
42
  exports.toCamelCase = toCamelCase;
43
43
  exports.stripMethodNamePrefixes = stripMethodNamePrefixes;
44
+ exports.removeMethodSuffix = removeMethodSuffix;
44
45
  exports.swaggerTypeToTsType = swaggerTypeToTsType;
45
46
  exports.generateParameterTypes = generateParameterTypes;
46
47
  exports.ensureDirectoryExists = ensureDirectoryExists;
@@ -50,6 +51,7 @@ exports.writeFile = writeFile;
50
51
  exports.generateApiComment = generateApiComment;
51
52
  exports.sanitizeFilename = sanitizeFilename;
52
53
  exports.getResponseType = getResponseType;
54
+ exports.sanitizeTypeName = sanitizeTypeName;
53
55
  const fs = __importStar(require("fs"));
54
56
  const path = __importStar(require("path"));
55
57
  const axios_1 = __importDefault(require("axios"));
@@ -150,26 +152,41 @@ function stripMethodNamePrefixes(methodName, prefixes) {
150
152
  }
151
153
  return result;
152
154
  }
155
+ /**
156
+ * 从函数名中移除 HTTP method 后缀
157
+ * @param functionName 函数名
158
+ * @param method HTTP 方法
159
+ * @returns 移除后缀后的函数名
160
+ */
161
+ function removeMethodSuffix(functionName, method) {
162
+ const methodSuffix = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
163
+ if (functionName.endsWith(methodSuffix)) {
164
+ return functionName.slice(0, -methodSuffix.length);
165
+ }
166
+ return functionName;
167
+ }
153
168
  /**
154
169
  * 将Swagger类型转换为TypeScript类型
155
170
  * @param schema Swagger模式
156
171
  * @returns TypeScript类型字符串
157
172
  */
158
173
  function swaggerTypeToTsType(schema) {
159
- if (!schema) {
174
+ if (!schema)
160
175
  return 'any';
161
- }
162
- let baseType;
163
- // 处理 allOf 类型组合
164
- if (schema.allOf && schema.allOf.length > 0) {
165
- // 检查是否为泛型模式:第一个是引用类型,第二个定义了扩展属性
166
- const firstSchema = schema.allOf[0];
167
- if (firstSchema.$ref && schema.allOf.length > 1) {
168
- const refName = firstSchema.$ref.split('/').pop();
169
- const secondSchema = schema.allOf[1];
170
- // 检查第二个 schema 是否定义了对象属性(可能没有 type 字段)
176
+ let baseType = 'any';
177
+ // 处理 allOf (通常用于继承或泛型)
178
+ if (schema.allOf) {
179
+ // 简单处理:如果是引用 + 对象定义,可能是泛型包装
180
+ const refSchema = schema.allOf.find((s) => s.$ref);
181
+ const secondSchema = schema.allOf.find((s) => !s.$ref);
182
+ if (refSchema && secondSchema) {
183
+ const refName = refSchema.$ref.split('/').pop();
184
+ const sanitizedRefName = sanitizeTypeName(refName || '');
185
+ // 检查是否是泛型容器 (如 ResOp)
186
+ // 注意:secondSchema 可能没有显式声明 type: 'object',但如果有 properties,则视为对象
171
187
  if (secondSchema.properties) {
172
- // 获取所有扩展属性的类型
188
+ // 尝试提取泛型参数类型
189
+ // 这里假设泛型参数是 properties 中的第一个属性
173
190
  const propertyTypes = [];
174
191
  for (const [propName, propSchema] of Object.entries(secondSchema.properties)) {
175
192
  const propType = swaggerTypeToTsType(propSchema);
@@ -177,7 +194,7 @@ function swaggerTypeToTsType(schema) {
177
194
  }
178
195
  // 如果只有一个属性,直接作为泛型参数
179
196
  if (propertyTypes.length === 1) {
180
- baseType = `${refName}<${propertyTypes[0]}>`;
197
+ baseType = `${sanitizedRefName}<${propertyTypes[0]}>`;
181
198
  }
182
199
  // 如果有多个属性,组合成联合类型或对象类型
183
200
  else if (propertyTypes.length > 1) {
@@ -188,14 +205,14 @@ function swaggerTypeToTsType(schema) {
188
205
  return `${key}${optional}: ${type}`;
189
206
  })
190
207
  .join('; ')} }`;
191
- baseType = `${refName}<${combinedType}>`;
208
+ baseType = `${sanitizedRefName}<${combinedType}>`;
192
209
  }
193
210
  else {
194
- baseType = refName || 'any';
211
+ baseType = sanitizedRefName || 'any';
195
212
  }
196
213
  }
197
214
  else {
198
- baseType = refName || 'any';
215
+ baseType = sanitizedRefName || 'any';
199
216
  }
200
217
  }
201
218
  else {
@@ -206,10 +223,29 @@ function swaggerTypeToTsType(schema) {
206
223
  baseType = types.length > 0 ? types[0] : 'any';
207
224
  }
208
225
  }
226
+ // 处理 anyOf 或 oneOf
227
+ else if (schema.anyOf || schema.oneOf) {
228
+ const types = (schema.anyOf || schema.oneOf)
229
+ .map((s) => {
230
+ // 特殊处理 type: 'null'
231
+ if (s.type === 'null')
232
+ return 'null';
233
+ return swaggerTypeToTsType(s);
234
+ })
235
+ .filter((t) => t !== 'any');
236
+ // 去重
237
+ const uniqueTypes = Array.from(new Set(types));
238
+ if (uniqueTypes.length > 0) {
239
+ baseType = uniqueTypes.join(' | ');
240
+ }
241
+ else {
242
+ baseType = 'any';
243
+ }
244
+ }
209
245
  // 处理引用类型
210
246
  else if (schema.$ref) {
211
247
  const refName = schema.$ref.split('/').pop();
212
- baseType = refName || 'any';
248
+ baseType = sanitizeTypeName(refName || 'any');
213
249
  }
214
250
  // 处理数组类型
215
251
  else if (schema.type === 'array') {
@@ -253,6 +289,9 @@ function swaggerTypeToTsType(schema) {
253
289
  case 'file':
254
290
  baseType = 'File';
255
291
  break;
292
+ case 'null': // Add this
293
+ baseType = 'null';
294
+ break;
256
295
  default:
257
296
  baseType = 'any';
258
297
  break;
@@ -339,9 +378,15 @@ function removeDirectory(dirPath) {
339
378
  async function loadSwaggerDocument(input) {
340
379
  try {
341
380
  if (input.startsWith('http://') || input.startsWith('https://')) {
342
- // 从URL加载
343
- const response = await axios_1.default.get(input);
344
- return response.data;
381
+ const { data } = await axios_1.default.get(input);
382
+ console.log('Loaded from URL:', input);
383
+ if (data.components?.schemas) {
384
+ console.log('Schemas count:', Object.keys(data.components.schemas).length);
385
+ }
386
+ else {
387
+ console.log('No schemas in loaded data');
388
+ }
389
+ return data;
345
390
  }
346
391
  else {
347
392
  // 从文件加载
@@ -390,8 +435,8 @@ function generateApiComment(operation, parameters) {
390
435
  // 如果有查询参数或路径参数,添加params注释
391
436
  if (hasParams) {
392
437
  const paramDescriptions = [...pathParams, ...queryParams]
393
- .map(p => p.description || '')
394
- .filter(desc => desc)
438
+ .map((p) => p.description || '')
439
+ .filter((desc) => desc)
395
440
  .join(', ');
396
441
  const description = paramDescriptions || '请求参数';
397
442
  comments.push(` * @param params ${description}`);
@@ -426,6 +471,9 @@ function sanitizeFilename(filename) {
426
471
  * @returns TypeScript类型字符串
427
472
  */
428
473
  function getResponseType(responses) {
474
+ if (!responses) {
475
+ return 'any';
476
+ }
429
477
  // 优先获取200响应
430
478
  const successResponse = responses['200'] || responses['201'] || responses['default'];
431
479
  if (!successResponse) {
@@ -443,3 +491,12 @@ function getResponseType(responses) {
443
491
  }
444
492
  return 'any';
445
493
  }
494
+ function sanitizeTypeName(name) {
495
+ if (!name)
496
+ return name;
497
+ // 1. 替换非法字符(包括点号)为下划线
498
+ const replaced = name.replace(/[^a-zA-Z0-9_]/g, '_');
499
+ // 2. 转换为 PascalCase
500
+ // 使用现有的 toPascalCase,它能处理下划线
501
+ return toPascalCase(replaced);
502
+ }
package/package.json CHANGED
@@ -1,68 +1,68 @@
1
- {
2
- "name": "swagger2api-v3",
3
- "version": "1.1.1",
4
- "description": "A command-line tool for generating TypeScript API interfaces from Swagger (OAS 3.0) documentation",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "type": "commonjs",
8
- "bin": {
9
- "swagger2api-v3": "dist/cli/index.js"
10
- },
11
- "files": [
12
- "dist",
13
- "README.md",
14
- "package.json"
15
- ],
16
- "scripts": {
17
- "test": "jest",
18
- "test:watch": "jest --watch",
19
- "test:coverage": "jest --coverage",
20
- "test:ci": "jest --ci --coverage --watchAll=false",
21
- "build": "tsc",
22
- "clean": "rimraf dist",
23
- "prebuild": "npm run clean",
24
- "start": "node dist/cli/index.js",
25
- "dev": "npm run build && npm start",
26
- "lint": "prettier --write",
27
- "generate": "npm run build && node dist/cli/index.js generate",
28
- "init": "npm run build && node dist/cli/index.js init",
29
- "validate": "npm run build && node dist/cli/index.js validate",
30
- "swagger:generate": "npm run generate",
31
- "swagger:run": "npm run generate",
32
- "swagger:init": "npm run init",
33
- "swagger:validate": "npm run validate"
34
- },
35
- "keywords": [
36
- "swagger",
37
- "openapi",
38
- "typescript",
39
- "api",
40
- "generator",
41
- "cli",
42
- "code-generation"
43
- ],
44
- "author": "xiaoyang",
45
- "license": "MIT",
46
- "homepage": "https://github.com/xiaoyang33/swagger2api-v3#readme",
47
- "repository": {
48
- "type": "git",
49
- "url": "https://github.com/xiaoyang33/swagger2api-v3.git"
50
- },
51
- "bugs": {
52
- "url": "https://github.com/xiaoyang33/swagger2api-v3/issues"
53
- },
54
- "packageManager": "pnpm@10.11.0",
55
- "devDependencies": {
56
- "@types/jest": "^29.5.0",
57
- "@types/node": "^24.3.1",
58
- "jest": "^29.5.0",
59
- "prettier": "^3.6.2",
60
- "rimraf": "^6.0.1",
61
- "ts-jest": "^29.1.0",
62
- "typescript": "^5.9.2"
63
- },
64
- "dependencies": {
65
- "axios": "^1.11.0",
66
- "commander": "^12.0.0"
67
- }
68
- }
1
+ {
2
+ "name": "swagger2api-v3",
3
+ "version": "1.1.3",
4
+ "description": "A command-line tool for generating TypeScript API interfaces from Swagger (OAS 3.0) documentation",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "commonjs",
8
+ "bin": {
9
+ "swagger2api-v3": "dist/cli/index.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "package.json"
15
+ ],
16
+ "scripts": {
17
+ "test": "jest",
18
+ "test:watch": "jest --watch",
19
+ "test:coverage": "jest --coverage",
20
+ "test:ci": "jest --ci --coverage --watchAll=false",
21
+ "build": "tsc",
22
+ "clean": "rimraf dist",
23
+ "prebuild": "npm run clean",
24
+ "start": "node dist/cli/index.js",
25
+ "dev": "npm run build && npm start",
26
+ "lint": "prettier --write",
27
+ "generate": "npm run build && node dist/cli/index.js generate",
28
+ "init": "npm run build && node dist/cli/index.js init",
29
+ "validate": "npm run build && node dist/cli/index.js validate",
30
+ "swagger:generate": "npm run generate",
31
+ "swagger:run": "npm run generate",
32
+ "swagger:init": "npm run init",
33
+ "swagger:validate": "npm run validate"
34
+ },
35
+ "keywords": [
36
+ "swagger",
37
+ "openapi",
38
+ "typescript",
39
+ "api",
40
+ "generator",
41
+ "cli",
42
+ "code-generation"
43
+ ],
44
+ "author": "xiaoyang",
45
+ "license": "MIT",
46
+ "homepage": "https://github.com/xiaoyang33/swagger2api-v3#readme",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "https://github.com/xiaoyang33/swagger2api-v3.git"
50
+ },
51
+ "bugs": {
52
+ "url": "https://github.com/xiaoyang33/swagger2api-v3/issues"
53
+ },
54
+ "packageManager": "pnpm@10.11.0",
55
+ "devDependencies": {
56
+ "@types/jest": "^29.5.0",
57
+ "@types/node": "^24.3.1",
58
+ "jest": "^29.5.0",
59
+ "prettier": "^3.6.2",
60
+ "rimraf": "^6.0.1",
61
+ "ts-jest": "^29.1.0",
62
+ "typescript": "^5.9.2"
63
+ },
64
+ "dependencies": {
65
+ "axios": "^1.11.0",
66
+ "commander": "^12.0.0"
67
+ }
68
+ }