openapi-ts-request 0.13.4 → 1.0.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 CHANGED
@@ -6,10 +6,11 @@
6
6
 
7
7
  根据 [Swagger2/OpenAPI3/Apifox](https://swagger.io/blog/news/whats-new-in-openapi-3-0/) 文档生成:
8
8
 
9
- - TS 类型
10
- - 客户端请求函数
9
+ - TypeScript/JavaScript
10
+ - 客户端请求函数(支持任意客户端)
11
11
  - 模拟请求响应服务
12
12
  - 枚举和枚举翻译
13
+ - react-query
13
14
  - 类型字段翻译
14
15
  - JSON Schemas
15
16
 
@@ -18,9 +19,9 @@
18
19
  ## 功能
19
20
 
20
21
  - 支持 Swagger2.0/OpenAPI/Apifox 3.0,3.1 定义
21
- - 生成 TS 类型, 请求客户端, 请求模拟服务, 枚举, 类型字段翻译, JSON Schemas
22
+ - 生成 TypeScript/JavaScript, 请求客户端(支持任意客户端), 请求模拟服务, 枚举和枚举翻译, react-query, 类型字段翻译, JSON Schemas
22
23
  - 支持通过 npx、CLI、Nodejs 的方式使用
23
- - 支持自定义请求工具函数, 支持 Fetch、Axios、[UniApp-Request](https://github.com/openapi-ui/openapi-ts-request/issues/46)、Node.js、XHR 客户端
24
+ - 支持自定义请求工具函数, 支持 Fetch、Axios、[UniApp-Request](https://github.com/openapi-ui/openapi-ts-request/issues/46)、Taro-Request、Node.js、XHR 客户端
24
25
  - 支持通过 tags 过滤生成结果
25
26
  - 支持 JSON/YAML 定义文件
26
27
  - 支持将中文 tag 名称翻译为英文 tag 名称
@@ -94,10 +95,13 @@ import request from 'axios';
94
95
  import * as API from './types';
95
96
 
96
97
  /** Update an existing pet PUT /pet */
97
- export async function updatePet(
98
- body: API.Pet,
99
- options?: { [key: string]: unknown }
100
- ) {
98
+ export async function updatePet({
99
+ body,
100
+ options,
101
+ }: {
102
+ body: API.Pet;
103
+ options?: { [key: string]: unknown };
104
+ }) {
101
105
  return request<unknown>(`/pet`, {
102
106
  method: 'PUT',
103
107
  headers: {
@@ -177,31 +181,30 @@ $ openapi --help
177
181
  Usage: openapi [options]
178
182
 
179
183
  Options:
180
- -V, --version output the version number
181
- -i, --input <string> OpenAPI specification, can be a path, url (required)
182
- -o, --output <string> output directory (required)
183
- --requestLibPath <string> custom request lib path, for example: "@/request", "node-fetch" (default: "axios")
184
- --enableLogging <boolean> open the log (default: false)
185
- --priorityRule <string> priority rule, include/exclude/both (default: "include")
186
- --includeTags <(string|RegExp)[]> generate code from include tags
187
- --includePaths <(string|RegExp)[]> generate code from include paths
188
- --excludeTags <(string|RegExp)[]> generate code from exclude tags
189
- --excludePaths <(string|RegExp)[]> generate code from exclude paths
190
- --requestOptionsType <string> custom request method options parameter type (default: "{ [key:
191
- string]: unknown }")
192
- --requestImportStatement <string> custom request import statement, for example: "const request =
193
- require('@/request')"
194
- --apiPrefix <string> custom the prefix of the api path, for example: "api"(variable),
195
- "'api'"(string)
196
- --isDisplayTypeLabel <boolean> generate label matching type field (default: false)
197
- --isGenJsonSchemas <boolean> generate JSON Schemas (default: false)
198
- --mockFolder <string> mock file path, for example: './mocks'
199
- --authorization <string> docs authorization
200
- --nullable <boolean> null instead of optional (default: false)
201
- --isTranslateToEnglishTag <boolean>translate chinese tag name to english tag name (default: false)
202
- --isOnlyGenTypeScriptType <boolean>only generate typescript type (default: false)
203
- --isCamelCase <boolean> camelCase naming of controller files and request client (default: true)
204
- -h, --help display help for command
184
+ -V, --version output the version number
185
+ -i, --input <string> OpenAPI specification, can be a path, url (required)
186
+ -o, --output <string> output directory (required)
187
+ --requestLibPath <string> custom request lib path, for example: "@/request", "node-fetch" (default: "axios")
188
+ --enableLogging <boolean> open the log (default: false)
189
+ --priorityRule <string> priority rule, include/exclude/both (default: "include")
190
+ --includeTags <(string|RegExp)[]> generate code from include tags
191
+ --includePaths <(string|RegExp)[]> generate code from include paths
192
+ --excludeTags <(string|RegExp)[]> generate code from exclude tags
193
+ --excludePaths <(string|RegExp)[]> generate code from exclude paths
194
+ --requestOptionsType <string> custom request method options parameter type (default: "{ [key: string]: unknown }")
195
+ --requestImportStatement <string> custom request import statement, for example: "const request = require('@/request')"
196
+ --apiPrefix <string> custom the prefix of the api path, for example: "api"(variable), "'api'"(string)
197
+ --isGenReactQuery <boolean> generate react-query (default: false)
198
+ --isGenJavaScript <boolean> generate JavaScript (default: false)
199
+ --isDisplayTypeLabel <boolean> generate label matching type field (default: false)
200
+ --isGenJsonSchemas <boolean> generate JSON Schemas (default: false)
201
+ --mockFolder <string> mock file path, for example: './mocks'
202
+ --authorization <string> docs authorization
203
+ --nullable <boolean> null instead of optional (default: false)
204
+ --isTranslateToEnglishTag <boolean> translate chinese tag name to english tag name (default: false)
205
+ --isOnlyGenTypeScriptType <boolean> only generate typescript type (default: false)
206
+ --isCamelCase <boolean> camelCase naming of controller files and request client (default: true)
207
+ -h, --help display help for command
205
208
  ```
206
209
 
207
210
  运行:
@@ -226,6 +229,8 @@ openapi --i ./spec.json --o ./apis
226
229
  | requestOptionsType | 否 | string | '{ [key: string]: unknown }' | 自定义请求方法 options 参数类型 |
227
230
  | requestImportStatement | 否 | string | - | 自定义请求方法表达式,例如:"const request = require('@/request')" |
228
231
  | apiPrefix | 否 | string | - | api path的前缀,例如:'api'(动态变量), "'api'"(字符串) |
232
+ | isGenReactQuery | 否 | boolean | false | 是否生成 react-query |
233
+ | isGenJavaScript | 否 | boolean | false | 是否生成 JavaScript |
229
234
  | isDisplayTypeLabel | 否 | boolean | false | 是否生成 type 对应的label |
230
235
  | isGenJsonSchemas | 否 | boolean | false | 是否生成 JSON Schemas |
231
236
  | mockFolder | 否 | string | - | mock文件路径,例如:'./mocks' |
@@ -22,6 +22,8 @@ const params = commander_1.program
22
22
  .option('--requestOptionsType <string>', 'custom request method options parameter type (default: "{ [key: string]: unknown }")')
23
23
  .option('--requestImportStatement <string>', `custom request import statement, for example: "const request = require('@/request')"`)
24
24
  .option('--apiPrefix <string>', `custom the prefix of the api path, for example: "api"(variable), "'api'"(string)`)
25
+ .option('--isGenReactQuery <boolean>', 'generate react-query', false)
26
+ .option('--isGenJavaScript <boolean>', 'generate JavaScript', false)
25
27
  .option('--isDisplayTypeLabel <boolean>', 'generate label matching type field', false)
26
28
  .option('--isGenJsonSchemas <boolean>', 'generate JSON Schemas', false)
27
29
  .option('--mockFolder <string>', 'mock file path')
@@ -56,6 +58,8 @@ function run() {
56
58
  excludePaths: params.excludePaths,
57
59
  requestOptionsType: params.requestOptionsType,
58
60
  apiPrefix: params.apiPrefix,
61
+ isGenReactQuery: JSON.parse(params.isGenReactQuery) === true,
62
+ isGenJavaScript: JSON.parse(params.isGenJavaScript) === true,
59
63
  isDisplayTypeLabel: JSON.parse(params.isDisplayTypeLabel) === true,
60
64
  isGenJsonSchemas: JSON.parse(params.isGenJsonSchemas) === true,
61
65
  mockFolder: params.mockFolder,
@@ -5,13 +5,15 @@ export declare const interfaceFileName = "types";
5
5
  export declare const displayEnumLabelFileName = "displayEnumLabel";
6
6
  export declare const displayTypeLabelFileName = "displayTypeLabel";
7
7
  export declare const schemaFileName = "schema";
8
+ export declare const reactQueryFileName = "reactquery";
8
9
  export declare enum TypescriptFileType {
9
10
  interface = "interface",
10
11
  serviceController = "serviceController",
11
12
  serviceIndex = "serviceIndex",
12
13
  displayEnumLabel = "displayEnumLabel",
13
14
  displayTypeLabel = "displayTypeLabel",
14
- schema = "schema"
15
+ schema = "schema",
16
+ reactQuery = "reactQuery"
15
17
  }
16
18
  export declare const DEFAULT_SCHEMA: SchemaObject;
17
19
  export declare const DEFAULT_PATH_PARAM: ParameterObject & Dictionary<unknown>;
@@ -32,3 +34,7 @@ export declare enum parametersInsEnum {
32
34
  export declare const parametersIn: string[];
33
35
  export declare const numberEnum: string[];
34
36
  export declare const lineBreakReg: RegExp;
37
+ export declare enum LangType {
38
+ ts = "ts",
39
+ js = "js"
40
+ }
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.lineBreakReg = exports.numberEnum = exports.parametersIn = exports.parametersInsEnum = exports.methods = exports.DEFAULT_PATH_PARAM = exports.DEFAULT_SCHEMA = exports.TypescriptFileType = exports.schemaFileName = exports.displayTypeLabelFileName = exports.displayEnumLabelFileName = exports.interfaceFileName = exports.serviceEntryFileName = void 0;
3
+ exports.LangType = exports.lineBreakReg = exports.numberEnum = exports.parametersIn = exports.parametersInsEnum = exports.methods = exports.DEFAULT_PATH_PARAM = exports.DEFAULT_SCHEMA = exports.TypescriptFileType = exports.reactQueryFileName = exports.schemaFileName = exports.displayTypeLabelFileName = exports.displayEnumLabelFileName = exports.interfaceFileName = exports.serviceEntryFileName = void 0;
4
4
  exports.serviceEntryFileName = 'index';
5
5
  exports.interfaceFileName = 'types';
6
6
  exports.displayEnumLabelFileName = 'displayEnumLabel';
7
7
  exports.displayTypeLabelFileName = 'displayTypeLabel';
8
8
  exports.schemaFileName = 'schema';
9
+ exports.reactQueryFileName = 'reactquery';
9
10
  var TypescriptFileType;
10
11
  (function (TypescriptFileType) {
11
12
  TypescriptFileType["interface"] = "interface";
@@ -14,6 +15,7 @@ var TypescriptFileType;
14
15
  TypescriptFileType["displayEnumLabel"] = "displayEnumLabel";
15
16
  TypescriptFileType["displayTypeLabel"] = "displayTypeLabel";
16
17
  TypescriptFileType["schema"] = "schema";
18
+ TypescriptFileType["reactQuery"] = "reactQuery";
17
19
  })(TypescriptFileType || (exports.TypescriptFileType = TypescriptFileType = {}));
18
20
  exports.DEFAULT_SCHEMA = {
19
21
  type: 'object',
@@ -59,3 +61,8 @@ exports.numberEnum = [
59
61
  ];
60
62
  // 匹配换行符的正则
61
63
  exports.lineBreakReg = /[\r\n]+/g;
64
+ var LangType;
65
+ (function (LangType) {
66
+ LangType["ts"] = "ts";
67
+ LangType["js"] = "js";
68
+ })(LangType || (exports.LangType = LangType = {}));
@@ -4,7 +4,6 @@ import { ControllerType, ISchemaItem, TagAPIDataType } from './type';
4
4
  export default class ServiceGenerator {
5
5
  protected apiData: TagAPIDataType;
6
6
  protected classNameList: ControllerType[];
7
- protected finalPath: string;
8
7
  protected config: GenerateServiceProps;
9
8
  protected openAPIData: OpenAPIObject;
10
9
  protected schemaList: ISchemaItem[];
@@ -20,7 +20,6 @@ class ServiceGenerator {
20
20
  this.apiData = {};
21
21
  this.classNameList = [];
22
22
  this.schemaList = [];
23
- this.finalPath = '';
24
23
  this.config = Object.assign({ templatesFolder: (0, path_1.join)(__dirname, '../../', 'templates') }, config);
25
24
  this.generateInfoLog();
26
25
  const includeTags = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.includeTags) || [];
@@ -141,17 +140,21 @@ class ServiceGenerator {
141
140
  catch (error) {
142
141
  (0, log_1.default)(`🚥 api 生成失败: ${error}`);
143
142
  }
143
+ const isOnlyGenTypeScriptType = this.config.isOnlyGenTypeScriptType;
144
+ const isGenJavaScript = this.config.isGenJavaScript;
144
145
  // 处理重复的 typeName
145
146
  const interfaceTPConfigs = this.getInterfaceTPConfigs();
146
147
  (0, util_1.handleDuplicateTypeNames)(interfaceTPConfigs);
147
148
  // 生成 ts 类型声明
148
- this.genFileFromTemplate(`${config_1.interfaceFileName}.ts`, config_1.TypescriptFileType.interface, {
149
- nullable: this.config.nullable,
150
- list: interfaceTPConfigs,
151
- });
149
+ if (!isGenJavaScript) {
150
+ this.genFileFromTemplate(`${config_1.interfaceFileName}.ts`, config_1.TypescriptFileType.interface, {
151
+ nullable: this.config.nullable,
152
+ list: interfaceTPConfigs,
153
+ });
154
+ }
152
155
  // 生成枚举翻译
153
156
  const enums = (0, lodash_1.filter)(interfaceTPConfigs, (item) => item.isEnum);
154
- if (!this.config.isOnlyGenTypeScriptType && !(0, lodash_1.isEmpty)(enums)) {
157
+ if (!isGenJavaScript && !isOnlyGenTypeScriptType && !(0, lodash_1.isEmpty)(enums)) {
155
158
  this.genFileFromTemplate(`${config_1.displayEnumLabelFileName}.ts`, config_1.TypescriptFileType.displayEnumLabel, {
156
159
  list: enums,
157
160
  namespace: this.config.namespace,
@@ -160,7 +163,8 @@ class ServiceGenerator {
160
163
  }
161
164
  const displayTypeLabels = (0, lodash_1.filter)(interfaceTPConfigs, (item) => !item.isEnum);
162
165
  // 生成 type 翻译
163
- if (!this.config.isOnlyGenTypeScriptType &&
166
+ if (!isGenJavaScript &&
167
+ !isOnlyGenTypeScriptType &&
164
168
  this.config.isDisplayTypeLabel &&
165
169
  !(0, lodash_1.isEmpty)(displayTypeLabels)) {
166
170
  this.genFileFromTemplate(`${config_1.displayTypeLabelFileName}.ts`, config_1.TypescriptFileType.displayTypeLabel, {
@@ -169,39 +173,51 @@ class ServiceGenerator {
169
173
  interfaceFileName: config_1.interfaceFileName,
170
174
  });
171
175
  }
172
- if (!this.config.isOnlyGenTypeScriptType) {
176
+ if (!isOnlyGenTypeScriptType) {
173
177
  const prettierError = [];
174
178
  // 生成 service controller 文件
175
179
  this.getServiceTPConfigs().forEach((tp) => {
176
- const hasError = this.genFileFromTemplate((0, util_1.getFinalFileName)(`${tp.className}.ts`), config_1.TypescriptFileType.serviceController, Object.assign({ namespace: this.config.namespace, requestOptionsType: this.config.requestOptionsType, requestImportStatement: this.config.requestImportStatement, interfaceFileName: config_1.interfaceFileName }, tp));
180
+ const hasError = this.genFileFromTemplate(isGenJavaScript
181
+ ? (0, util_1.getFinalFileName)(`${tp.className}.js`)
182
+ : (0, util_1.getFinalFileName)(`${tp.className}.ts`), config_1.TypescriptFileType.serviceController, Object.assign({ namespace: this.config.namespace, requestOptionsType: this.config.requestOptionsType, requestImportStatement: this.config.requestImportStatement, interfaceFileName: config_1.interfaceFileName }, tp));
177
183
  prettierError.push(hasError);
184
+ if (this.config.isGenReactQuery) {
185
+ this.genFileFromTemplate(isGenJavaScript
186
+ ? (0, util_1.getFinalFileName)(`${tp.className}.${config_1.reactQueryFileName}.js`)
187
+ : (0, util_1.getFinalFileName)(`${tp.className}.${config_1.reactQueryFileName}.ts`), config_1.TypescriptFileType.reactQuery, Object.assign({ namespace: this.config.namespace, requestOptionsType: this.config.requestOptionsType, requestImportStatement: this.config.requestImportStatement, interfaceFileName: config_1.interfaceFileName }, tp));
188
+ }
178
189
  });
179
190
  if (prettierError.includes(true)) {
180
191
  (0, log_1.default)('🚥 格式化失败,请检查 service controller 文件内可能存在的语法错误');
181
192
  }
182
193
  }
183
- if (!this.config.isOnlyGenTypeScriptType &&
194
+ if (!isOnlyGenTypeScriptType &&
184
195
  this.config.isGenJsonSchemas &&
185
196
  !(0, lodash_1.isEmpty)(this.schemaList)) {
186
197
  // 处理重复的 schemaName
187
198
  (0, util_1.handleDuplicateTypeNames)(this.schemaList);
188
199
  // 生成 schema 文件
189
- this.genFileFromTemplate(`${config_1.schemaFileName}.ts`, config_1.TypescriptFileType.schema, {
200
+ this.genFileFromTemplate(isGenJavaScript ? `${config_1.schemaFileName}.js` : `${config_1.schemaFileName}.ts`, config_1.TypescriptFileType.schema, {
190
201
  list: this.schemaList,
191
202
  });
192
203
  }
193
204
  // 生成 service index 文件
194
- this.genFileFromTemplate(`${config_1.serviceEntryFileName}.ts`, config_1.TypescriptFileType.serviceIndex, {
205
+ this.genFileFromTemplate(isGenJavaScript
206
+ ? `${config_1.serviceEntryFileName}.js`
207
+ : `${config_1.serviceEntryFileName}.ts`, config_1.TypescriptFileType.serviceIndex, {
195
208
  list: this.classNameList,
196
209
  namespace: this.config.namespace,
197
210
  interfaceFileName: config_1.interfaceFileName,
198
- isGenJsonSchemas: !this.config.isOnlyGenTypeScriptType &&
211
+ genType: isGenJavaScript ? config_1.LangType.js : config_1.LangType.ts,
212
+ isGenJsonSchemas: !isOnlyGenTypeScriptType &&
199
213
  this.config.isGenJsonSchemas &&
200
214
  !(0, lodash_1.isEmpty)(this.schemaList),
201
215
  schemaFileName: config_1.schemaFileName,
202
- isDisplayEnumLabel: !this.config.isOnlyGenTypeScriptType && !(0, lodash_1.isEmpty)(enums),
216
+ isDisplayEnumLabel: !isOnlyGenTypeScriptType && !(0, lodash_1.isEmpty)(enums),
203
217
  displayEnumLabelFileName: config_1.displayEnumLabelFileName,
204
- isDisplayTypeLabel: !this.config.isOnlyGenTypeScriptType &&
218
+ isGenReactQuery: this.config.isGenReactQuery,
219
+ reactQueryFileName: config_1.reactQueryFileName,
220
+ isDisplayTypeLabel: !isOnlyGenTypeScriptType &&
205
221
  this.config.isDisplayTypeLabel &&
206
222
  !(0, lodash_1.isEmpty)(displayTypeLabels),
207
223
  displayTypeLabelFileName: config_1.displayTypeLabelFileName,
@@ -228,7 +244,7 @@ class ServiceGenerator {
228
244
  if ((0, lodash_1.isEmpty)(includeTags) || (!(0, lodash_1.isEmpty)(includeTags) && (0, lodash_1.isEmpty)(tags))) {
229
245
  return;
230
246
  }
231
- const flag = this.validateRegexp((0, lodash_1.map)(tags, (tag) => tag.toLowerCase()), includeTags);
247
+ const flag = this.validateRegexp((0, lodash_1.filter)((0, lodash_1.map)(tags, (tag) => (tag === null || tag === void 0 ? void 0 : tag.toLowerCase) ? tag.toLowerCase() : undefined), (tag) => !!tag), includeTags);
232
248
  if (!flag) {
233
249
  return;
234
250
  }
@@ -434,7 +450,7 @@ class ServiceGenerator {
434
450
  });
435
451
  }
436
452
  return {
437
- genType: 'ts',
453
+ genType: this.config.isGenJavaScript ? config_1.LangType.js : config_1.LangType.ts,
438
454
  className,
439
455
  instanceName: `${(_b = fileName[0]) === null || _b === void 0 ? void 0 : _b.toLowerCase()}${fileName.slice(1)}`,
440
456
  list: genParams,
@@ -446,9 +462,10 @@ class ServiceGenerator {
446
462
  try {
447
463
  const template = this.getTemplate(type);
448
464
  // 设置输出不转义
449
- nunjucks_1.default.configure({
465
+ const env = nunjucks_1.default.configure({
450
466
  autoescape: false,
451
467
  });
468
+ env.addFilter('capitalizeFirst', util_1.capitalizeFirstLetter);
452
469
  return (0, file_1.writeFile)(this.config.serversPath, fileName, nunjucks_1.default.renderString(template, Object.assign({ disableTypeCheck: false }, params)));
453
470
  }
454
471
  catch (error) {
@@ -21,3 +21,4 @@ export declare function isBinaryArraySchemaObject(schema: unknown): schema is Bi
21
21
  export declare function resolveRefs(obj: OpenAPIObject, fields: string[]): unknown;
22
22
  export declare function isAllNumeric(arr: any): boolean;
23
23
  export declare function isAllNumber(arr: any): boolean;
24
+ export declare function capitalizeFirstLetter(str: string): string;
@@ -21,6 +21,7 @@ exports.isBinaryArraySchemaObject = isBinaryArraySchemaObject;
21
21
  exports.resolveRefs = resolveRefs;
22
22
  exports.isAllNumeric = isAllNumeric;
23
23
  exports.isAllNumber = isAllNumber;
24
+ exports.capitalizeFirstLetter = capitalizeFirstLetter;
24
25
  const tslib_1 = require("tslib");
25
26
  const lodash_1 = require("lodash");
26
27
  const reserved_words_1 = tslib_1.__importDefault(require("reserved-words"));
@@ -159,7 +160,8 @@ function getDefaultType(schemaObject, namespace = '', schemas) {
159
160
  // 不使用 getRefName 函数处理,无法通过 schemas[schemaKey] 获取到schema
160
161
  const schemaKey = getLastRefName(item.$ref);
161
162
  if ((_a = schemas === null || schemas === void 0 ? void 0 : schemas[schemaKey]) === null || _a === void 0 ? void 0 : _a.enum) {
162
- return `I${getDefaultType(item, namespace)}`;
163
+ // return `I${getDefaultType(item, namespace)}`;
164
+ return getDefaultType(item, namespace);
163
165
  }
164
166
  }
165
167
  return getDefaultType(item, namespace);
@@ -338,3 +340,6 @@ function isAllNumeric(arr) {
338
340
  function isAllNumber(arr) {
339
341
  return (0, lodash_1.every)(arr, (item) => (0, lodash_1.isNumber)(item));
340
342
  }
343
+ function capitalizeFirstLetter(str) {
344
+ return str.replace(/^[a-z]/, (match) => match.toUpperCase());
345
+ }
package/dist/index.d.ts CHANGED
@@ -60,6 +60,14 @@ export type GenerateServiceProps = {
60
60
  namespace: string;
61
61
  functionName: string;
62
62
  }) => string);
63
+ /**
64
+ * 是否生成 react-query 配置
65
+ */
66
+ isGenReactQuery?: boolean;
67
+ /**
68
+ * 是否生成 JavaScript, 不生成 TypeScript
69
+ */
70
+ isGenJavaScript?: boolean;
63
71
  /**
64
72
  * 是否生成 type 对应的label, 默认: false
65
73
  */
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ function generateService(_a) {
28
28
  ? [/.*/g]
29
29
  : null, excludeTags: excludeTags
30
30
  ? (0, lodash_1.map)(excludeTags, (item) => typeof item === 'string' ? item.toLowerCase() : item)
31
- : null, requestOptionsType: '{[key: string]: unknown}', namespace: 'API', nullable: false, isCamelCase: true, isDisplayTypeLabel: false, isGenJsonSchemas: false, isOnlyGenTypeScriptType: false }, rest), openAPI);
31
+ : null, requestOptionsType: '{[key: string]: unknown}', namespace: 'API', isGenReactQuery: false, isGenJavaScript: false, isDisplayTypeLabel: false, isGenJsonSchemas: false, nullable: false, isOnlyGenTypeScriptType: false, isCamelCase: true }, rest), openAPI);
32
32
  serviceGenerator.genFile();
33
33
  if (mockFolder) {
34
34
  (0, mockGenarator_1.mockGenerator)({
package/dist/util.js CHANGED
@@ -20,7 +20,7 @@ const getImportStatement = (requestLibPath) => {
20
20
  }
21
21
  return `import request from '${requestLibPath}';`;
22
22
  }
23
- return `import request from 'axios';`;
23
+ return `import { request } from 'axios';`;
24
24
  };
25
25
  exports.getImportStatement = getImportStatement;
26
26
  function getSchema(schemaPath, authorization) {
@@ -140,29 +140,31 @@ function translateChineseModuleNodeToEnglish(openAPI) {
140
140
  });
141
141
  void Promise.all((0, lodash_1.map)((0, lodash_1.uniq)(tags), (tagName) => {
142
142
  return new Promise((resolve) => {
143
- void (0, bing_translate_api_1.translate)(tagName, null, 'en')
144
- .then((translateRes) => {
145
- const text = (0, lodash_1.camelCase)(translateRes === null || translateRes === void 0 ? void 0 : translateRes.translation);
146
- if (text) {
147
- translateMap[tagName] = text;
148
- resolve(text);
149
- }
150
- })
151
- .catch(() => {
143
+ if (tagName && /[\u3220-\uFA29]/.test(tagName)) {
144
+ void (0, bing_translate_api_1.translate)(tagName, null, 'en')
145
+ .then((translateRes) => {
146
+ const text = (0, lodash_1.camelCase)(translateRes === null || translateRes === void 0 ? void 0 : translateRes.translation);
147
+ if (text) {
148
+ translateMap[tagName] = text;
149
+ resolve(text);
150
+ }
151
+ })
152
+ .catch(() => {
153
+ resolve(tagName);
154
+ });
155
+ }
156
+ else {
152
157
  resolve(tagName);
153
- });
158
+ }
154
159
  });
155
160
  }))
156
161
  .then(() => {
157
- (0, lodash_1.map)(operations, (operation) => {
158
- var _a;
159
- const tagName = (_a = operation.tags) === null || _a === void 0 ? void 0 : _a[0];
160
- if (tagName && /[\u3220-\uFA29]/.test(tagName)) {
161
- operation.tags = [
162
- translateMap[tagName],
163
- ...operation.tags.slice(1),
164
- ];
165
- }
162
+ (0, lodash_1.forEach)(operations, (operation) => {
163
+ (0, lodash_1.forEach)(operation.tags, (tagName, index) => {
164
+ if (translateMap[tagName]) {
165
+ operation.tags[index] = translateMap[tagName];
166
+ }
167
+ });
166
168
  });
167
169
  resolve(true);
168
170
  })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "openapi-ts-request",
3
- "version": "0.13.4",
4
- "description": "Swagger2/OpenAPI3 to TypeScript, request client, request mock service, enum, type field label, JSON Schemas",
3
+ "version": "1.0.0",
4
+ "description": "Swagger2/OpenAPI3/Apifox to TypeScript/JavaScript, request client(support any client), request mock service, enum and enum translation, react-query, type field label, JSON Schemas",
5
5
  "engines": {
6
6
  "node": ">=18.0.0",
7
7
  "pnpm": ">=9"
@@ -51,6 +51,7 @@
51
51
  "@changesets/cli": "^2.27.6",
52
52
  "@commitlint/cli": "^19.2.1",
53
53
  "@commitlint/config-conventional": "^19.2.2",
54
+ "@tanstack/react-query": "^5.62.10",
54
55
  "@types/js-yaml": "^4.0.9",
55
56
  "@types/lodash": "^4.17.5",
56
57
  "@types/memoizee": "^0.4.11",
@@ -63,21 +64,25 @@
63
64
  "@typescript-eslint/parser": "^7.9.0",
64
65
  "eslint": "^8.57.1",
65
66
  "husky": "^9.0.11",
66
- "lint-staged": "^15.2.5",
67
+ "lint-staged": "^15.3.0",
67
68
  "openapi-types": "^12.1.3",
68
69
  "ts-node": "^10.9.2",
69
70
  "typescript": "5.7.2"
70
71
  },
71
72
  "keywords": [
72
73
  "openapi",
73
- "openapi3",
74
74
  "swagger",
75
- "openapi to ts",
76
- "openapi to request client",
77
- "openapi to axios client",
78
- "openapi to fetch client",
79
- "openapi to uni request client",
80
- "openapi to JSON Schemas"
75
+ "openapi-ts",
76
+ "swagger-ts",
77
+ "openapi-typescript",
78
+ "swagger-typescript",
79
+ "openapi-react-query",
80
+ "openapi-fetch",
81
+ "openapi-axios",
82
+ "openapi-uniapp",
83
+ "openapi-taro",
84
+ "openapi-node-fetch",
85
+ "openapi-JSON-Schemas"
81
86
  ],
82
87
  "scripts": {
83
88
  "start": "tsc -w",
@@ -0,0 +1,112 @@
1
+ {% if genType === "ts" %}
2
+ /* eslint-disable */
3
+ // @ts-ignore
4
+ {% endif -%}
5
+ import { queryOptions, useMutation } from '@tanstack/react-query';
6
+ {%- if genType === "ts" %}
7
+ import type { DefaultError } from '@tanstack/react-query';
8
+ {% endif %}
9
+
10
+ import * as apis from './{{ className }}';
11
+ {%- if genType === "ts" %}
12
+ import * as {{ namespace }} from './{{ interfaceFileName }}';
13
+ {% endif %}
14
+
15
+ {% for api in list %}
16
+ /** {{ api.desc if api.desc else '此处后端没有提供注释' }} {{ api.method | upper }} {{ api.pathInComment | safe }}{{ ' ' if api.apifoxRunLink else '' }}{{ api.apifoxRunLink }} */
17
+ {%- if api.method | lower === "get" %}
18
+ export function {{ api.functionName }}QueryOptions(options
19
+ {%- if genType === "ts" -%}
20
+ : {
21
+ {%- if api.params and api.hasParams %}
22
+ // 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
23
+ params
24
+ : {{ namespace }}.{{ api.typeName }}
25
+ {# header 入参 -#}
26
+ {% if api.params.header -%}
27
+ & { // header
28
+ {% for param in api.params.header -%}
29
+ {% if param.description -%}
30
+ /** {{ param.description }} */
31
+ {% endif -%}
32
+ '{{ param.name }}'
33
+ {{- "?" if not param.required }}
34
+ {{- (": " + param.type + ";") | safe }}
35
+ {% endfor -%}
36
+ }
37
+ {%- endif -%}
38
+ {%- if api.hasParams -%}
39
+ {{ ";" if api.body or api.file}}
40
+ {%- endif -%}
41
+ {%- endif -%}
42
+
43
+ {%- if api.body -%}
44
+ body:
45
+ {% if api.body.propertiesList %}{
46
+ {%- for prop in api.body.propertiesList %}
47
+ {% if prop.schema.description -%}
48
+ /** {{ prop.schema.description }} */
49
+ {% endif -%}
50
+ '{{ prop.key }}'{{ "?" if not prop.schema.required }}: {{ prop.schema.type }},
51
+ {%- endfor %}
52
+ }
53
+ {%- else -%}
54
+ {{ api.body.type }}
55
+ {%- endif -%}
56
+ {{ ";" if api.file }}
57
+ {%- endif %}
58
+
59
+ {%- if api.file -%}
60
+ {%- for file in api.file -%}
61
+ {{file.title | safe}}
62
+ {{- "?" if not api.file.required -}}
63
+ : File {{ "[]" if file.multiple }}
64
+ {{";" if not loop.last }}
65
+ {%- endfor -%}
66
+ {%- endif -%}
67
+ {{ ";" if api.body or api.hasParams or api.file }}
68
+ options?: {{ requestOptionsType }}
69
+ }
70
+ {%- endif -%}
71
+ ) {
72
+ return queryOptions({
73
+ queryFn: async ({ queryKey }) => {
74
+ return apis.{{ api.functionName }}(queryKey[1]{{ " as typeof options" if genType === "ts" }});
75
+ },
76
+ queryKey: ['{{ api.functionName }}', options],
77
+ });
78
+ }
79
+ {%- else %}
80
+ export function use{{ api.functionName | capitalizeFirst }}Mutation(options
81
+ {%- if genType === "ts" -%}
82
+ ?: {
83
+ onSuccess?: (value?: {{ api.response.type }}) => void;
84
+ onError?: (error?: DefaultError) => void;
85
+ }
86
+ {%- endif %}
87
+ ) {
88
+ const { onSuccess, onError } = options || {};
89
+
90
+ const response = useMutation({
91
+ mutationFn: apis.{{ api.functionName }},
92
+ onSuccess(data{{ (": " + api.response.type) | safe if genType === "ts" }}) {
93
+ {% if genType === "ts" %}
94
+ onSuccess?.(data);
95
+ {% else %}
96
+ onSuccess && onSuccess(data);
97
+ {% endif %}
98
+ },
99
+ onError(error) {
100
+ {% if genType === "ts" %}
101
+ onError?.(error);
102
+ {% else %}
103
+ onError && onError(error);
104
+ {% endif %}
105
+ }
106
+ })
107
+
108
+ return response;
109
+ }
110
+ {%- endif %}
111
+
112
+ {% endfor %}
@@ -1,168 +1,173 @@
1
- /* eslint-disable */
2
- // @ts-ignore
3
- import * as {{ namespace }} from './{{ interfaceFileName }}';
1
+ {% if genType === "ts" %}
2
+ /* eslint-disable */
3
+ // @ts-ignore
4
+ {% endif -%}
4
5
  {{ requestImportStatement }}
6
+ {% if genType === "ts" %}
7
+ import * as {{ namespace }} from './{{ interfaceFileName }}';
8
+ {% endif %}
5
9
 
6
10
  {% for api in list -%}
7
- /** {{ api.desc if api.desc else '此处后端没有提供注释' }} {{ api.method | upper }} {{ api.pathInComment | safe }}{{ ' ' if api.apifoxRunLink else '' }}{{ api.apifoxRunLink | safe }} */
8
- export async function {{ api.functionName }}(
9
- {%- if api.params and api.hasParams %}
10
- // 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
11
- params
12
- {%- if genType === "ts" -%}
13
- : {{namespace}}.{{api.typeName}}
14
- {# header 入参 -#}
15
- {% if api.params.header -%}
16
- & { // header
17
- {% for param in api.params.header -%}
18
- {% if param.description -%}
19
- /** {{ param.description }} */
20
- {% endif -%}
21
- '{{ param.name }}'
22
- {{- "?" if not param.required }}
23
- {{- (": " + param.type + ";") | safe }}
24
- {% endfor -%}
25
- }
11
+ /** {{ api.desc if api.desc else '此处后端没有提供注释' }} {{ api.method | upper }} {{ api.pathInComment | safe }}{{ ' ' if api.apifoxRunLink else '' }}{{ api.apifoxRunLink }} */
12
+ export async function {{ api.functionName }}({
13
+ {%- if api.params and api.hasParams %}
14
+ params
15
+ {%- if api.hasParams -%}
16
+ {{ "," if api.body or api.file }}
17
+ {%- endif -%}
26
18
  {%- endif -%}
27
- {%- endif -%}
28
- {%- if api.hasParams -%}
29
- {{ "," if api.body or api.file}}
30
- {%- endif -%}
31
- {%- endif -%}
32
-
33
-
34
-
35
- {%- if api.body -%}
36
- body
37
- {%- if genType === "ts" -%}
38
-
39
- : {% if api.body.propertiesList %}{
40
- {%- for prop in api.body.propertiesList %}
41
- {% if prop.schema.description -%}
42
- /** {{ prop.schema.description }} */
43
- {% endif -%}
44
- '{{ prop.key }}'{{ "?" if not prop.schema.required }}: {{ prop.schema.type }},
45
- {%- endfor %}
19
+ {%- if api.body -%}
20
+ body
21
+ {{ "," if api.file }}
22
+ {%- endif %}
23
+ {%- if api.file -%}
24
+ {%- for file in api.file -%}
25
+ {{ file.title | safe }}
26
+ {{ "," if not loop.last }}
27
+ {%- endfor -%}
28
+ {%- endif -%}
29
+ {{ "," if api.body or api.hasParams or api.file }}
30
+ options
46
31
  }
47
- {%- else -%}
48
- {{ api.body.type }}
49
- {%- endif -%}
50
-
51
- {%- endif -%}
52
- {{ "," if api.file }}
53
- {%- endif %}
54
-
55
-
56
-
57
- {%- if api.file -%}
58
- {%- for file in api.file -%}
59
- {{file.title | safe}}
60
- {%- if genType === "ts" -%}
61
- {{- "?" if not api.file.required -}}
62
- : File {{ "[]" if file.multiple }}
63
- {%- endif -%}
64
- {{"," if not loop.last }}
65
- {%- endfor -%}
66
- {%- endif -%}
67
-
68
-
69
-
70
- {{ "," if api.body or api.hasParams or api.file }}
71
- options {{ ("?: " + requestOptionsType) if genType === "ts" }}
72
- ) {
73
- {% if api.params and api.params.path -%}
74
- const { {% for param in api.params.path %}'{{ param.name }}': {{ param.alias }}, {% endfor %}
75
- {% if api.params.path -%}
76
- ...queryParams
77
- {% endif -%}
78
- } = params;
79
- {% endif -%}
80
-
81
-
82
-
83
- {% if api.hasFormData -%}
84
- const formData = new FormData();
32
+ {%- if genType === "ts" -%}
33
+ : {
34
+ {%- if api.params and api.hasParams %}
35
+ // 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
36
+ params: {{ namespace }}.{{ api.typeName }}
37
+ {# header 入参 -#}
38
+ {% if api.params.header -%}
39
+ & { // header
40
+ {% for param in api.params.header -%}
41
+ {% if param.description -%}
42
+ /** {{ param.description }} */
43
+ {% endif -%}
44
+ '{{ param.name }}'
45
+ {{- "?" if not param.required }}
46
+ {{- (": " + param.type + ";") | safe }}
47
+ {% endfor -%}
48
+ }
49
+ {%- endif -%}
50
+ {%- if api.hasParams -%}
51
+ {{ ";" if api.body or api.file }}
52
+ {%- endif -%}
53
+ {%- endif -%}
54
+
55
+ {%- if api.body -%}
56
+ body:
57
+ {% if api.body.propertiesList %}
58
+ {
59
+ {%- for prop in api.body.propertiesList %}
60
+ {% if prop.schema.description -%}
61
+ /** {{ prop.schema.description }} */
62
+ {% endif -%}
63
+ '{{ prop.key }}'{{ "?" if not prop.schema.required }}: {{ prop.schema.type }},
64
+ {%- endfor %}
65
+ }
66
+ {%- else -%}
67
+ {{ api.body.type }}
68
+ {%- endif -%}
69
+ {{ ";" if api.file }}
70
+ {%- endif %}
85
71
 
86
- {% if api.file -%}
87
- {% for file in api.file %}
88
- if({{file.title | safe}}){
89
- {% if file.multiple %}
90
- {{file.title | safe}}.forEach(f => formData.append('{{file.title | safe}}', f || ''));
91
- {% else %}
92
- formData.append('{{file.title | safe}}', {{file.title | safe}})
93
- {% endif %}
94
- }
95
- {% endfor %}
72
+ {%- if api.file -%}
73
+ {%- for file in api.file -%}
74
+ {{ file.title | safe }}
75
+ {{- "?" if not api.file.required -}}
76
+ : File {{ "[]" if file.multiple }}
77
+ {{ ";" if not loop.last }}
78
+ {%- endfor -%}
79
+ {%- endif -%}
80
+ {{ ";" if api.body or api.hasParams or api.file }}
81
+ options?: {{ requestOptionsType }}
82
+ }
96
83
  {%- endif -%}
97
-
98
- {% if api.body %}
99
- Object.keys(body).forEach(ele => {
100
- {% if genType === "ts" %}
101
- const item = (body as { [key: string]: any })[ele];
102
- {% else %}
103
- const item = body[ele];
84
+ )
85
+ {
86
+ {% if api.params and api.params.path %}
87
+ const { {% for param in api.params.path %}'{{ param.name }}': {{ param.alias }}, {% endfor %}
88
+ {% if api.params.path -%}
89
+ ...queryParams
90
+ {% endif -%}
91
+ } = params;
104
92
  {% endif %}
105
- if (item !== undefined && item !== null) {
106
- {% if genType === "ts" %}
107
- if (typeof item === 'object' && !(item instanceof File)) {
108
- if (item instanceof Array) {
109
- item.forEach((f) => formData.append(ele, f || ''));
110
- } else {
111
- formData.append(ele, JSON.stringify(item));
112
- }
113
- } else {
114
- formData.append(ele, item);
115
- }
116
- {% else %}
117
- formData.append(ele, typeof item === 'object' ? JSON.stringify(item) : item);
93
+ {%- if api.hasFormData -%}
94
+ const formData = new FormData();
95
+
96
+ {% if api.file -%}
97
+ {% for file in api.file %}
98
+ if({{ file.title | safe }}) {
99
+ {% if file.multiple %}
100
+ {{ file.title | safe }}.forEach(f => formData.append('{{ file.title | safe }}', f || ''));
101
+ {% else %}
102
+ formData.append('{{ file.title | safe }}', {{ file.title | safe }})
103
+ {% endif %}
104
+ }
105
+ {% endfor %}
106
+ {%- endif -%}
107
+
108
+ {% if api.body %}
109
+ Object.keys(body).forEach(ele => {
110
+ {% if genType === "ts" %}
111
+ const item = (body as { [key: string]: any })[ele];
112
+ {% else %}
113
+ const item = body[ele];
114
+ {% endif %}
115
+ if (item !== undefined && item !== null) {
116
+ {% if genType === "ts" %}
117
+ if (typeof item === 'object' && !(item instanceof File)) {
118
+ if (item instanceof Array) {
119
+ item.forEach((f) => formData.append(ele, f || ''));
120
+ } else {
121
+ formData.append(ele, JSON.stringify(item));
122
+ }
123
+ } else {
124
+ formData.append(ele, item);
125
+ }
126
+ {% else %}
127
+ formData.append(ele, typeof item === 'object' ? JSON.stringify(item) : item);
128
+ {% endif %}
129
+ }
130
+ });
118
131
  {% endif %}
119
- }
120
- });
121
- {% endif %}
122
- {% endif -%}
123
-
124
-
125
-
126
- {% if api.hasPathVariables or api.hasApiPrefix -%}
127
- return request{{ ("<" + api.response.type + ">") | safe if genType === "ts" }}(`{{ api.path | safe }}`, {
128
- {% else -%}
129
- return request{{ ("<" + api.response.type + ">") | safe if genType === "ts" }}('{{ api.path }}', {
130
- {% endif -%}
131
- method: '{{ api.method | upper }}',
132
+ {% endif %}
132
133
 
133
- {%- if api.hasHeader and api.body.mediaType %}
134
- headers: {
135
- {%- if api.body.mediaType %}
136
- 'Content-Type': '{{ api.body.mediaType | safe }}',
134
+ {% if api.hasPathVariables or api.hasApiPrefix -%}
135
+ return request{{ ("<" + api.response.type + ">") | safe if genType === "ts" }}(`{{ api.path | safe }}`, {
136
+ {% else -%}
137
+ return request{{ ("<" + api.response.type + ">") | safe if genType === "ts" }}('{{ api.path }}', {
138
+ {% endif -%}
139
+ method: '{{ api.method | upper }}',
140
+ {%- if api.hasHeader and api.body.mediaType %}
141
+ headers: {
142
+ {%- if api.body.mediaType %}
143
+ 'Content-Type': '{{ api.body.mediaType | safe }}',
144
+ {%- endif %}
145
+ },
137
146
  {%- endif %}
138
- },
139
- {%- endif %}
140
-
141
- {%- if api.params and api.hasParams %}
142
- params: {
143
- {%- for query in api.params.query %}
144
- {% if query.schema.default -%}
145
- // {{query.name | safe}} has a default value: {{ query.schema.default | safe }}
146
- '{{query.name | safe}}': '{{query.schema.default | safe}}',
147
- {%- endif -%}
148
- {%- endfor -%}
149
- ...{{ 'queryParams' if api.params and api.params.path else 'params' }},
150
- {%- for query in api.params.query %}
151
- {%- if query.isComplexType %}
152
- '{{query.name | safe}}': undefined,
153
- ...{{ 'queryParams' if api.params and api.params.path else 'params' }}['{{query.name | safe}}'],
154
- {%- endif %}
155
- {%- endfor -%}
156
- },
157
- {%- endif %}
158
-
159
- {%- if api.hasFormData %}
160
- data: formData,
161
- {%- elseif api.body %}
162
- data: body,
163
- {%- endif %}
164
- ...(options || {{api.options | dump}}),
165
- });
166
- }
147
+ {%- if api.params and api.hasParams %}
148
+ params: {
149
+ {%- for query in api.params.query %}
150
+ {% if query.schema.default -%}
151
+ // {{ query.name | safe }} has a default value: {{ query.schema.default | safe }}
152
+ '{{ query.name | safe }}': '{{query.schema.default | safe}}',
153
+ {%- endif -%}
154
+ {%- endfor -%}
155
+ ...{{ 'queryParams' if api.params and api.params.path else 'params' }},
156
+ {%- for query in api.params.query %}
157
+ {%- if query.isComplexType %}
158
+ '{{ query.name | safe }}': undefined,
159
+ ...{{ 'queryParams' if api.params and api.params.path else 'params' }}['{{ query.name | safe }}'],
160
+ {%- endif %}
161
+ {%- endfor -%}
162
+ },
163
+ {%- endif %}
164
+ {%- if api.hasFormData %}
165
+ data: formData,
166
+ {%- elseif api.body %}
167
+ data: body,
168
+ {%- endif %}
169
+ ...(options || {{ api.options | dump }}),
170
+ });
171
+ }
167
172
 
168
173
  {% endfor -%}
@@ -1,15 +1,21 @@
1
- /* eslint-disable */
2
- // @ts-ignore
3
- export * from './{{ interfaceFileName }}';
4
- {%- if isDisplayEnumLabel %}
5
- export * from './{{ displayEnumLabelFileName }}';
6
- {%- endif %}
7
- {%- if isDisplayTypeLabel %}
8
- export * from './{{ displayTypeLabelFileName }}';
9
- {%- endif %}
1
+ {% if genType === "ts" %}
2
+ /* eslint-disable */
3
+ // @ts-ignore
4
+ export * from './{{ interfaceFileName }}';
5
+ {%- if isDisplayEnumLabel %}
6
+ export * from './{{ displayEnumLabelFileName }}';
7
+ {% endif -%}
8
+ {%- if isDisplayTypeLabel %}
9
+ export * from './{{ displayTypeLabelFileName }}';
10
+ {% endif -%}
11
+ {% endif %}
10
12
  {%- if isGenJsonSchemas %}
11
- export * from './{{ schemaFileName }}';
13
+ export * from './{{ schemaFileName }}';
12
14
  {%- endif %}
15
+
13
16
  {% for api in list -%}
14
- export * from './{{ api.fileName }}';
15
- {% endfor -%}
17
+ export * from './{{ api.fileName }}';
18
+ {%- if isGenReactQuery -%}
19
+ export * from './{{ api.fileName }}.{{ reactQueryFileName }}';
20
+ {%- endif -%}
21
+ {%- endfor -%}