swagger2api-v3 1.1.7 → 1.1.8
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 +15 -1
- package/dist/.swagger2api.schema.json +120 -0
- package/dist/cli/index.js +119 -47
- package/dist/config/validator.d.ts +7 -0
- package/dist/config/validator.js +218 -0
- package/dist/core/generator.d.ts +7 -1
- package/dist/core/generator.js +26 -44
- package/dist/core/parser.d.ts +13 -1
- package/dist/core/parser.js +54 -40
- package/dist/index.d.ts +6 -0
- package/dist/index.js +21 -13
- package/dist/types/index.d.ts +75 -38
- package/dist/utils/comment.d.ts +8 -0
- package/dist/utils/comment.js +47 -0
- package/dist/utils/file.d.ts +23 -0
- package/dist/utils/file.js +98 -0
- package/dist/utils/index.d.ts +4 -99
- package/dist/utils/index.js +6 -566
- package/dist/utils/naming.d.ts +51 -0
- package/dist/utils/naming.js +124 -0
- package/dist/utils/type.d.ts +39 -0
- package/dist/utils/type.js +331 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -37,7 +37,8 @@ The tool generates a `.swagger.config.json` configuration file:
|
|
|
37
37
|
|
|
38
38
|
```json
|
|
39
39
|
{
|
|
40
|
-
"
|
|
40
|
+
"$schema": "./node_modules/swagger2api-v3/dist/.swagger2api.schema.json",
|
|
41
|
+
"input": "https://petstore3.swagger.io/api/v3/openapi.json",
|
|
41
42
|
"output": "./src/api",
|
|
42
43
|
"importTemplate": "import { request } from '@/utils/request';",
|
|
43
44
|
"generator": "typescript",
|
|
@@ -48,6 +49,15 @@ The tool generates a `.swagger.config.json` configuration file:
|
|
|
48
49
|
"lint": "prettier --write",
|
|
49
50
|
"methodNameIgnorePrefix": [],
|
|
50
51
|
"addMethodSuffix": true,
|
|
52
|
+
"headerComment": "",
|
|
53
|
+
"filter": {
|
|
54
|
+
"include": {
|
|
55
|
+
"tags": []
|
|
56
|
+
},
|
|
57
|
+
"exclude": {
|
|
58
|
+
"tags": []
|
|
59
|
+
}
|
|
60
|
+
},
|
|
51
61
|
"options": {
|
|
52
62
|
"addComments": true
|
|
53
63
|
}
|
|
@@ -64,6 +74,7 @@ npx swagger2api-v3 generate
|
|
|
64
74
|
|
|
65
75
|
| Option | Type | Default | Description |
|
|
66
76
|
| ------------------------ | --------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
77
|
+
| `$schema` | string | - | Local JSON Schema path for editor completion. The default points to `node_modules/swagger2api-v3/dist/.swagger2api.schema.json` |
|
|
67
78
|
| `input` | string | - | Swagger JSON file path or URL |
|
|
68
79
|
| `output` | string | `'./src/api'` | Output directory for generated code |
|
|
69
80
|
| `generator` | string | `'typescript'` | Code generator type. Supports `'typescript'` and `'javascript'`. `'javascript'` outputs `.js` files and skips type file generation |
|
|
@@ -75,6 +86,9 @@ npx swagger2api-v3 generate
|
|
|
75
86
|
| `lint` | string | - | Code formatting command (optional) |
|
|
76
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` |
|
|
77
88
|
| `addMethodSuffix` | boolean | `true` | Whether to add HTTP method suffix to generated function names. `true` generates `userListPost`, `false` generates `userList` |
|
|
89
|
+
| `headerComment` | string | - | Custom header comment for generated `types`, API, and index files |
|
|
90
|
+
| `filter.include.tags` | string[] | `[]` | Only generate APIs whose tags match this list. Empty means include all |
|
|
91
|
+
| `filter.exclude.tags` | string[] | `[]` | Skip APIs whose tags match this list. Exclude rules take priority over include rules |
|
|
78
92
|
| `options.addComments` | boolean | `true` | Whether to add detailed comments |
|
|
79
93
|
|
|
80
94
|
## 📁 Generated File Structure
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "swagger2api-v3 config",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"required": ["input", "output", "generator", "groupByTags"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "本地 JSON Schema 路径,用于编辑器提示"
|
|
10
|
+
},
|
|
11
|
+
"input": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "OpenAPI JSON 文件路径或 URL"
|
|
14
|
+
},
|
|
15
|
+
"output": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "生成代码输出目录"
|
|
18
|
+
},
|
|
19
|
+
"generator": {
|
|
20
|
+
"enum": ["typescript", "javascript"],
|
|
21
|
+
"description": "生成器类型"
|
|
22
|
+
},
|
|
23
|
+
"groupByTags": {
|
|
24
|
+
"type": "boolean",
|
|
25
|
+
"description": "是否按 tags 分组生成文件"
|
|
26
|
+
},
|
|
27
|
+
"overwrite": {
|
|
28
|
+
"type": "boolean",
|
|
29
|
+
"description": "生成前是否覆盖输出目录"
|
|
30
|
+
},
|
|
31
|
+
"prefix": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "接口路径公共前缀"
|
|
34
|
+
},
|
|
35
|
+
"requestStyle": {
|
|
36
|
+
"enum": ["method", "generic"],
|
|
37
|
+
"description": "请求调用风格"
|
|
38
|
+
},
|
|
39
|
+
"importTemplate": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "request 导入语句"
|
|
42
|
+
},
|
|
43
|
+
"lint": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"description": "生成后执行的格式化命令"
|
|
46
|
+
},
|
|
47
|
+
"methodNameIgnorePrefix": {
|
|
48
|
+
"type": "array",
|
|
49
|
+
"items": { "type": "string" },
|
|
50
|
+
"description": "生成方法名时需要忽略的前缀"
|
|
51
|
+
},
|
|
52
|
+
"addMethodSuffix": {
|
|
53
|
+
"type": "boolean",
|
|
54
|
+
"description": "是否在方法名中追加 HTTP method 后缀"
|
|
55
|
+
},
|
|
56
|
+
"headerComment": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"description": "自定义生成文件头部注释"
|
|
59
|
+
},
|
|
60
|
+
"filter": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"additionalProperties": false,
|
|
63
|
+
"properties": {
|
|
64
|
+
"include": {
|
|
65
|
+
"type": "object",
|
|
66
|
+
"additionalProperties": false,
|
|
67
|
+
"properties": {
|
|
68
|
+
"tags": {
|
|
69
|
+
"type": "array",
|
|
70
|
+
"items": { "type": "string" }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"exclude": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"additionalProperties": false,
|
|
77
|
+
"properties": {
|
|
78
|
+
"tags": {
|
|
79
|
+
"type": "array",
|
|
80
|
+
"items": { "type": "string" }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"tagGrouping": {
|
|
87
|
+
"type": "object",
|
|
88
|
+
"additionalProperties": false,
|
|
89
|
+
"properties": {
|
|
90
|
+
"enabled": { "type": "boolean" },
|
|
91
|
+
"createSubDirectories": { "type": "boolean" },
|
|
92
|
+
"fileNaming": {
|
|
93
|
+
"enum": ["tag", "kebab-case", "camelCase"]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"options": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"additionalProperties": false,
|
|
100
|
+
"properties": {
|
|
101
|
+
"generateModels": { "type": "boolean" },
|
|
102
|
+
"generateApis": { "type": "boolean" },
|
|
103
|
+
"generateIndex": { "type": "boolean" },
|
|
104
|
+
"useAxios": { "type": "boolean" },
|
|
105
|
+
"addComments": { "type": "boolean" },
|
|
106
|
+
"prettify": { "type": "boolean" }
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"comments": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"additionalProperties": false,
|
|
112
|
+
"properties": {
|
|
113
|
+
"includeDescription": { "type": "boolean" },
|
|
114
|
+
"includeParameters": { "type": "boolean" },
|
|
115
|
+
"includeResponses": { "type": "boolean" },
|
|
116
|
+
"includeExamples": { "type": "boolean" }
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -93,29 +93,12 @@ program
|
|
|
93
93
|
.option('-f, --force', '强制覆盖已存在的配置文件')
|
|
94
94
|
.action(async (options) => {
|
|
95
95
|
const configPath = path.resolve(process.cwd(), '.swagger.config.json');
|
|
96
|
-
if (fs.existsSync(configPath) && !options.force) {
|
|
97
|
-
console.error('❌ 配置文件已存在,使用 --force 参数强制覆盖');
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
const config = {
|
|
101
|
-
input: 'http://localhost:3000/admin/docs/json',
|
|
102
|
-
output: './src/api',
|
|
103
|
-
importTemplate: "import { request } from '@/utils/request';",
|
|
104
|
-
generator: 'typescript',
|
|
105
|
-
requestStyle: 'generic',
|
|
106
|
-
groupByTags: true,
|
|
107
|
-
overwrite: true,
|
|
108
|
-
prefix: '',
|
|
109
|
-
lint: 'prettier --write',
|
|
110
|
-
methodNameIgnorePrefix: [],
|
|
111
|
-
addMethodSuffix: true,
|
|
112
|
-
options: {
|
|
113
|
-
addComments: true
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
96
|
try {
|
|
97
|
+
const existsBeforeInit = fs.existsSync(configPath);
|
|
98
|
+
const config = createInitConfig(configPath, options.force);
|
|
99
|
+
const successMessage = getInitSuccessMessage(existsBeforeInit, options.force);
|
|
117
100
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
118
|
-
console.log(
|
|
101
|
+
console.log(successMessage, configPath);
|
|
119
102
|
console.log('💡 请根据需要修改配置文件,然后运行 swagger2api-v3 generate');
|
|
120
103
|
}
|
|
121
104
|
catch (error) {
|
|
@@ -137,21 +120,14 @@ program
|
|
|
137
120
|
}
|
|
138
121
|
const configContent = fs.readFileSync(configPath, 'utf-8');
|
|
139
122
|
const config = JSON.parse(configContent);
|
|
140
|
-
const {
|
|
141
|
-
const
|
|
142
|
-
if (
|
|
123
|
+
const { validateSwaggerConfig } = await Promise.resolve().then(() => __importStar(require('../config/validator')));
|
|
124
|
+
const errors = validateSwaggerConfig(config);
|
|
125
|
+
if (errors.length === 0) {
|
|
143
126
|
console.log('✅ 配置文件验证通过');
|
|
144
|
-
// 尝试加载 Swagger 文档
|
|
145
|
-
try {
|
|
146
|
-
const { loadSwaggerDocument } = await Promise.resolve().then(() => __importStar(require('../utils')));
|
|
147
|
-
const document = await loadSwaggerDocument(config.input);
|
|
148
|
-
console.log(`✅ Swagger 文档加载成功: ${document.info.title} v${document.info.version}`);
|
|
149
|
-
}
|
|
150
|
-
catch (error) {
|
|
151
|
-
console.warn('⚠️ Swagger 文档加载失败:', error);
|
|
152
|
-
}
|
|
153
127
|
}
|
|
154
128
|
else {
|
|
129
|
+
console.error('❌ 配置验证失败:');
|
|
130
|
+
errors.forEach((error) => console.error(` - ${error}`));
|
|
155
131
|
process.exit(1);
|
|
156
132
|
}
|
|
157
133
|
}
|
|
@@ -166,23 +142,119 @@ program
|
|
|
166
142
|
process.exit(1);
|
|
167
143
|
}
|
|
168
144
|
});
|
|
169
|
-
// run 命令(别名,兼容性)
|
|
170
|
-
program
|
|
171
|
-
.command('run')
|
|
172
|
-
.description('运行生成器(generate 命令的别名)')
|
|
173
|
-
.option('-c, --config <path>', '配置文件路径', '.swagger.config.json')
|
|
174
|
-
.action(async (options) => {
|
|
175
|
-
try {
|
|
176
|
-
await (0, index_1.generateFromConfig)(options.config);
|
|
177
|
-
}
|
|
178
|
-
catch (error) {
|
|
179
|
-
console.error('❌ 生成失败:', error);
|
|
180
|
-
process.exit(1);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
145
|
// 解析命令行参数
|
|
184
146
|
program.parse();
|
|
185
147
|
// 如果没有提供命令,显示帮助信息
|
|
186
148
|
if (!process.argv.slice(2).length) {
|
|
187
149
|
program.outputHelp();
|
|
188
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* 创建 init 命令需要写入的配置
|
|
153
|
+
* @param configPath 配置文件路径
|
|
154
|
+
* @param force 是否强制覆盖
|
|
155
|
+
* @returns 初始化配置对象
|
|
156
|
+
*/
|
|
157
|
+
function createInitConfig(configPath, force) {
|
|
158
|
+
const defaultConfig = createDefaultConfig();
|
|
159
|
+
if (!fs.existsSync(configPath) || force) {
|
|
160
|
+
return defaultConfig;
|
|
161
|
+
}
|
|
162
|
+
const existingConfig = readExistingConfig(configPath);
|
|
163
|
+
return mergeMissingConfig(existingConfig, defaultConfig);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* 创建默认配置对象
|
|
167
|
+
* @returns 默认配置对象
|
|
168
|
+
*/
|
|
169
|
+
function createDefaultConfig() {
|
|
170
|
+
return {
|
|
171
|
+
$schema: './node_modules/swagger2api-v3/dist/.swagger2api.schema.json',
|
|
172
|
+
input: 'http://localhost:3000/admin/docs/json',
|
|
173
|
+
output: './src/api',
|
|
174
|
+
importTemplate: "import { request } from '@/utils/request';",
|
|
175
|
+
generator: 'typescript',
|
|
176
|
+
requestStyle: 'generic',
|
|
177
|
+
groupByTags: true,
|
|
178
|
+
overwrite: true,
|
|
179
|
+
prefix: '',
|
|
180
|
+
lint: 'prettier --write',
|
|
181
|
+
methodNameIgnorePrefix: [],
|
|
182
|
+
addMethodSuffix: true,
|
|
183
|
+
headerComment: '',
|
|
184
|
+
filter: {
|
|
185
|
+
include: {
|
|
186
|
+
tags: []
|
|
187
|
+
},
|
|
188
|
+
exclude: {
|
|
189
|
+
tags: []
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
options: {
|
|
193
|
+
addComments: true
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* 获取 init 命令成功提示
|
|
199
|
+
* @param existsBeforeInit 执行 init 前配置文件是否存在
|
|
200
|
+
* @param force 是否强制覆盖
|
|
201
|
+
* @returns 成功提示文案
|
|
202
|
+
*/
|
|
203
|
+
function getInitSuccessMessage(existsBeforeInit, force) {
|
|
204
|
+
if (existsBeforeInit && force) {
|
|
205
|
+
return '✅ 配置文件已覆盖:';
|
|
206
|
+
}
|
|
207
|
+
if (existsBeforeInit) {
|
|
208
|
+
return '✅ 配置文件已补全:';
|
|
209
|
+
}
|
|
210
|
+
return '✅ 配置文件已创建:';
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 读取已存在的配置文件
|
|
214
|
+
* @param configPath 配置文件路径
|
|
215
|
+
* @returns 已存在的配置对象
|
|
216
|
+
*/
|
|
217
|
+
function readExistingConfig(configPath) {
|
|
218
|
+
try {
|
|
219
|
+
const configContent = fs.readFileSync(configPath, 'utf-8');
|
|
220
|
+
return JSON.parse(configContent);
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
if (error instanceof SyntaxError) {
|
|
224
|
+
console.error(`❌ 配置文件 JSON 格式错误: ${configPath}`);
|
|
225
|
+
console.error('错误详情:', error.message);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
console.error('❌ 读取配置文件失败:', error);
|
|
229
|
+
}
|
|
230
|
+
process.exit(1);
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* 合并缺失的配置字段,保留已有配置值
|
|
236
|
+
* @param current 当前配置
|
|
237
|
+
* @param defaults 默认配置
|
|
238
|
+
* @returns 补全后的配置
|
|
239
|
+
*/
|
|
240
|
+
function mergeMissingConfig(current, defaults) {
|
|
241
|
+
const result = { ...current };
|
|
242
|
+
for (const [key, value] of Object.entries(defaults)) {
|
|
243
|
+
if (result[key] === undefined) {
|
|
244
|
+
result[key] = value;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (isPlainObject(result[key]) && isPlainObject(value)) {
|
|
248
|
+
result[key] = mergeMissingConfig(result[key], value);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return result;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* 判断是否为普通对象
|
|
255
|
+
* @param value 待判断的值
|
|
256
|
+
* @returns 是否为普通对象
|
|
257
|
+
*/
|
|
258
|
+
function isPlainObject(value) {
|
|
259
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
260
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateSwaggerConfig = validateSwaggerConfig;
|
|
4
|
+
const CONFIG_KEYS = [
|
|
5
|
+
'$schema',
|
|
6
|
+
'input',
|
|
7
|
+
'output',
|
|
8
|
+
'generator',
|
|
9
|
+
'groupByTags',
|
|
10
|
+
'overwrite',
|
|
11
|
+
'prefix',
|
|
12
|
+
'requestStyle',
|
|
13
|
+
'tagGrouping',
|
|
14
|
+
'options',
|
|
15
|
+
'comments',
|
|
16
|
+
'importTemplate',
|
|
17
|
+
'lint',
|
|
18
|
+
'methodNameIgnorePrefix',
|
|
19
|
+
'addMethodSuffix',
|
|
20
|
+
'filter',
|
|
21
|
+
'headerComment'
|
|
22
|
+
];
|
|
23
|
+
const OPTIONS_KEYS = [
|
|
24
|
+
'generateModels',
|
|
25
|
+
'generateApis',
|
|
26
|
+
'generateIndex',
|
|
27
|
+
'useAxios',
|
|
28
|
+
'addComments',
|
|
29
|
+
'prettify'
|
|
30
|
+
];
|
|
31
|
+
const TAG_GROUPING_KEYS = ['enabled', 'createSubDirectories', 'fileNaming'];
|
|
32
|
+
const COMMENT_KEYS = [
|
|
33
|
+
'includeDescription',
|
|
34
|
+
'includeParameters',
|
|
35
|
+
'includeResponses',
|
|
36
|
+
'includeExamples'
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* 验证配置对象
|
|
40
|
+
* @param config 配置对象
|
|
41
|
+
* @returns 错误信息数组
|
|
42
|
+
*/
|
|
43
|
+
function validateSwaggerConfig(config) {
|
|
44
|
+
const errors = [];
|
|
45
|
+
validateRequiredString(config.input, 'input', errors);
|
|
46
|
+
validateRequiredString(config.output, 'output', errors);
|
|
47
|
+
validateEnum(config.generator, 'generator', ['typescript', 'javascript'], errors);
|
|
48
|
+
validateBoolean(config.groupByTags, 'groupByTags', errors);
|
|
49
|
+
validateOptionalBoolean(config.overwrite, 'overwrite', errors);
|
|
50
|
+
validateOptionalString(config.prefix, 'prefix', errors);
|
|
51
|
+
validateOptionalString(config.importTemplate, 'importTemplate', errors);
|
|
52
|
+
validateOptionalString(config.lint, 'lint', errors);
|
|
53
|
+
validateOptionalString(config.headerComment, 'headerComment', errors);
|
|
54
|
+
validateOptionalString(config.$schema, '$schema', errors);
|
|
55
|
+
validateOptionalBoolean(config.addMethodSuffix, 'addMethodSuffix', errors);
|
|
56
|
+
validateOptionalEnum(config.requestStyle, 'requestStyle', ['method', 'generic'], errors);
|
|
57
|
+
validateStringArray(config.methodNameIgnorePrefix, 'methodNameIgnorePrefix', errors);
|
|
58
|
+
validateFilter(config, errors);
|
|
59
|
+
validateOptions(config, errors);
|
|
60
|
+
validateTagGrouping(config, errors);
|
|
61
|
+
validateComments(config, errors);
|
|
62
|
+
validateKnownKeys(config, CONFIG_KEYS, 'config', errors);
|
|
63
|
+
return errors;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 验证必填字符串
|
|
67
|
+
* @param value 字段值
|
|
68
|
+
* @param field 字段名
|
|
69
|
+
* @param errors 错误信息数组
|
|
70
|
+
*/
|
|
71
|
+
function validateRequiredString(value, field, errors) {
|
|
72
|
+
if (typeof value !== 'string' || !value) {
|
|
73
|
+
errors.push(`${field} 配置项不能为空,且必须是字符串`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 验证可选字符串
|
|
78
|
+
* @param value 字段值
|
|
79
|
+
* @param field 字段名
|
|
80
|
+
* @param errors 错误信息数组
|
|
81
|
+
*/
|
|
82
|
+
function validateOptionalString(value, field, errors) {
|
|
83
|
+
if (value !== undefined && typeof value !== 'string') {
|
|
84
|
+
errors.push(`${field} 必须是字符串`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 验证布尔值
|
|
89
|
+
* @param value 字段值
|
|
90
|
+
* @param field 字段名
|
|
91
|
+
* @param errors 错误信息数组
|
|
92
|
+
*/
|
|
93
|
+
function validateBoolean(value, field, errors) {
|
|
94
|
+
if (typeof value !== 'boolean') {
|
|
95
|
+
errors.push(`${field} 必须是布尔值`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 验证可选布尔值
|
|
100
|
+
* @param value 字段值
|
|
101
|
+
* @param field 字段名
|
|
102
|
+
* @param errors 错误信息数组
|
|
103
|
+
*/
|
|
104
|
+
function validateOptionalBoolean(value, field, errors) {
|
|
105
|
+
if (value !== undefined && typeof value !== 'boolean') {
|
|
106
|
+
errors.push(`${field} 必须是布尔值`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 验证枚举值
|
|
111
|
+
* @param value 字段值
|
|
112
|
+
* @param field 字段名
|
|
113
|
+
* @param values 允许值
|
|
114
|
+
* @param errors 错误信息数组
|
|
115
|
+
*/
|
|
116
|
+
function validateEnum(value, field, values, errors) {
|
|
117
|
+
if (typeof value !== 'string' || !values.includes(value)) {
|
|
118
|
+
errors.push(`${field} 必须是 ${values.join(' 或 ')}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 验证可选枚举值
|
|
123
|
+
* @param value 字段值
|
|
124
|
+
* @param field 字段名
|
|
125
|
+
* @param values 允许值
|
|
126
|
+
* @param errors 错误信息数组
|
|
127
|
+
*/
|
|
128
|
+
function validateOptionalEnum(value, field, values, errors) {
|
|
129
|
+
if (value !== undefined) {
|
|
130
|
+
validateEnum(value, field, values, errors);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 验证字符串数组
|
|
135
|
+
* @param value 字段值
|
|
136
|
+
* @param field 字段名
|
|
137
|
+
* @param errors 错误信息数组
|
|
138
|
+
*/
|
|
139
|
+
function validateStringArray(value, field, errors) {
|
|
140
|
+
if (value === undefined)
|
|
141
|
+
return;
|
|
142
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {
|
|
143
|
+
errors.push(`${field} 必须是字符串数组`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 验证过滤配置
|
|
148
|
+
* @param config 配置对象
|
|
149
|
+
* @param errors 错误信息数组
|
|
150
|
+
*/
|
|
151
|
+
function validateFilter(config, errors) {
|
|
152
|
+
if (!config.filter)
|
|
153
|
+
return;
|
|
154
|
+
validateKnownKeys(config.filter, ['include', 'exclude'], 'filter', errors);
|
|
155
|
+
validateKnownKeys(config.filter.include, ['tags'], 'filter.include', errors);
|
|
156
|
+
validateKnownKeys(config.filter.exclude, ['tags'], 'filter.exclude', errors);
|
|
157
|
+
validateStringArray(config.filter.include?.tags, 'filter.include.tags', errors);
|
|
158
|
+
validateStringArray(config.filter.exclude?.tags, 'filter.exclude.tags', errors);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* 验证生成选项配置
|
|
162
|
+
* @param config 配置对象
|
|
163
|
+
* @param errors 错误信息数组
|
|
164
|
+
*/
|
|
165
|
+
function validateOptions(config, errors) {
|
|
166
|
+
if (!config.options)
|
|
167
|
+
return;
|
|
168
|
+
validateKnownKeys(config.options, OPTIONS_KEYS, 'options', errors);
|
|
169
|
+
validateOptionalBoolean(config.options.generateModels, 'options.generateModels', errors);
|
|
170
|
+
validateOptionalBoolean(config.options.generateApis, 'options.generateApis', errors);
|
|
171
|
+
validateOptionalBoolean(config.options.generateIndex, 'options.generateIndex', errors);
|
|
172
|
+
validateOptionalBoolean(config.options.useAxios, 'options.useAxios', errors);
|
|
173
|
+
validateOptionalBoolean(config.options.addComments, 'options.addComments', errors);
|
|
174
|
+
validateOptionalBoolean(config.options.prettify, 'options.prettify', errors);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* 验证标签分组选项
|
|
178
|
+
* @param config 配置对象
|
|
179
|
+
* @param errors 错误信息数组
|
|
180
|
+
*/
|
|
181
|
+
function validateTagGrouping(config, errors) {
|
|
182
|
+
if (!config.tagGrouping)
|
|
183
|
+
return;
|
|
184
|
+
validateKnownKeys(config.tagGrouping, TAG_GROUPING_KEYS, 'tagGrouping', errors);
|
|
185
|
+
validateOptionalBoolean(config.tagGrouping.enabled, 'tagGrouping.enabled', errors);
|
|
186
|
+
validateOptionalBoolean(config.tagGrouping.createSubDirectories, 'tagGrouping.createSubDirectories', errors);
|
|
187
|
+
validateOptionalEnum(config.tagGrouping.fileNaming, 'tagGrouping.fileNaming', ['tag', 'kebab-case', 'camelCase'], errors);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* 验证注释配置
|
|
191
|
+
* @param config 配置对象
|
|
192
|
+
* @param errors 错误信息数组
|
|
193
|
+
*/
|
|
194
|
+
function validateComments(config, errors) {
|
|
195
|
+
if (!config.comments)
|
|
196
|
+
return;
|
|
197
|
+
validateKnownKeys(config.comments, COMMENT_KEYS, 'comments', errors);
|
|
198
|
+
validateOptionalBoolean(config.comments.includeDescription, 'comments.includeDescription', errors);
|
|
199
|
+
validateOptionalBoolean(config.comments.includeParameters, 'comments.includeParameters', errors);
|
|
200
|
+
validateOptionalBoolean(config.comments.includeResponses, 'comments.includeResponses', errors);
|
|
201
|
+
validateOptionalBoolean(config.comments.includeExamples, 'comments.includeExamples', errors);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* 验证未知字段
|
|
205
|
+
* @param value 对象值
|
|
206
|
+
* @param knownKeys 允许字段列表
|
|
207
|
+
* @param path 对象路径
|
|
208
|
+
* @param errors 错误信息数组
|
|
209
|
+
*/
|
|
210
|
+
function validateKnownKeys(value, knownKeys, path, errors) {
|
|
211
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
212
|
+
return;
|
|
213
|
+
for (const key of Object.keys(value)) {
|
|
214
|
+
if (!knownKeys.includes(key)) {
|
|
215
|
+
errors.push(`${path}.${key} 不是支持的配置项`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
package/dist/core/generator.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export declare class CodeGenerator {
|
|
|
51
51
|
private generateApiFunction;
|
|
52
52
|
/**
|
|
53
53
|
* 生成直接参数形式
|
|
54
|
-
* @param parameters
|
|
54
|
+
* @param parameters OpenAPI 参数数组
|
|
55
55
|
* @returns 函数参数字符串
|
|
56
56
|
*/
|
|
57
57
|
private generateDirectParameters;
|
|
@@ -104,6 +104,12 @@ export declare class CodeGenerator {
|
|
|
104
104
|
* @returns 文件名
|
|
105
105
|
*/
|
|
106
106
|
private getTagFileName;
|
|
107
|
+
/**
|
|
108
|
+
* 生成文件头部注释
|
|
109
|
+
* @param defaultHeader 默认头部注释
|
|
110
|
+
* @returns 文件头部注释内容
|
|
111
|
+
*/
|
|
112
|
+
private generateHeader;
|
|
107
113
|
/**
|
|
108
114
|
* 在所有文件生成完成后运行lint命令
|
|
109
115
|
*/
|