openapi-ts-request 1.9.1 → 1.10.0
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 +13 -8
- package/dist/bin/cli.js +38 -7
- package/dist/bin/openapi.js +33 -16
- package/dist/generator/serviceGenarator.js +10 -6
- package/dist/index.d.ts +8 -0
- package/dist/index.js +7 -0
- package/dist/log.js +2 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -45,19 +45,20 @@ pnpm i openapi-ts-request -D
|
|
|
45
45
|
> 配置文件还支持 **_.openapi-ts-request.ts_**, **_openapi-ts-request.config.cjs_** 等格式,参考 [cosmiconfig](https://github.com/cosmiconfig/cosmiconfig?tab=readme-ov-file#cosmiconfig)
|
|
46
46
|
|
|
47
47
|
```ts
|
|
48
|
-
import
|
|
48
|
+
import { defineConfig } from 'openapi-ts-request';
|
|
49
49
|
|
|
50
|
-
export default {
|
|
50
|
+
export default defineConfig({
|
|
51
51
|
schemaPath: 'http://petstore.swagger.io/v2/swagger.json',
|
|
52
|
-
|
|
52
|
+
serversPath: './src/apis',
|
|
53
|
+
});
|
|
53
54
|
```
|
|
54
55
|
|
|
55
56
|
支持传入数组配置进行生成
|
|
56
57
|
|
|
57
58
|
```ts
|
|
58
|
-
import
|
|
59
|
+
import { defineConfig } from 'openapi-ts-request';
|
|
59
60
|
|
|
60
|
-
export default [
|
|
61
|
+
export default defineConfig([
|
|
61
62
|
{
|
|
62
63
|
schemaPath: 'http://app.swagger.io/v2/swagger.json',
|
|
63
64
|
serversPath: './src/apis/app',
|
|
@@ -66,7 +67,7 @@ export default [
|
|
|
66
67
|
schemaPath: 'http://auth.swagger.io/v2/swagger.json',
|
|
67
68
|
serversPath: './src/apis/auth',
|
|
68
69
|
},
|
|
69
|
-
]
|
|
70
|
+
]);
|
|
70
71
|
```
|
|
71
72
|
|
|
72
73
|
在 `package.json` 的 `script` 中添加命令: `"openapi": "openapi-ts",`
|
|
@@ -190,7 +191,7 @@ $ openapi --help
|
|
|
190
191
|
-f, --full <boolean> full replacement (default: true)
|
|
191
192
|
--enableLogging <boolean> open the log (default: false)
|
|
192
193
|
--priorityRule <string> priority rule, include/exclude/both (default: "include")
|
|
193
|
-
--filterCaseInsensitive <boolean> whether to perform a case-insensitive match with includeTags, includePaths, excludeTags, excludePaths filters
|
|
194
|
+
--filterCaseInsensitive <boolean> whether to perform a case-insensitive match with includeTags, includePaths, excludeTags, excludePaths filters (default: false)
|
|
194
195
|
--includeTags <(string|RegExp)[]> generate code from include tags
|
|
195
196
|
--includePaths <(string|RegExp)[]> generate code from include paths
|
|
196
197
|
--excludeTags <(string|RegExp)[]> generate code from exclude tags
|
|
@@ -227,6 +228,7 @@ openapi --i ./spec.json --o ./apis
|
|
|
227
228
|
| serversPath | 否 | string | './src/apis' | 运行结果文件夹路径 |
|
|
228
229
|
| requestLibPath | 否 | string | 'axios' | 自定义请求方法路径,例如:'@/request'、'node-fetch' |
|
|
229
230
|
| full | 否 | boolean | true | 是否全量替换 |
|
|
231
|
+
| describe | 否 | string | - | 描述信息,在用 cli 可交互运行方式时会用到 |
|
|
230
232
|
| enableLogging | 否 | boolean | false | 是否开启日志 |
|
|
231
233
|
| priorityRule | 否 | string | 'include' | 模式规则,可选include/exclude/both |
|
|
232
234
|
| filterCaseInsensitive | 否 | boolean | false | 执行 includeTags、includePaths、excludeTags、excludePaths 过滤时是否忽略大小写 |
|
|
@@ -266,6 +268,8 @@ openapi --i ./spec.json --o ./apis
|
|
|
266
268
|
| customTemplates | {<br>[TypescriptFileType.serviceController]?: <T, U>(item: T, context: U) => string;<br>} | 自定义模板,详情请看源码 |
|
|
267
269
|
| customRenderTemplateData | {<br>[TypescriptFileType]?: (list: any[], context: {fileName: string, params: Record<string, unknown>}) => any[]<br>} | 自定义文件生成时的 list 参数处理,支持对不同文件类型进行精细化控制 |
|
|
268
270
|
|
|
271
|
+
[hooks 示例](https://github.com/openapi-ui/openapi-ts-request/blob/main/agents.md#-advanced-customization-hooks)
|
|
272
|
+
|
|
269
273
|
## Apifox-Config
|
|
270
274
|
|
|
271
275
|
| 属性 | 类型 | 说明 | 必填 |
|
|
@@ -343,7 +347,8 @@ export default {
|
|
|
343
347
|
4. 确保你的代码可以通过所有测试用例(新增功能需要添加新的功能测试用例):`pnpm test:unit`
|
|
344
348
|
5. 创建 changeset 文件通过命令:`pnpm changeset`
|
|
345
349
|
6. 使用 commit 提交你的修改(需遵循 commitlint 规范)
|
|
346
|
-
7.
|
|
350
|
+
7. 如果涉及文档,请同步更新 README.md、READMD-en_US.md、agents.md
|
|
351
|
+
8. 发起 Pull Request
|
|
347
352
|
|
|
348
353
|
## 感谢
|
|
349
354
|
|
package/dist/bin/cli.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const
|
|
5
|
+
const prompts_1 = require("@clack/prompts");
|
|
6
6
|
const commander_1 = require("commander");
|
|
7
7
|
const index_1 = require("../index");
|
|
8
|
+
const log_1 = require("../log");
|
|
8
9
|
const readConfig_1 = require("../readConfig");
|
|
9
10
|
commander_1.program
|
|
10
11
|
.option('-cfn, --configFileName <string>', 'config file name')
|
|
@@ -12,6 +13,11 @@ commander_1.program
|
|
|
12
13
|
.option('-u, --uniqueKey <string>', 'unique key');
|
|
13
14
|
commander_1.program.parse();
|
|
14
15
|
const options = commander_1.program.opts();
|
|
16
|
+
/**
|
|
17
|
+
* 1. 执行 cli 命令读取配置文件,已经使用 openapi.ts 替代了 cli.ts,后期会废弃 cli.ts
|
|
18
|
+
* 2. 如果配置文件中有 uniqueKey,则根据 uniqueKey 生成 service
|
|
19
|
+
* 3. 如果配置文件中没有 uniqueKey,且有多个 service,则交互式选择要生成的 service
|
|
20
|
+
*/
|
|
15
21
|
function run() {
|
|
16
22
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
17
23
|
const config = yield (0, readConfig_1.readConfig)({
|
|
@@ -25,30 +31,55 @@ function run() {
|
|
|
25
31
|
let configs = Array.isArray(config)
|
|
26
32
|
? config
|
|
27
33
|
: [config];
|
|
34
|
+
/** 是否交互式 */
|
|
35
|
+
let isInteractive = false;
|
|
28
36
|
if (options.uniqueKey) {
|
|
29
37
|
configs = configs.filter((config) => config.uniqueKey === options.uniqueKey);
|
|
30
38
|
}
|
|
39
|
+
else if (configs.length > 1) {
|
|
40
|
+
// 如果没有指定 uniqueKey,并且有多个配置,则交互式选择
|
|
41
|
+
isInteractive = true;
|
|
42
|
+
console.log(''); // 添加一个空行
|
|
43
|
+
(0, prompts_1.intro)('🎉 欢迎使用 openapi-ts-request 生成器');
|
|
44
|
+
const selected = yield (0, prompts_1.multiselect)({
|
|
45
|
+
message: '请选择要生成的 service',
|
|
46
|
+
options: configs.map((config) => ({
|
|
47
|
+
value: config,
|
|
48
|
+
label: config.describe || config.schemaPath,
|
|
49
|
+
})),
|
|
50
|
+
});
|
|
51
|
+
if ((0, prompts_1.isCancel)(selected)) {
|
|
52
|
+
(0, prompts_1.cancel)('👋 Has cancelled');
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
configs = selected;
|
|
56
|
+
}
|
|
31
57
|
for (const config of configs) {
|
|
32
58
|
tasks.push((0, index_1.generateService)(config));
|
|
33
59
|
}
|
|
34
60
|
const results = yield Promise.allSettled(tasks);
|
|
35
|
-
const errors = results.filter((result) => result.status === 'rejected');
|
|
36
61
|
let errorMsg = '';
|
|
37
|
-
for (let i = 0; i <
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
62
|
+
for (let i = 0; i < results.length; i++) {
|
|
63
|
+
const result = results[i];
|
|
64
|
+
if (result.status === 'rejected') {
|
|
65
|
+
const cnf = configs[i];
|
|
66
|
+
errorMsg += `${cnf.uniqueKey}${cnf.uniqueKey && ':'}${result.reason}\n`;
|
|
67
|
+
}
|
|
41
68
|
}
|
|
42
69
|
if (errorMsg) {
|
|
43
70
|
throw new Error(errorMsg);
|
|
44
71
|
}
|
|
72
|
+
if (isInteractive && !errorMsg) {
|
|
73
|
+
(0, prompts_1.outro)('🎉 All done!');
|
|
74
|
+
}
|
|
45
75
|
}
|
|
46
76
|
else {
|
|
47
77
|
throw new Error('config is not found');
|
|
48
78
|
}
|
|
49
79
|
}
|
|
50
80
|
catch (error) {
|
|
51
|
-
|
|
81
|
+
(0, log_1.logError)(error);
|
|
82
|
+
process.exit(1);
|
|
52
83
|
}
|
|
53
84
|
});
|
|
54
85
|
}
|
package/dist/bin/openapi.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const prompts_1 = require("@clack/prompts");
|
|
5
6
|
const commander_1 = require("commander");
|
|
6
7
|
const lodash_1 = require("lodash");
|
|
7
8
|
const path_1 = require("path");
|
|
@@ -21,8 +22,7 @@ const params = commander_1.program
|
|
|
21
22
|
.option('--requestLibPath <string>', 'custom request lib path, for example: "@/request", "node-fetch" (default: "axios")')
|
|
22
23
|
.option('-f, --full <boolean>', 'full replacement', true)
|
|
23
24
|
.option('--enableLogging <boolean>', 'open the log', false)
|
|
24
|
-
.option('--
|
|
25
|
-
.option('--includeTags <(string|RegExp)[]>', 'generate code from include tags')
|
|
25
|
+
.option('--priorityRule <string>', 'priority rule, include/exclude/both (default: "include")')
|
|
26
26
|
.option('--filterCaseInsensitive <boolean>', 'whether to perform a case-insensitive match with includeTags, includePaths, excludeTags, excludePaths filters', false)
|
|
27
27
|
.option('--includeTags <(string|RegExp)[]>', 'generate code from include tags')
|
|
28
28
|
.option('--includePaths <(string|RegExp)[]>', 'generate code from include paths')
|
|
@@ -100,33 +100,50 @@ function run() {
|
|
|
100
100
|
if (cnf) {
|
|
101
101
|
const tasks = [];
|
|
102
102
|
let configs = Array.isArray(cnf) ? cnf : [cnf];
|
|
103
|
+
/** 是否交互式 */
|
|
104
|
+
let isInteractive = false;
|
|
103
105
|
if (params.uniqueKey) {
|
|
104
106
|
configs = configs.filter((config) => config.uniqueKey === params.uniqueKey);
|
|
105
107
|
}
|
|
108
|
+
else if (configs.length > 1) {
|
|
109
|
+
// 如果没有指定 uniqueKey,并且有多个配置,则交互式选择
|
|
110
|
+
isInteractive = true;
|
|
111
|
+
console.log(''); // 添加一个空行
|
|
112
|
+
(0, prompts_1.intro)('🎉 欢迎使用 openapi-ts-request 生成器');
|
|
113
|
+
const selected = yield (0, prompts_1.multiselect)({
|
|
114
|
+
message: '请选择要生成的 service',
|
|
115
|
+
options: configs.map((config) => ({
|
|
116
|
+
value: config,
|
|
117
|
+
label: config.describe || config.schemaPath,
|
|
118
|
+
})),
|
|
119
|
+
});
|
|
120
|
+
if ((0, prompts_1.isCancel)(selected)) {
|
|
121
|
+
(0, prompts_1.cancel)('👋 Has cancelled');
|
|
122
|
+
process.exit(0);
|
|
123
|
+
}
|
|
124
|
+
configs = selected;
|
|
125
|
+
}
|
|
106
126
|
for (const config of configs) {
|
|
107
127
|
tasks.push((0, index_1.generateService)(config));
|
|
108
128
|
}
|
|
109
129
|
const results = yield Promise.allSettled(tasks);
|
|
110
|
-
const errors = results.filter((result) => result.status === 'rejected');
|
|
111
130
|
let errorMsg = '';
|
|
112
|
-
for (let i = 0; i <
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
131
|
+
for (let i = 0; i < results.length; i++) {
|
|
132
|
+
const result = results[i];
|
|
133
|
+
if (result.status === 'rejected') {
|
|
134
|
+
const cnf = configs[i];
|
|
135
|
+
errorMsg += `${cnf.uniqueKey}${cnf.uniqueKey && ':'}${result.reason}\n`;
|
|
136
|
+
}
|
|
116
137
|
}
|
|
117
138
|
if (errorMsg) {
|
|
118
|
-
|
|
119
|
-
|
|
139
|
+
throw new Error(errorMsg);
|
|
140
|
+
}
|
|
141
|
+
if (isInteractive && !errorMsg) {
|
|
142
|
+
(0, prompts_1.outro)('🎉 All done!');
|
|
120
143
|
}
|
|
121
144
|
}
|
|
122
145
|
else {
|
|
123
|
-
|
|
124
|
-
(0, log_1.logError)('Please provide either input/output options or a configuration file path and name.');
|
|
125
|
-
process.exit(1);
|
|
126
|
-
}
|
|
127
|
-
const options = baseGenerate(params);
|
|
128
|
-
yield (0, index_1.generateService)((0, lodash_1.pickBy)(options, (value) => value !== null && value !== undefined && value !== ''));
|
|
129
|
-
process.exit(0);
|
|
146
|
+
throw new Error('Please provide either input/output options or a configuration file path and name.');
|
|
130
147
|
}
|
|
131
148
|
}
|
|
132
149
|
catch (error) {
|
|
@@ -249,7 +249,7 @@ class ServiceGenerator {
|
|
|
249
249
|
displayTypeLabelFileName: config_2.displayTypeLabelFileName,
|
|
250
250
|
});
|
|
251
251
|
// 打印日志
|
|
252
|
-
(0, log_1.default)('✅ 成功生成 api 文件目录-> ', this.config.serversPath);
|
|
252
|
+
(0, log_1.default)('✅ 成功生成 api 文件目录-> ', ` ${this.config.serversPath}`);
|
|
253
253
|
}
|
|
254
254
|
getInterfaceTPConfigs() {
|
|
255
255
|
var _a, _b, _c;
|
|
@@ -391,7 +391,7 @@ class ServiceGenerator {
|
|
|
391
391
|
// 暂不支持变量, path 需要普通前缀请使用例如: apiPrefix: "`api`", path 需要变量前缀请使用例如: apiPrefix: "api"
|
|
392
392
|
!api.path.includes('${'))
|
|
393
393
|
.map((api) => {
|
|
394
|
-
var _a, _b, _c, _d, _e, _f;
|
|
394
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
395
395
|
const newApi = api;
|
|
396
396
|
try {
|
|
397
397
|
const params = this.getParamsTP(newApi.parameters, newApi.path) || {};
|
|
@@ -422,9 +422,13 @@ class ServiceGenerator {
|
|
|
422
422
|
}
|
|
423
423
|
if (response === null || response === void 0 ? void 0 : response.isAnonymous) {
|
|
424
424
|
const responseName = (0, lodash_1.upperFirst)(`${functionName}Response`);
|
|
425
|
+
// 使用正则表达式移除 response?.type 中包含 this.config.namespace 的部分,isAnonymous模式不需要 this.config.namespace 前缀
|
|
426
|
+
const cleanType = ((_b = response === null || response === void 0 ? void 0 : response.type) === null || _b === void 0 ? void 0 : _b.includes(`${this.config.namespace}.`))
|
|
427
|
+
? (_c = response === null || response === void 0 ? void 0 : response.type) === null || _c === void 0 ? void 0 : _c.replace(new RegExp(`${this.config.namespace}\\.`, 'g'), '')
|
|
428
|
+
: (response === null || response === void 0 ? void 0 : response.type) || '';
|
|
425
429
|
this.interfaceTPConfigs.push({
|
|
426
430
|
typeName: responseName,
|
|
427
|
-
type:
|
|
431
|
+
type: cleanType,
|
|
428
432
|
isEnum: false,
|
|
429
433
|
props: [],
|
|
430
434
|
});
|
|
@@ -494,13 +498,13 @@ class ServiceGenerator {
|
|
|
494
498
|
: [
|
|
495
499
|
newApi.summary,
|
|
496
500
|
newApi.description,
|
|
497
|
-
((
|
|
498
|
-
? `返回值: ${((
|
|
501
|
+
((_e = (_d = newApi.responses) === null || _d === void 0 ? void 0 : _d.default) === null || _e === void 0 ? void 0 : _e.description)
|
|
502
|
+
? `返回值: ${((_f = newApi.responses) === null || _f === void 0 ? void 0 : _f.default).description}`
|
|
499
503
|
: '',
|
|
500
504
|
]
|
|
501
505
|
.filter((s) => s)
|
|
502
506
|
.join(' ')
|
|
503
|
-
.replace(config_2.lineBreakReg, ''), hasHeader: !!(params === null || params === void 0 ? void 0 : params.header) || !!(body === null || body === void 0 ? void 0 : body.mediaType), params: finalParams, hasParams: Boolean((0, lodash_1.keys)(finalParams).length), options: ((
|
|
507
|
+
.replace(config_2.lineBreakReg, ''), hasHeader: !!(params === null || params === void 0 ? void 0 : params.header) || !!(body === null || body === void 0 ? void 0 : body.mediaType), params: finalParams, hasParams: Boolean((0, lodash_1.keys)(finalParams).length), options: ((_h = (_g = this.config.hook) === null || _g === void 0 ? void 0 : _g.customOptionsDefaultValue) === null || _h === void 0 ? void 0 : _h.call(_g, newApi)) || {}, body,
|
|
504
508
|
file, hasFormData: formData, response });
|
|
505
509
|
}
|
|
506
510
|
catch (error) {
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export type GenerateServiceProps = {
|
|
|
23
23
|
* 是否全量替换, 默认: true, 如果为false, 则进行增量替换
|
|
24
24
|
*/
|
|
25
25
|
full?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* 描述信息,在用 cli 可交互运行方式时会用到
|
|
28
|
+
*/
|
|
29
|
+
describe?: string;
|
|
26
30
|
/**
|
|
27
31
|
* 开启日志
|
|
28
32
|
*/
|
|
@@ -280,3 +284,7 @@ export type GenerateServiceProps = {
|
|
|
280
284
|
};
|
|
281
285
|
};
|
|
282
286
|
export declare function generateService({ requestLibPath, schemaPath, mockFolder, includeTags, excludeTags, includePaths, excludePaths, authorization, isTranslateToEnglishTag, priorityRule, timeout, reactQueryMode, apifoxConfig, ...rest }: GenerateServiceProps): Promise<void>;
|
|
287
|
+
/**
|
|
288
|
+
* Defines the configuration for openapi-ts-request.
|
|
289
|
+
*/
|
|
290
|
+
export declare function defineConfig(config: GenerateServiceProps | GenerateServiceProps[]): GenerateServiceProps | GenerateServiceProps[];
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateService = generateService;
|
|
4
|
+
exports.defineConfig = defineConfig;
|
|
4
5
|
const tslib_1 = require("tslib");
|
|
5
6
|
const lodash_1 = require("lodash");
|
|
6
7
|
const config_1 = require("./config");
|
|
@@ -53,3 +54,9 @@ function generateService(_a) {
|
|
|
53
54
|
}
|
|
54
55
|
});
|
|
55
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Defines the configuration for openapi-ts-request.
|
|
59
|
+
*/
|
|
60
|
+
function defineConfig(config) {
|
|
61
|
+
return config;
|
|
62
|
+
}
|
package/dist/log.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.logError = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
-
const log = (...rest) => console.log(
|
|
7
|
-
const logError = (...rest) => console.error(
|
|
6
|
+
const log = (...rest) => console.log(` ${chalk_1.default.blue('[openAPI]')}: ${rest.join('\n')}`);
|
|
7
|
+
const logError = (...rest) => console.error(` ${chalk_1.default.red('❌ [openAPI]')}: ${rest.join('\n')}`);
|
|
8
8
|
exports.logError = logError;
|
|
9
9
|
exports.default = log;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openapi-ts-request",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Swagger2/OpenAPI3/Apifox to TypeScript/JavaScript, request client(support any client), request mock service, enum and enum translation, react-query/vue-query, type field label, JSON Schemas",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"prettier.config.cjs"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@clack/prompts": "^0.11.0",
|
|
27
28
|
"@prettier/sync": "^0.6.1",
|
|
28
29
|
"@trivago/prettier-plugin-sort-imports": "^5.2.1",
|
|
29
30
|
"axios": "^1.7.2",
|