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.
@@ -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 util_1 = require("./util");
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) || util_1.getDefaultFileTag;
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, lodash_1.camelCase)((0, util_1.resolveTypeName)(tag))
123
- : (0, util_1.resolveTypeName)(tag);
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
- try {
134
- (0, glob_1.globSync)(`${this.config.serversPath}/**/*`)
135
- .filter((item) => !item.includes('_deperated'))
136
- .forEach((item) => {
137
- (0, rimraf_1.sync)(item);
138
- });
139
- }
140
- catch (error) {
141
- (0, log_1.default)(`🚥 api 生成失败: ${error}`);
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, util_1.handleDuplicateTypeNames)(interfaceTPConfigs);
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, util_1.getFinalFileName)(`${tp.className}.js`)
184
- : (0, util_1.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));
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, util_1.getFinalFileName)(`${tp.className}.${reactQueryFileName}.js`)
189
- : (0, util_1.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));
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, util_1.handleDuplicateTypeNames)(this.schemaList);
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) || util_1.getDefaultFileTag;
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, util_1.markAllowedSchema)(JSON.stringify(pathItem), this.openAPIData);
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, lodash_1.camelCase)(`display-${item.name}-Enum`),
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, util_1.resolveTypeName)(schemaKey);
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, lodash_1.camelCase)(`display-${typeName}-Enum`)
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, util_1.resolveTypeName)(schemaKey)}`,
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, lodash_1.camelCase)(functionName)
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, util_1.replaceDot)(tag) || `api${index}`;
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', util_1.capitalizeFirstLetter);
471
- return (0, file_1.writeFile)(this.config.serversPath, fileName, nunjucks_1.default.renderString(template, Object.assign({ disableTypeCheck: false }, params)));
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, util_1.getBasePrefix)((0, lodash_1.keys)(this.openAPIData.paths));
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.operationId
487
- ? (0, util_1.resolveFunctionName)((0, util_1.stripDot)(data.operationId), data.method)
488
- : data.method + (0, util_1.genDefaultFunctionName)(data.path, pathBasePrefix);
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: util_1.getDefaultType,
526
+ originGetType: util_2.getDefaultType,
500
527
  });
501
528
  if (typeof type === 'string') {
502
529
  return type;
503
530
  }
504
531
  }
505
- return (0, util_1.getDefaultType)(schemaObject, namespace, schemas);
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, util_1.resolveTypeName)(`${namespace}${typeName !== null && typeName !== void 0 ? typeName : data.operationId}Params`);
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, util_1.isBinaryArraySchemaObject)(propertyObj)) {
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, util_1.isBinaryArraySchemaObject)(p))) ||
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, util_1.isReferenceObject)(schema)) {
611
- const refName = (0, util_1.getLastRefName)(schema.$ref);
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, util_1.isNonArraySchemaObject)(childrenSchema) && this.config.dataFields) {
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, util_1.isSchemaObject)(schema)) {
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, util_1.getLastRefName)(((_b = p.schema) === null || _b === void 0 ? void 0 : _b.$ref) ||
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, util_1.isReferenceObject)(schemaObject)) {
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, util_1.isArraySchemaObject)(schemaObject)) {
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, util_1.isReferenceObject)(schemaObject.items)) {
699
- const refName = (0, util_1.getRefName)(schemaObject.items);
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, util_1.isAllNumber)(enumArray)) {
723
- enumStr = `{${(0, lodash_1.map)(enumArray, (value) => `"NUMBER_${value}"=${Number(value)}`).join(',')}}`;
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, util_1.isAllNumeric)(enumArray)) {
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, util_1.isAllNumber)(enumArray)) {
753
- enumLabelTypeStr = `{${(0, lodash_1.map)(enumArray, (value) => `"NUMBER_${value}":${Number(value)}`).join(',')}}`;
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, util_1.isAllNumeric)(enumArray)) {
756
- enumLabelTypeStr = `{${(0, lodash_1.map)(enumArray, (value) => `"STRING_NUMBER_${value}":"${value}"`).join(',')}}`;
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, util_1.isReferenceObject)(item)
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, util_1.isReferenceObject)(refObject)) {
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, util_1.resolveRefs)(this.openAPIData, refPaths.slice(1));
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, util_1.isReferenceObject)(schema)
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
  }
@@ -1,4 +1,5 @@
1
- import { OperationObject, ParameterObject, SchemaObject } from '../type';
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 {};
@@ -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 = {}));
@@ -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>;
@@ -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, schemas, originGetType, }: {
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
- const openAPI = (yield (0, util_1.getOpenAPIConfig)(schemaPath, authorization));
18
- if ((0, lodash_1.isEmpty)(openAPI)) {
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
@@ -1,2 +1,3 @@
1
1
  declare const log: (...rest: any[]) => void;
2
+ export declare const logError: (...rest: any[]) => void;
2
3
  export default log;
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;
@@ -0,0 +1,2 @@
1
+ import type { ReadConfigOptions } from './type';
2
+ export declare const readConfig: <T = unknown>({ fileName, filePath, fallbackName, }: ReadConfigOptions) => Promise<T | undefined>;