openapi-ts-request 1.1.2 → 1.3.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 +53 -4
- package/dist/bin/cli.js +30 -11
- package/dist/bin/openapi.js +81 -30
- package/dist/generator/merge.d.ts +6 -0
- package/dist/generator/merge.js +267 -0
- package/dist/generator/mockGenarator.js +1 -1
- package/dist/generator/serviceGenarator.js +105 -60
- package/dist/generator/type.d.ts +16 -1
- package/dist/generator/type.js +6 -0
- package/dist/generator/util.d.ts +1 -0
- package/dist/generator/util.js +47 -0
- package/dist/index.d.ts +26 -6
- package/dist/index.js +11 -5
- package/dist/log.d.ts +1 -0
- package/dist/log.js +3 -0
- package/dist/readConfig.d.ts +2 -0
- package/dist/readConfig.js +31 -0
- package/dist/type.d.ts +42 -0
- package/dist/util.d.ts +17 -2
- package/dist/util.js +104 -7
- package/package.json +4 -2
- package/templates/displayEnumLabel.njk +1 -1
|
@@ -10,10 +10,12 @@ const path_1 = require("path");
|
|
|
10
10
|
const rimraf_1 = require("rimraf");
|
|
11
11
|
const config_1 = require("../config");
|
|
12
12
|
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
13
|
+
const util_1 = require("../util");
|
|
13
14
|
const config_2 = require("./config");
|
|
14
15
|
const file_1 = require("./file");
|
|
16
|
+
const merge_1 = require("./merge");
|
|
15
17
|
const patchSchema_1 = require("./patchSchema");
|
|
16
|
-
const
|
|
18
|
+
const util_2 = require("./util");
|
|
17
19
|
class ServiceGenerator {
|
|
18
20
|
constructor(config, openAPIData) {
|
|
19
21
|
var _a, _b, _c, _d, _e;
|
|
@@ -81,7 +83,7 @@ class ServiceGenerator {
|
|
|
81
83
|
if (!operationObject) {
|
|
82
84
|
return;
|
|
83
85
|
}
|
|
84
|
-
const hookCustomFileNames = ((_a = this.config.hook) === null || _a === void 0 ? void 0 : _a.customFileNames) ||
|
|
86
|
+
const hookCustomFileNames = ((_a = this.config.hook) === null || _a === void 0 ? void 0 : _a.customFileNames) || util_2.getDefaultFileTag;
|
|
85
87
|
const tags = hookCustomFileNames(operationObject, pathKey, method);
|
|
86
88
|
// 这里判断tags
|
|
87
89
|
tags.forEach((tag) => {
|
|
@@ -119,8 +121,8 @@ class ServiceGenerator {
|
|
|
119
121
|
}
|
|
120
122
|
}
|
|
121
123
|
const tagKey = this.config.isCamelCase
|
|
122
|
-
? (0,
|
|
123
|
-
: (0,
|
|
124
|
+
? (0, util_1.camelCase)((0, util_2.resolveTypeName)(tag))
|
|
125
|
+
: (0, util_2.resolveTypeName)(tag);
|
|
124
126
|
if (!this.apiData[tagKey]) {
|
|
125
127
|
this.apiData[tagKey] = [];
|
|
126
128
|
}
|
|
@@ -130,15 +132,17 @@ class ServiceGenerator {
|
|
|
130
132
|
}
|
|
131
133
|
}
|
|
132
134
|
genFile() {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
(
|
|
135
|
+
if (this.config.full) {
|
|
136
|
+
try {
|
|
137
|
+
(0, glob_1.globSync)(`${this.config.serversPath}/**/*`)
|
|
138
|
+
.filter((item) => !item.includes('_deperated'))
|
|
139
|
+
.forEach((item) => {
|
|
140
|
+
(0, rimraf_1.rimrafSync)(item);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
(0, log_1.default)(`🚥 api 生成失败: ${error}`);
|
|
145
|
+
}
|
|
142
146
|
}
|
|
143
147
|
const isOnlyGenTypeScriptType = this.config.isOnlyGenTypeScriptType;
|
|
144
148
|
const isGenJavaScript = this.config.isGenJavaScript;
|
|
@@ -146,7 +150,7 @@ class ServiceGenerator {
|
|
|
146
150
|
const reactQueryFileName = (0, config_2.displayReactQueryFileName)(reactQueryMode);
|
|
147
151
|
// 处理重复的 typeName
|
|
148
152
|
const interfaceTPConfigs = this.getInterfaceTPConfigs();
|
|
149
|
-
(0,
|
|
153
|
+
(0, util_2.handleDuplicateTypeNames)(interfaceTPConfigs);
|
|
150
154
|
// 生成 ts 类型声明
|
|
151
155
|
if (!isGenJavaScript) {
|
|
152
156
|
this.genFileFromTemplate(`${config_2.interfaceFileName}.ts`, config_2.TypescriptFileType.interface, {
|
|
@@ -180,13 +184,13 @@ class ServiceGenerator {
|
|
|
180
184
|
// 生成 service controller 文件
|
|
181
185
|
this.getServiceTPConfigs().forEach((tp) => {
|
|
182
186
|
const hasError = this.genFileFromTemplate(isGenJavaScript
|
|
183
|
-
? (0,
|
|
184
|
-
: (0,
|
|
187
|
+
? (0, util_2.getFinalFileName)(`${tp.className}.js`)
|
|
188
|
+
: (0, util_2.getFinalFileName)(`${tp.className}.ts`), config_2.TypescriptFileType.serviceController, Object.assign({ namespace: this.config.namespace, requestOptionsType: this.config.requestOptionsType, requestImportStatement: this.config.requestImportStatement, interfaceFileName: config_2.interfaceFileName }, tp));
|
|
185
189
|
prettierError.push(hasError);
|
|
186
190
|
if (this.config.isGenReactQuery) {
|
|
187
191
|
this.genFileFromTemplate(isGenJavaScript
|
|
188
|
-
? (0,
|
|
189
|
-
: (0,
|
|
192
|
+
? (0, util_2.getFinalFileName)(`${tp.className}.${reactQueryFileName}.js`)
|
|
193
|
+
: (0, util_2.getFinalFileName)(`${tp.className}.${reactQueryFileName}.ts`), config_2.TypescriptFileType.reactQuery, Object.assign({ namespace: this.config.namespace, requestOptionsType: this.config.requestOptionsType, requestImportStatement: this.config.requestImportStatement, interfaceFileName: config_2.interfaceFileName, reactQueryModePackageName: (0, config_1.displayReactQueryMode)(reactQueryMode) }, tp));
|
|
190
194
|
}
|
|
191
195
|
});
|
|
192
196
|
if (prettierError.includes(true)) {
|
|
@@ -197,7 +201,7 @@ class ServiceGenerator {
|
|
|
197
201
|
this.config.isGenJsonSchemas &&
|
|
198
202
|
!(0, lodash_1.isEmpty)(this.schemaList)) {
|
|
199
203
|
// 处理重复的 schemaName
|
|
200
|
-
(0,
|
|
204
|
+
(0, util_2.handleDuplicateTypeNames)(this.schemaList);
|
|
201
205
|
// 生成 schema 文件
|
|
202
206
|
this.genFileFromTemplate(isGenJavaScript ? `${config_2.schemaFileName}.js` : `${config_2.schemaFileName}.ts`, config_2.TypescriptFileType.schema, {
|
|
203
207
|
list: this.schemaList,
|
|
@@ -225,7 +229,7 @@ class ServiceGenerator {
|
|
|
225
229
|
displayTypeLabelFileName: config_2.displayTypeLabelFileName,
|
|
226
230
|
});
|
|
227
231
|
// 打印日志
|
|
228
|
-
(0, log_1.default)('✅ 成功生成 api
|
|
232
|
+
(0, log_1.default)('✅ 成功生成 api 文件目录-> ', this.config.serversPath);
|
|
229
233
|
}
|
|
230
234
|
getInterfaceTPConfigs() {
|
|
231
235
|
var _a, _b;
|
|
@@ -238,7 +242,7 @@ class ServiceGenerator {
|
|
|
238
242
|
(0, lodash_1.forEach)(config_2.methods, (method) => {
|
|
239
243
|
var _a, _b, _c, _d;
|
|
240
244
|
const operationObject = pathItem[method];
|
|
241
|
-
const hookCustomFileNames = ((_a = this.config.hook) === null || _a === void 0 ? void 0 : _a.customFileNames) ||
|
|
245
|
+
const hookCustomFileNames = ((_a = this.config.hook) === null || _a === void 0 ? void 0 : _a.customFileNames) || util_2.getDefaultFileTag;
|
|
242
246
|
if (!operationObject) {
|
|
243
247
|
return;
|
|
244
248
|
}
|
|
@@ -251,7 +255,7 @@ class ServiceGenerator {
|
|
|
251
255
|
return;
|
|
252
256
|
}
|
|
253
257
|
// 筛选出 pathItem 包含的 $ref 对应的schema
|
|
254
|
-
(0,
|
|
258
|
+
(0, util_2.markAllowedSchema)(JSON.stringify(pathItem), this.openAPIData);
|
|
255
259
|
operationObject.parameters = (_b = operationObject.parameters) === null || _b === void 0 ? void 0 : _b.filter((item) => (item === null || item === void 0 ? void 0 : item.in) !== `${config_2.parametersInsEnum.header}`);
|
|
256
260
|
const props = [];
|
|
257
261
|
(_c = operationObject.parameters) === null || _c === void 0 ? void 0 : _c.forEach((parameter) => {
|
|
@@ -312,14 +316,14 @@ class ServiceGenerator {
|
|
|
312
316
|
type: enumObj.type,
|
|
313
317
|
props: [],
|
|
314
318
|
isEnum: enumObj.isEnum,
|
|
315
|
-
displayLabelFuncName: (0,
|
|
319
|
+
displayLabelFuncName: (0, util_1.camelCase)(`display-${item.name}-Enum`),
|
|
316
320
|
enumLabelType: enumObj.enumLabelType,
|
|
317
321
|
});
|
|
318
322
|
}
|
|
319
323
|
});
|
|
320
324
|
}
|
|
321
325
|
const isEnum = result.isEnum;
|
|
322
|
-
const typeName = (0,
|
|
326
|
+
const typeName = (0, util_2.resolveTypeName)(schemaKey);
|
|
323
327
|
if (typeName) {
|
|
324
328
|
lastTypes.push({
|
|
325
329
|
typeName,
|
|
@@ -327,14 +331,14 @@ class ServiceGenerator {
|
|
|
327
331
|
props: (result.props || []),
|
|
328
332
|
isEnum,
|
|
329
333
|
displayLabelFuncName: isEnum
|
|
330
|
-
? (0,
|
|
334
|
+
? (0, util_1.camelCase)(`display-${typeName}-Enum`)
|
|
331
335
|
: '',
|
|
332
336
|
enumLabelType: isEnum ? result.enumLabelType : '',
|
|
333
337
|
});
|
|
334
338
|
}
|
|
335
339
|
if (this.config.isGenJsonSchemas) {
|
|
336
340
|
this.schemaList.push({
|
|
337
|
-
typeName: `$${(0,
|
|
341
|
+
typeName: `$${(0, util_2.resolveTypeName)(schemaKey)}`,
|
|
338
342
|
type: JSON.stringify((0, patchSchema_1.patchSchema)(schema, (_a = this.openAPIData.components) === null || _a === void 0 ? void 0 : _a.schemas)),
|
|
339
343
|
});
|
|
340
344
|
}
|
|
@@ -416,7 +420,7 @@ class ServiceGenerator {
|
|
|
416
420
|
return `$\{${prefix}}${formattedPath}`;
|
|
417
421
|
};
|
|
418
422
|
return Object.assign(Object.assign({}, newApi), { functionName: this.config.isCamelCase
|
|
419
|
-
? (0,
|
|
423
|
+
? (0, util_1.camelCase)(functionName)
|
|
420
424
|
: functionName, typeName: this.getFunctionParamsTypeName(newApi), path: getPrefixPath(), pathInComment: formattedPath.replace(/\*/g, '*'), apifoxRunLink: newApi === null || newApi === void 0 ? void 0 : newApi['x-run-in-apifox'], hasPathVariables: formattedPath.includes('{'), hasApiPrefix: !!this.config.apiPrefix, method: newApi.method,
|
|
421
425
|
// 如果 functionName 和 summary 相同,则不显示 summary
|
|
422
426
|
desc: functionName === newApi.summary
|
|
@@ -440,7 +444,7 @@ class ServiceGenerator {
|
|
|
440
444
|
})
|
|
441
445
|
// 排序下,防止git乱
|
|
442
446
|
.sort((a, b) => a.path.localeCompare(b.path));
|
|
443
|
-
const fileName = (0,
|
|
447
|
+
const fileName = (0, util_2.replaceDot)(tag) || `api${index}`;
|
|
444
448
|
let className = fileName;
|
|
445
449
|
if ((_a = this.config.hook) === null || _a === void 0 ? void 0 : _a.customClassName) {
|
|
446
450
|
className = this.config.hook.customClassName(tag);
|
|
@@ -467,8 +471,27 @@ class ServiceGenerator {
|
|
|
467
471
|
const env = nunjucks_1.default.configure({
|
|
468
472
|
autoescape: false,
|
|
469
473
|
});
|
|
470
|
-
env.addFilter('capitalizeFirst',
|
|
471
|
-
|
|
474
|
+
env.addFilter('capitalizeFirst', util_2.capitalizeFirstLetter);
|
|
475
|
+
const destPath = (0, path_1.join)(this.config.serversPath, fileName);
|
|
476
|
+
const destCode = nunjucks_1.default.renderString(template, Object.assign({ disableTypeCheck: false }, params));
|
|
477
|
+
let mergerProps = {};
|
|
478
|
+
if ((0, fs_1.existsSync)(destPath)) {
|
|
479
|
+
mergerProps = {
|
|
480
|
+
srcPath: destPath,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
mergerProps = {
|
|
485
|
+
source: '',
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
if (this.config.full) {
|
|
489
|
+
return (0, file_1.writeFile)(this.config.serversPath, fileName, destCode);
|
|
490
|
+
}
|
|
491
|
+
const merger = new merge_1.Merger(mergerProps);
|
|
492
|
+
return (0, file_1.writeFile)(this.config.serversPath, fileName, merger.merge({
|
|
493
|
+
source: destCode,
|
|
494
|
+
}));
|
|
472
495
|
}
|
|
473
496
|
catch (error) {
|
|
474
497
|
console.error('[GenSDK] file gen fail:', fileName, 'type:', type);
|
|
@@ -478,14 +501,18 @@ class ServiceGenerator {
|
|
|
478
501
|
getTemplate(type) {
|
|
479
502
|
return (0, fs_1.readFileSync)((0, path_1.join)(this.config.templatesFolder, `${type}.njk`), 'utf8');
|
|
480
503
|
}
|
|
504
|
+
// 生成方法名 functionName
|
|
481
505
|
getFunctionName(data) {
|
|
482
506
|
// 获取路径相同部分
|
|
483
|
-
const pathBasePrefix = (0,
|
|
507
|
+
const pathBasePrefix = (0, util_2.getBasePrefix)((0, lodash_1.keys)(this.openAPIData.paths));
|
|
484
508
|
return this.config.hook && this.config.hook.customFunctionName
|
|
485
|
-
? this.config.hook.customFunctionName(data)
|
|
486
|
-
: data.
|
|
487
|
-
|
|
488
|
-
|
|
509
|
+
? this.config.hook.customFunctionName(data, pathBasePrefix)
|
|
510
|
+
: (0, util_1.camelCase)(`${(0, util_2.genDefaultFunctionName)(data.path, pathBasePrefix)}-using-${data.method}`);
|
|
511
|
+
// return this.config.hook && this.config.hook.customFunctionName
|
|
512
|
+
// ? this.config.hook.customFunctionName(data)
|
|
513
|
+
// : data.operationId
|
|
514
|
+
// ? resolveFunctionName(stripDot(data.operationId), data.method)
|
|
515
|
+
// : data.method + genDefaultFunctionName(data.path, pathBasePrefix);
|
|
489
516
|
}
|
|
490
517
|
getType(schemaObject, namespace) {
|
|
491
518
|
var _a, _b;
|
|
@@ -496,19 +523,19 @@ class ServiceGenerator {
|
|
|
496
523
|
schemaObject,
|
|
497
524
|
namespace,
|
|
498
525
|
schemas,
|
|
499
|
-
originGetType:
|
|
526
|
+
originGetType: util_2.getDefaultType,
|
|
500
527
|
});
|
|
501
528
|
if (typeof type === 'string') {
|
|
502
529
|
return type;
|
|
503
530
|
}
|
|
504
531
|
}
|
|
505
|
-
return (0,
|
|
532
|
+
return (0, util_2.getDefaultType)(schemaObject, namespace, schemas);
|
|
506
533
|
}
|
|
507
534
|
getFunctionParamsTypeName(data) {
|
|
508
535
|
var _a, _b, _c;
|
|
509
536
|
const namespace = this.config.namespace ? `${this.config.namespace}.` : '';
|
|
510
537
|
const typeName = ((_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.hook) === null || _b === void 0 ? void 0 : _b.customTypeName) === null || _c === void 0 ? void 0 : _c.call(_b, data)) || this.getFunctionName(data);
|
|
511
|
-
return (0,
|
|
538
|
+
return (0, util_2.resolveTypeName)(`${namespace}${typeName !== null && typeName !== void 0 ? typeName : data.operationId}Params`);
|
|
512
539
|
}
|
|
513
540
|
getBodyTP(requestBody) {
|
|
514
541
|
var _a;
|
|
@@ -534,7 +561,7 @@ class ServiceGenerator {
|
|
|
534
561
|
const propertyObj = schema.properties[propertyKey];
|
|
535
562
|
if (propertyObj &&
|
|
536
563
|
![config_1.SchemaObjectFormat.binary, config_1.SchemaObjectFormat.base64].includes(propertyObj.format) &&
|
|
537
|
-
!(0,
|
|
564
|
+
!(0, util_2.isBinaryArraySchemaObject)(propertyObj)) {
|
|
538
565
|
// 测试了很多用例,很少有用例走到这里
|
|
539
566
|
return {
|
|
540
567
|
key: propertyKey,
|
|
@@ -569,7 +596,7 @@ class ServiceGenerator {
|
|
|
569
596
|
const props = (((_a = resolved.props) === null || _a === void 0 ? void 0 : _a.length) > 0 &&
|
|
570
597
|
resolved.props[0].filter((p) => p.format === 'binary' ||
|
|
571
598
|
p.format === 'base64' ||
|
|
572
|
-
(0,
|
|
599
|
+
(0, util_2.isBinaryArraySchemaObject)(p))) ||
|
|
573
600
|
[];
|
|
574
601
|
if (props.length > 0) {
|
|
575
602
|
ret = props.map((p) => {
|
|
@@ -607,10 +634,10 @@ class ServiceGenerator {
|
|
|
607
634
|
}
|
|
608
635
|
let schema = (resContent[mediaType].schema ||
|
|
609
636
|
config_2.DEFAULT_SCHEMA);
|
|
610
|
-
if ((0,
|
|
611
|
-
const refName = (0,
|
|
637
|
+
if ((0, util_2.isReferenceObject)(schema)) {
|
|
638
|
+
const refName = (0, util_2.getLastRefName)(schema.$ref);
|
|
612
639
|
const childrenSchema = components.schemas[refName];
|
|
613
|
-
if ((0,
|
|
640
|
+
if ((0, util_2.isNonArraySchemaObject)(childrenSchema) && this.config.dataFields) {
|
|
614
641
|
schema = (((_a = this.config.dataFields
|
|
615
642
|
.map((field) => childrenSchema.properties[field])
|
|
616
643
|
.filter(Boolean)) === null || _a === void 0 ? void 0 : _a[0]) ||
|
|
@@ -618,7 +645,7 @@ class ServiceGenerator {
|
|
|
618
645
|
config_2.DEFAULT_SCHEMA);
|
|
619
646
|
}
|
|
620
647
|
}
|
|
621
|
-
if ((0,
|
|
648
|
+
if ((0, util_2.isSchemaObject)(schema)) {
|
|
622
649
|
(0, lodash_1.keys)(schema.properties).map((fieldName) => {
|
|
623
650
|
var _a, _b;
|
|
624
651
|
schema.properties[fieldName]['required'] =
|
|
@@ -641,7 +668,7 @@ class ServiceGenerator {
|
|
|
641
668
|
var _a, _b, _c, _d, _e;
|
|
642
669
|
const isDirectObject = (((_a = p.schema) === null || _a === void 0 ? void 0 : _a.type) === 'object' ||
|
|
643
670
|
p.type) === 'object';
|
|
644
|
-
const refName = (0,
|
|
671
|
+
const refName = (0, util_2.getLastRefName)(((_b = p.schema) === null || _b === void 0 ? void 0 : _b.$ref) ||
|
|
645
672
|
p.$ref);
|
|
646
673
|
const deRefObj = (0, lodash_1.entries)((_c = this.openAPIData.components) === null || _c === void 0 ? void 0 : _c.schemas).find(([k]) => k === refName) || [];
|
|
647
674
|
const isRefObject = ((_d = deRefObj[1]) === null || _d === void 0 ? void 0 : _d.type) === 'object' &&
|
|
@@ -672,7 +699,7 @@ class ServiceGenerator {
|
|
|
672
699
|
// 不使用 schemaObject: ISchemaObject = {}
|
|
673
700
|
schemaObject = schemaObject !== null && schemaObject !== void 0 ? schemaObject : {};
|
|
674
701
|
// 引用类型
|
|
675
|
-
if ((0,
|
|
702
|
+
if ((0, util_2.isReferenceObject)(schemaObject)) {
|
|
676
703
|
return this.resolveRefObject(schemaObject);
|
|
677
704
|
}
|
|
678
705
|
// 枚举类型
|
|
@@ -688,15 +715,15 @@ class ServiceGenerator {
|
|
|
688
715
|
return this.resolveProperties(schemaObject);
|
|
689
716
|
}
|
|
690
717
|
// 数组类型
|
|
691
|
-
if ((0,
|
|
718
|
+
if ((0, util_2.isArraySchemaObject)(schemaObject)) {
|
|
692
719
|
return this.resolveArray(schemaObject);
|
|
693
720
|
}
|
|
694
721
|
return schemaObject;
|
|
695
722
|
}
|
|
696
723
|
resolveArray(schemaObject) {
|
|
697
724
|
var _a;
|
|
698
|
-
if ((0,
|
|
699
|
-
const refName = (0,
|
|
725
|
+
if ((0, util_2.isReferenceObject)(schemaObject.items)) {
|
|
726
|
+
const refName = (0, util_2.getRefName)(schemaObject.items);
|
|
700
727
|
return {
|
|
701
728
|
type: `${refName}[]`,
|
|
702
729
|
};
|
|
@@ -719,10 +746,19 @@ class ServiceGenerator {
|
|
|
719
746
|
const enumArray = schemaObject.enum;
|
|
720
747
|
let enumStr = '';
|
|
721
748
|
let enumLabelTypeStr = '';
|
|
722
|
-
if (config_2.numberEnum.includes(schemaObject.type) || (0,
|
|
723
|
-
|
|
749
|
+
if (config_2.numberEnum.includes(schemaObject.type) || (0, util_2.isAllNumber)(enumArray)) {
|
|
750
|
+
if (this.config.isSupportParseEnumDesc && schemaObject.description) {
|
|
751
|
+
const enumMap = (0, util_2.parseDescriptionEnum)(schemaObject.description);
|
|
752
|
+
enumStr = `{${(0, lodash_1.map)(enumArray, (value) => {
|
|
753
|
+
const enumLabel = enumMap.get(Number(value));
|
|
754
|
+
return `${enumLabel}=${Number(value)}`;
|
|
755
|
+
}).join(',')}}`;
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
enumStr = `{${(0, lodash_1.map)(enumArray, (value) => `"NUMBER_${value}"=${Number(value)}`).join(',')}}`;
|
|
759
|
+
}
|
|
724
760
|
}
|
|
725
|
-
else if ((0,
|
|
761
|
+
else if ((0, util_2.isAllNumeric)(enumArray)) {
|
|
726
762
|
enumStr = `{${(0, lodash_1.map)(enumArray, (value) => `"STRING_NUMBER_${value}"="${value}"`).join(',')}}`;
|
|
727
763
|
}
|
|
728
764
|
else {
|
|
@@ -749,11 +785,20 @@ class ServiceGenerator {
|
|
|
749
785
|
}).join(',')}}`;
|
|
750
786
|
}
|
|
751
787
|
else {
|
|
752
|
-
if (config_2.numberEnum.includes(schemaObject.type) || (0,
|
|
753
|
-
|
|
788
|
+
if (config_2.numberEnum.includes(schemaObject.type) || (0, util_2.isAllNumber)(enumArray)) {
|
|
789
|
+
if (this.config.isSupportParseEnumDesc && schemaObject.description) {
|
|
790
|
+
const enumMap = (0, util_2.parseDescriptionEnum)(schemaObject.description);
|
|
791
|
+
enumLabelTypeStr = `{${(0, lodash_1.map)(enumArray, (value) => {
|
|
792
|
+
const enumLabel = enumMap.get(Number(value));
|
|
793
|
+
return `${Number(value)}:"${enumLabel}"`;
|
|
794
|
+
}).join(',')}}`;
|
|
795
|
+
}
|
|
796
|
+
else {
|
|
797
|
+
enumLabelTypeStr = `{${(0, lodash_1.map)(enumArray, (value) => `${Number(value)}:"NUMBER_${value}"`).join(',')}}`;
|
|
798
|
+
}
|
|
754
799
|
}
|
|
755
|
-
else if ((0,
|
|
756
|
-
enumLabelTypeStr = `{${(0, lodash_1.map)(enumArray, (value) => `"
|
|
800
|
+
else if ((0, util_2.isAllNumeric)(enumArray)) {
|
|
801
|
+
enumLabelTypeStr = `{${(0, lodash_1.map)(enumArray, (value) => `"${value}":"STRING_NUMBER_${value}"`).join(',')}}`;
|
|
757
802
|
}
|
|
758
803
|
else {
|
|
759
804
|
enumLabelTypeStr = `{${(0, lodash_1.map)(enumArray, (value) => `${value}:"${value}"`).join(',')}}`;
|
|
@@ -767,7 +812,7 @@ class ServiceGenerator {
|
|
|
767
812
|
}
|
|
768
813
|
resolveAllOfObject(schemaObject) {
|
|
769
814
|
const props = (0, lodash_1.map)(schemaObject.allOf, (item) => {
|
|
770
|
-
return (0,
|
|
815
|
+
return (0, util_2.isReferenceObject)(item)
|
|
771
816
|
? [Object.assign(Object.assign({}, item), { type: this.getType(item) })]
|
|
772
817
|
: this.getProps(item);
|
|
773
818
|
});
|
|
@@ -799,16 +844,16 @@ class ServiceGenerator {
|
|
|
799
844
|
});
|
|
800
845
|
}
|
|
801
846
|
resolveRefObject(refObject) {
|
|
802
|
-
if (!(0,
|
|
847
|
+
if (!(0, util_2.isReferenceObject)(refObject)) {
|
|
803
848
|
return refObject;
|
|
804
849
|
}
|
|
805
850
|
const refPaths = refObject.$ref.split('/');
|
|
806
851
|
if (refPaths[0] === '#') {
|
|
807
|
-
const schema = (0,
|
|
852
|
+
const schema = (0, util_2.resolveRefs)(this.openAPIData, refPaths.slice(1));
|
|
808
853
|
if (!schema) {
|
|
809
854
|
throw new Error(`[GenSDK] Data Error! Notfoud: ${refObject.$ref}`);
|
|
810
855
|
}
|
|
811
|
-
return Object.assign(Object.assign({}, (this.resolveRefObject(schema) || {})), { type: (0,
|
|
856
|
+
return Object.assign(Object.assign({}, (this.resolveRefObject(schema) || {})), { type: (0, util_2.isReferenceObject)(schema)
|
|
812
857
|
? this.resolveRefObject(schema).type
|
|
813
858
|
: schema.type });
|
|
814
859
|
}
|
package/dist/generator/type.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ProjectOptions } from 'ts-morph';
|
|
2
|
+
import { type MutuallyExclusive, OperationObject, ParameterObject, SchemaObject } from '../type';
|
|
2
3
|
import { TypescriptFileType } from './config';
|
|
3
4
|
export type ITypescriptFileType = keyof typeof TypescriptFileType;
|
|
4
5
|
export interface APIDataType extends OperationObject {
|
|
@@ -36,3 +37,17 @@ export interface ISchemaItem {
|
|
|
36
37
|
typeName: string;
|
|
37
38
|
type: string;
|
|
38
39
|
}
|
|
40
|
+
export declare enum MergeRule {
|
|
41
|
+
LEFT = "left",
|
|
42
|
+
RIGHT = "right"
|
|
43
|
+
}
|
|
44
|
+
export type MergeOption = MutuallyExclusive<{
|
|
45
|
+
source: string;
|
|
46
|
+
srcPath: string;
|
|
47
|
+
}>;
|
|
48
|
+
type MergerOptionProps = {
|
|
49
|
+
mergeRule: MergeRule;
|
|
50
|
+
projectOptions: ProjectOptions;
|
|
51
|
+
};
|
|
52
|
+
export type MergerOptions = MergeOption & Partial<MergerOptionProps>;
|
|
53
|
+
export {};
|
package/dist/generator/type.js
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MergeRule = void 0;
|
|
4
|
+
var MergeRule;
|
|
5
|
+
(function (MergeRule) {
|
|
6
|
+
MergeRule["LEFT"] = "left";
|
|
7
|
+
MergeRule["RIGHT"] = "right";
|
|
8
|
+
})(MergeRule || (exports.MergeRule = MergeRule = {}));
|
package/dist/generator/util.d.ts
CHANGED
|
@@ -22,3 +22,4 @@ export declare function resolveRefs(obj: OpenAPIObject, fields: string[]): unkno
|
|
|
22
22
|
export declare function isAllNumeric(arr: any): boolean;
|
|
23
23
|
export declare function isAllNumber(arr: any): boolean;
|
|
24
24
|
export declare function capitalizeFirstLetter(str: string): string;
|
|
25
|
+
export declare const parseDescriptionEnum: (description: string) => Map<number, string>;
|
package/dist/generator/util.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseDescriptionEnum = void 0;
|
|
3
4
|
exports.stripDot = stripDot;
|
|
4
5
|
exports.resolveTypeName = resolveTypeName;
|
|
5
6
|
exports.getRefName = getRefName;
|
|
@@ -343,3 +344,49 @@ function isAllNumber(arr) {
|
|
|
343
344
|
function capitalizeFirstLetter(str) {
|
|
344
345
|
return str.replace(/^[a-z]/, (match) => match.toUpperCase());
|
|
345
346
|
}
|
|
347
|
+
// 解析 description 中的枚举翻译
|
|
348
|
+
const parseDescriptionEnum = (description) => {
|
|
349
|
+
const enumMap = new Map();
|
|
350
|
+
if (!description)
|
|
351
|
+
return enumMap;
|
|
352
|
+
// 首先处理可能的总体描述,例如 "系统用户角色:User=0,..."
|
|
353
|
+
let descToProcess = description;
|
|
354
|
+
const mainDescriptionMatch = description.match(/^([^:]+):(.*)/);
|
|
355
|
+
if (mainDescriptionMatch) {
|
|
356
|
+
// 如果有总体描述(如 "系统用户角色:"),只处理冒号后面的部分
|
|
357
|
+
descToProcess = mainDescriptionMatch[2];
|
|
358
|
+
}
|
|
359
|
+
// 匹配形如 "User(普通用户)=0" 或 "User=0" 的模式
|
|
360
|
+
const enumPattern = /([^():,=]+)(?:\(([^)]+)\))?=(\d+)/g;
|
|
361
|
+
let match;
|
|
362
|
+
while ((match = enumPattern.exec(descToProcess)) !== null) {
|
|
363
|
+
const name = match[1] ? match[1].trim() : '';
|
|
364
|
+
const valueStr = match[3] ? match[3].trim() : '';
|
|
365
|
+
if (valueStr && !isNaN(Number(valueStr))) {
|
|
366
|
+
// 统一使用英文key(如User)
|
|
367
|
+
enumMap.set(Number(valueStr), name);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// 如果没有匹配到任何枚举,尝试使用简单的分割方法作为后备
|
|
371
|
+
if (enumMap.size === 0) {
|
|
372
|
+
const pairs = descToProcess.split(',');
|
|
373
|
+
pairs.forEach((pair) => {
|
|
374
|
+
const parts = pair.split('=');
|
|
375
|
+
if (parts.length === 2) {
|
|
376
|
+
let label = parts[0].trim();
|
|
377
|
+
const value = parts[1].trim();
|
|
378
|
+
// 处理可能带有括号的情况
|
|
379
|
+
const bracketMatch = label.match(/([^(]+)\(([^)]+)\)/);
|
|
380
|
+
if (bracketMatch) {
|
|
381
|
+
// 只使用括号前的英文key
|
|
382
|
+
label = bracketMatch[1].trim();
|
|
383
|
+
}
|
|
384
|
+
if (label && value && !isNaN(Number(value))) {
|
|
385
|
+
enumMap.set(Number(value), label);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
return enumMap;
|
|
391
|
+
};
|
|
392
|
+
exports.parseDescriptionEnum = parseDescriptionEnum;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { APIDataType } from './generator/type';
|
|
2
|
-
import { ComponentsObject, IPriorityRule, IReactQueryMode, OpenAPIObject, OperationObject, ReferenceObject, SchemaObject } from './type';
|
|
2
|
+
import { ComponentsObject, type GetSchemaByApifoxProps, IPriorityRule, IReactQueryMode, OpenAPIObject, OperationObject, ReferenceObject, SchemaObject } from './type';
|
|
3
3
|
export * from './generator/patchSchema';
|
|
4
4
|
export type GenerateServiceProps = {
|
|
5
5
|
/**
|
|
@@ -17,6 +17,10 @@ export type GenerateServiceProps = {
|
|
|
17
17
|
* 方式二: import request from '@/request';
|
|
18
18
|
*/
|
|
19
19
|
requestLibPath?: string;
|
|
20
|
+
/**
|
|
21
|
+
* 是否全量替换, 默认: true, 如果为false, 则进行增量替换
|
|
22
|
+
*/
|
|
23
|
+
full?: boolean;
|
|
20
24
|
/**
|
|
21
25
|
* 开启日志
|
|
22
26
|
*/
|
|
@@ -93,6 +97,10 @@ export type GenerateServiceProps = {
|
|
|
93
97
|
* 文档权限凭证
|
|
94
98
|
*/
|
|
95
99
|
authorization?: string;
|
|
100
|
+
/**
|
|
101
|
+
* apifox 配置
|
|
102
|
+
*/
|
|
103
|
+
apifoxConfig?: GetSchemaByApifoxProps;
|
|
96
104
|
/**
|
|
97
105
|
* 默认为false,true时使用null代替可选值
|
|
98
106
|
*/
|
|
@@ -109,6 +117,10 @@ export type GenerateServiceProps = {
|
|
|
109
117
|
* 模板文件、请求函数采用小驼峰命名
|
|
110
118
|
*/
|
|
111
119
|
isCamelCase?: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* 是否使用 description 中的枚举定义
|
|
122
|
+
*/
|
|
123
|
+
isSupportParseEnumDesc?: boolean;
|
|
112
124
|
/**
|
|
113
125
|
* 命名空间名称,默认为API,不需要关注
|
|
114
126
|
*/
|
|
@@ -117,6 +129,14 @@ export type GenerateServiceProps = {
|
|
|
117
129
|
* 模板文件的文件路径,不需要关注
|
|
118
130
|
*/
|
|
119
131
|
templatesFolder?: string;
|
|
132
|
+
/**
|
|
133
|
+
* 请求超时时间
|
|
134
|
+
*/
|
|
135
|
+
timeout?: number;
|
|
136
|
+
/**
|
|
137
|
+
* 多网关唯一标识
|
|
138
|
+
*/
|
|
139
|
+
uniqueKey?: string;
|
|
120
140
|
/**
|
|
121
141
|
* 自定义 hook
|
|
122
142
|
*/
|
|
@@ -124,7 +144,7 @@ export type GenerateServiceProps = {
|
|
|
124
144
|
/** change open api data after constructor */
|
|
125
145
|
afterOpenApiDataInited?: (openAPIData: OpenAPIObject) => OpenAPIObject;
|
|
126
146
|
/** 自定义函数名称 */
|
|
127
|
-
customFunctionName?: (data: APIDataType) => string;
|
|
147
|
+
customFunctionName?: (data: APIDataType, prefix?: string) => string;
|
|
128
148
|
/** 自定义类型名称 */
|
|
129
149
|
customTypeName?: (data: APIDataType) => string;
|
|
130
150
|
/** 自定义 options 默认值 */
|
|
@@ -135,17 +155,17 @@ export type GenerateServiceProps = {
|
|
|
135
155
|
* 自定义获取type hook
|
|
136
156
|
* 返回非字符串将使用默认方法获取type
|
|
137
157
|
* @example set number to string
|
|
138
|
-
* function customType(schemaObject,namespace){
|
|
158
|
+
* function customType({ schemaObject, namespace }){
|
|
139
159
|
* if(schemaObject.type==='number' && !schemaObject.format){
|
|
140
160
|
* return 'BigDecimalString';
|
|
141
161
|
* }
|
|
142
162
|
* }
|
|
143
163
|
*/
|
|
144
|
-
customType?: ({ schemaObject, namespace,
|
|
164
|
+
customType?: ({ schemaObject, namespace, originGetType, schemas, }: {
|
|
145
165
|
schemaObject: SchemaObject | ReferenceObject;
|
|
146
166
|
namespace: string;
|
|
167
|
+
originGetType: (schemaObject: SchemaObject, namespace: string, schemas?: ComponentsObject['schemas']) => string;
|
|
147
168
|
schemas?: ComponentsObject['schemas'];
|
|
148
|
-
originGetType: (schemaObject: SchemaObject, namespace: string) => string;
|
|
149
169
|
}) => string;
|
|
150
170
|
/**
|
|
151
171
|
* 自定义生成文件名,可返回多个,表示生成多个文件;
|
|
@@ -176,4 +196,4 @@ export type GenerateServiceProps = {
|
|
|
176
196
|
customFileNames?: (operationObject: OperationObject, apiPath: string, apiMethod: string) => string[] | null;
|
|
177
197
|
};
|
|
178
198
|
};
|
|
179
|
-
export declare function generateService({ requestLibPath, schemaPath, mockFolder, includeTags, excludeTags, authorization, isTranslateToEnglishTag, priorityRule, reactQueryMode, ...rest }: GenerateServiceProps): Promise<void>;
|
|
199
|
+
export declare function generateService({ requestLibPath, schemaPath, mockFolder, includeTags, excludeTags, authorization, isTranslateToEnglishTag, priorityRule, timeout, reactQueryMode, apifoxConfig, ...rest }: GenerateServiceProps): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -10,12 +10,18 @@ const util_1 = require("./util");
|
|
|
10
10
|
tslib_1.__exportStar(require("./generator/patchSchema"), exports);
|
|
11
11
|
function generateService(_a) {
|
|
12
12
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
13
|
-
var { requestLibPath, schemaPath, mockFolder, includeTags, excludeTags, authorization, isTranslateToEnglishTag, priorityRule = config_1.PriorityRule.include, reactQueryMode = config_1.ReactQueryMode.react } = _a, rest = tslib_1.__rest(_a, ["requestLibPath", "schemaPath", "mockFolder", "includeTags", "excludeTags", "authorization", "isTranslateToEnglishTag", "priorityRule", "reactQueryMode"]);
|
|
14
|
-
if (!schemaPath) {
|
|
13
|
+
var { requestLibPath, schemaPath, mockFolder, includeTags, excludeTags, authorization, isTranslateToEnglishTag, priorityRule = config_1.PriorityRule.include, timeout = 60000, reactQueryMode = config_1.ReactQueryMode.react, apifoxConfig } = _a, rest = tslib_1.__rest(_a, ["requestLibPath", "schemaPath", "mockFolder", "includeTags", "excludeTags", "authorization", "isTranslateToEnglishTag", "priorityRule", "timeout", "reactQueryMode", "apifoxConfig"]);
|
|
14
|
+
if (!schemaPath && !apifoxConfig) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
if (
|
|
17
|
+
let openAPI = null;
|
|
18
|
+
if (apifoxConfig) {
|
|
19
|
+
openAPI = (yield (0, util_1.getOpenAPIConfigByApifox)(apifoxConfig));
|
|
20
|
+
}
|
|
21
|
+
if (schemaPath) {
|
|
22
|
+
openAPI = (yield (0, util_1.getOpenAPIConfig)(schemaPath, authorization, timeout));
|
|
23
|
+
}
|
|
24
|
+
if (!openAPI || (0, lodash_1.isEmpty)(openAPI)) {
|
|
19
25
|
return;
|
|
20
26
|
}
|
|
21
27
|
if (isTranslateToEnglishTag) {
|
|
@@ -28,7 +34,7 @@ function generateService(_a) {
|
|
|
28
34
|
? [/.*/g]
|
|
29
35
|
: null, excludeTags: excludeTags
|
|
30
36
|
? (0, lodash_1.map)(excludeTags, (item) => typeof item === 'string' ? item.toLowerCase() : item)
|
|
31
|
-
: null, requestOptionsType: '{[key: string]: unknown}', namespace: 'API', isGenReactQuery: false, reactQueryMode, isGenJavaScript: false, isDisplayTypeLabel: false, isGenJsonSchemas: false, nullable: false, isOnlyGenTypeScriptType: false, isCamelCase: true }, rest), openAPI);
|
|
37
|
+
: null, requestOptionsType: '{[key: string]: unknown}', namespace: 'API', isGenReactQuery: false, reactQueryMode, isGenJavaScript: false, isDisplayTypeLabel: false, isGenJsonSchemas: false, nullable: false, isOnlyGenTypeScriptType: false, isCamelCase: true, isSupportParseEnumDesc: false, full: true }, rest), openAPI);
|
|
32
38
|
serviceGenerator.genFile();
|
|
33
39
|
if (mockFolder) {
|
|
34
40
|
(0, mockGenarator_1.mockGenerator)({
|
package/dist/log.d.ts
CHANGED
package/dist/log.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logError = void 0;
|
|
3
4
|
const tslib_1 = require("tslib");
|
|
4
5
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
5
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
|
+
exports.logError = logError;
|
|
6
9
|
exports.default = log;
|