swagger-to-axios 1.0.5 → 1.0.6

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/lib/index.d.ts CHANGED
@@ -1,49 +1,3 @@
1
- /** swagger 文档配置项 */
2
- interface SwaggerDocument {
3
- /** swagger 文档地址 */
4
- url: string;
5
- /** 是否使用本地 swagger 文档,默认为 false。
6
- * 如果该项为 true,则 url 应填本地地址,建议填写完整路径 */
7
- localFile?: boolean;
8
- /** swagger 文档文件类型,yaml 还是 json ,默认为 yaml */
9
- urlType?: string;
10
- /** 生成文件后该文档的文件夹名称,默认会使用随机数作为文件夹名称 */
11
- name?: string;
12
- }
13
- /** 生成文件配置项 */
14
- interface Config {
15
- /** 在生成文件时,每个函数是否携带 baseURL 属性,默认为 true。 */
16
- includeBaseURL?: boolean;
17
- /**
18
- * 如果 includeBaseURL 为 false,则不需要配置该项。
19
- * cli类型,是 Vite 还是 VueCli ,默认 VueCli。
20
- */
21
- cliType?: string;
22
- /**
23
- * 如果 includeBaseURL 为 false,则不需要配置该项。
24
- * host 的配置名称,不填时会根据 cliType 属性自动设为 VUE_APP_HOST 或者 VITE_APP_HOST。
25
- * 如果 swagger 的 host 填写了正确的地址,你也可以完全不配置该项,生成的代码会使用三目运算符,并将非的表达式设置为 swagger 的 host。
26
- */
27
- envHostName?: string;
28
- /**
29
- * 如果 includeBaseURL 为 false,则不需要配置该项。
30
- * 网络协议的配置名称,不填时会根据 cliType 属性自动设为 VUE_APP_PROTOCOL 或者 VITE_APP_PROTOCOL。
31
- * VUE_APP_PROTOCOL / VITE_APP_PROTOCOL 的值应该为 'https' 或者 'http'。
32
- */
33
- envProtocolName?: string;
34
- /**
35
- * 如果 includeBaseURL 为 false,则不需要配置该项。
36
- * 是否使用 https,默认为 false。 */
37
- https?: boolean;
38
- /** 生成的文件所在目录,默认为 ./apis。 */
39
- outputFolder?: string;
40
- /** 需要引用的 axios 函数地址,默认为 window.axios。 */
41
- improtAxiosPath?: string;
42
- /** 是否生成 ts 文件,默认为 false。 */
43
- typeScript?: boolean;
44
- /** url是否放置于 options 中,默认为 true。如为 false,则将放在第一个参数中。 */
45
- urlInOptions?: boolean;
46
- }
47
1
  /** 创建所有 API 文件
48
2
  * @param {SwaggerDocument[]} swaggerList - swagger 文档列表
49
3
  * @param {Config} config - 配置项
package/lib/index.js CHANGED
@@ -1,8 +1,6 @@
1
1
  import fs from 'fs';
2
2
  const fsPromises = fs.promises;
3
- import axios from 'axios';
4
- import YAML from 'js-yaml';
5
- import { writeFile, urlToName, urlToLinkParams } from './utils/index.js';
3
+ import { writeFile, urlToName, urlToLinkParams, getFolderList, } from './utils/index.js';
6
4
  /** 创建所有 API 文件
7
5
  * @param {SwaggerDocument[]} swaggerList - swagger 文档列表
8
6
  * @param {Config} config - 配置项
@@ -12,93 +10,14 @@ const createApiFiles = async (swaggerList = [], config = {}) => {
12
10
  const { includeBaseURL = true, cliType = 'VueCli', envHostName = cliType === 'VueCli' ? 'VUE_APP_HOST' : 'VITE_APP_HOST', envProtocolName = cliType === 'VueCli' ? 'VUE_APP_PROTOCOL' : 'VITE_APP_PROTOCOL', https = false, outputFolder = './apis', improtAxiosPath, typeScript = false, urlInOptions = true, } = config;
13
11
  const swagger = {
14
12
  path: outputFolder,
15
- list: [],
13
+ folderList: await getFolderList(swaggerList, cliType),
16
14
  };
17
- // 循环 swagger 文档列表
18
- for (const element of swaggerList) {
19
- const { url, localFile = false, urlType = 'yaml', name = Math.random().toString() } = element;
20
- let json;
21
- if (localFile) {
22
- const fileString = await fsPromises.readFile(url, { encoding: 'utf8' }).catch((error) => console.error(error));
23
- if (!fileString) {
24
- console.log(`${url}下的文件没有内容,已跳过`);
25
- continue;
26
- }
27
- json = urlType === 'json' ? fileString : YAML.load(fileString);
28
- }
29
- else {
30
- // 获取文档并转换成 json
31
- json = await axios
32
- .get(url)
33
- .then((res) => {
34
- if (urlType && urlType === 'json') {
35
- return res.data;
36
- }
37
- const jsonData = YAML.load(res.data);
38
- return jsonData;
39
- })
40
- .catch((error) => console.error(error));
41
- }
42
- // 创建文件夹对象
43
- const folderObj = {
44
- name,
45
- cliType,
46
- baseURL: json.basePath,
47
- host: json.host,
48
- list: [],
49
- };
50
- // 获取文档的 tags,并插入文件夹对象的 list 字段中
51
- if (json === null || json === void 0 ? void 0 : json.tags) {
52
- for (const tag of json.tags) {
53
- folderObj.list.push({
54
- name: tag.name,
55
- comment: tag.description,
56
- list: [],
57
- });
58
- }
59
- }
60
- // 循环文档的 paths,取出 api 地址、类型、描述并放入 tag list 中
61
- for (const path in json.paths) {
62
- if (json.paths.hasOwnProperty(path)) {
63
- const methods = json.paths[path];
64
- for (const name in methods) {
65
- if (methods.hasOwnProperty(name)) {
66
- const method = methods[name];
67
- let tag = folderObj.list.find((ele) => ele.name === method.tags[0]);
68
- if (!tag) {
69
- tag = {
70
- name: method.tags[0],
71
- comment: '',
72
- list: [],
73
- };
74
- folderObj.list.push(tag);
75
- }
76
- let api = tag.list.find((ele) => ele.url === path);
77
- if (!api) {
78
- api = {
79
- url: path,
80
- method: [],
81
- comment: [],
82
- };
83
- tag.list.push(api);
84
- }
85
- api.method.push(name);
86
- api.comment.push({
87
- summary: method.summary,
88
- description: method.description,
89
- });
90
- }
91
- }
92
- }
93
- }
94
- // 将文件夹对象放入 swagger 对象的文件夹 list 中
95
- swagger.list.push(folderObj);
96
- }
97
15
  // 生成文件夹
98
16
  await fsPromises.mkdir(`${swagger.path}`, { recursive: true });
99
- for (const folder of swagger.list) {
17
+ for (const folder of swagger.folderList) {
100
18
  await fsPromises.mkdir(`${swagger.path}/${folder.name}`, { recursive: true });
101
- for (const file of folder.list) {
19
+ let typings = 'declare namespace API {';
20
+ for (const file of folder.tagList) {
102
21
  let fileContent = '';
103
22
  // 如果包含注释,则在文件顶部添加注释
104
23
  if (file.comment) {
@@ -109,7 +28,12 @@ const createApiFiles = async (swaggerList = [], config = {}) => {
109
28
  fileContent += `import request from '${improtAxiosPath}';
110
29
  `;
111
30
  }
112
- fileContent += `const basePath = '${folder.baseURL}';
31
+ if (typeScript) {
32
+ fileContent += `import "./typings";
33
+ `;
34
+ }
35
+ fileContent += `
36
+ const basePath = '${folder.baseURL}';
113
37
  `;
114
38
  if (includeBaseURL) {
115
39
  const cliTypePrefix = folder.cliType === 'Vite' ? `import.meta.env.` : `process.env.`;
@@ -126,53 +50,81 @@ const createApiFiles = async (swaggerList = [], config = {}) => {
126
50
  fileContent += `const protocol = \`\${${protocolCliTypeString} ? ${protocolCliTypeString} : 'http${https ? 's' : ''}'}\`;
127
51
  `;
128
52
  }
129
- const apiList = file.list;
53
+ const apiList = file.apiList;
130
54
  for (const api of apiList) {
131
- for (let l = 0; l < api.method.length; l++) {
132
- const method = api.method[l];
133
- const { summary, description } = api.comment[l];
134
- if (summary) {
135
- fileContent += `
55
+ const method = api.method;
56
+ const functionName = method.toLowerCase() + urlToName(api.url);
57
+ if (api?.response) {
58
+ typings += `
59
+ type ${functionName}Response = ${api.response.data}`;
60
+ }
61
+ const { summary, description } = api.comment;
62
+ if (summary) {
63
+ fileContent += `
136
64
  // ${summary}`;
137
- }
138
- if (description) {
139
- fileContent += `
140
- // ${description}`;
141
- }
65
+ }
66
+ if (description) {
142
67
  fileContent += `
68
+ // ${description}`;
69
+ }
70
+ fileContent += `
143
71
  `;
144
- fileContent += `export function ${method.toLowerCase() + urlToName(api.url)}(`;
145
- fileContent += method.toUpperCase() === 'GET' ? 'params' : 'data';
146
- fileContent += `${typeScript ? '?: any' : ''}, options${typeScript ? '?: { [key: string]: any }' : ''}) {
72
+ fileContent += `export function ${functionName}(`;
73
+ fileContent += method.toUpperCase() === 'GET' ? 'params' : 'data';
74
+ fileContent += `${typeScript ? '?: any' : ''}, options${typeScript ? '?: { [key: string]: any }' : ''}) {
147
75
  `;
148
- fileContent += `return ${improtAxiosPath ? `request${typeScript ? '<any>' : ''}` : 'window.axios'}(`;
149
- if (!urlInOptions) {
150
- fileContent += `\`\${basePath}${urlToLinkParams(api.url, method)}\`, `;
151
- }
152
- fileContent += `{
76
+ fileContent += `return ${improtAxiosPath ? `request` : 'window.axios'}${typeScript ? `<API.${functionName}Response>` : ''}(`;
77
+ if (!urlInOptions) {
78
+ fileContent += `\`\${basePath}${urlToLinkParams(api.url, method)}\`, `;
79
+ }
80
+ fileContent += `{
153
81
  `;
154
- if (urlInOptions) {
155
- fileContent += `url: \`\${basePath}${urlToLinkParams(api.url, method)}\`,
82
+ if (urlInOptions) {
83
+ fileContent += `url: \`\${basePath}${urlToLinkParams(api.url, method)}\`,
156
84
  `;
157
- }
158
- if (includeBaseURL) {
159
- fileContent += `baseURL: \`\${protocol}://\${host}\`,
85
+ }
86
+ if (includeBaseURL) {
87
+ fileContent += `baseURL: \`\${protocol}://\${host}\`,
160
88
  `;
161
- }
162
- fileContent += `method: '${method}',
89
+ }
90
+ fileContent += `method: '${method}',
163
91
  ${method.toLowerCase() === 'get' ? 'params' : 'data'},
164
92
  ...(options || {}),
165
93
  });
166
94
  }
167
95
  `;
168
- }
169
96
  }
170
97
  await writeFile(`${swagger.path}${folder.name ? '/' + folder.name : ''}/${file.name}.${typeScript ? 'ts' : 'js'}`, fileContent).catch((err) => console.log(err));
171
98
  }
99
+ typings += `
100
+ }`;
101
+ if (typeScript) {
102
+ await writeFile(`${swagger.path}${folder.name ? '/' + folder.name : ''}/typings.d.ts`, typings).catch((err) => console.log(err));
103
+ }
172
104
  }
173
105
  }
174
106
  catch (error) {
175
107
  console.error('错误:', error);
176
108
  }
177
109
  };
110
+ // /** 生成 mock 文件
111
+ // * @param {SwaggerDocument[]} swaggerList - swagger 文档列表
112
+ // * @param {MockConfig} mockConfig - 配置项
113
+ // */
114
+ // const createMockFiles = async (
115
+ // swaggerList: SwaggerDocument[] = [],
116
+ // { mockType = 'vite-plugin-mock', outputFolder = './mocks' }: MockConfig = {},
117
+ // ) => {
118
+ // const swagger: Swagger = {
119
+ // path: outputFolder,
120
+ // folderList: await getFolderList(swaggerList, ''),
121
+ // };
122
+ // switch (mockType) {
123
+ // case 'vite-plugin-mock':
124
+ // break;
125
+ // default:
126
+ // break;
127
+ // }
128
+ // };
178
129
  export default createApiFiles;
130
+ // export { createMockFiles };
package/lib/typeing.d.ts CHANGED
@@ -1,20 +1,141 @@
1
+ /** swagger 文档配置项 */
2
+ declare interface SwaggerDocument {
3
+ /** swagger 文档地址 */
4
+ url: string;
5
+ /**
6
+ * 是否使用本地 swagger 文档。
7
+ * 默认值:false。
8
+ * 注:
9
+ * 1、如果该项为 true,则 url 应填本地地址,建议填写完整路径。
10
+ * */
11
+ localFile?: boolean;
12
+ /**
13
+ * swagger 文档文件类型。
14
+ * 默认值:yaml。
15
+ * */
16
+ urlType?: 'yaml' | 'json';
17
+ /** 生成文件后该文档的文件夹名称。
18
+ * 默认值:字符串随机数。
19
+ * */
20
+ name?: string;
21
+ }
22
+ /** 生成文件配置项 */
23
+ declare interface Config {
24
+ /**
25
+ * 生成文件时,每个函数是否携带 baseURL 属性。
26
+ * 默认值:true。
27
+ * */
28
+ includeBaseURL?: boolean;
29
+ /**
30
+ * cli类型。
31
+ * 默认值:VueCli。
32
+ * 注:
33
+ * 1、如果 includeBaseURL 为 false,则不需要配置该项。
34
+ */
35
+ cliType?: 'Vite' | 'VueCli';
36
+ /**
37
+ * host 的配置名称。
38
+ * 默认值:VUE_APP_HOST | VITE_APP_HOST(根据 cliType 属性)。
39
+ * 注:
40
+ * 1、如果 includeBaseURL 为 false,则不需要配置该项。
41
+ * 2、如果 swagger 的 host 填写了正确的地址,你也可以完全不配置该项,生成的代码会使用三目运算符,并将非的表达式设置为 swagger 的 host。
42
+ */
43
+ envHostName?: string;
44
+ /**
45
+ * 网络协议的配置名称。
46
+ * 默认值:VUE_APP_PROTOCOL | VITE_APP_PROTOCOL(根据 cliType 属性)。
47
+ * 注:
48
+ * 1、如果 includeBaseURL 为 false,则不需要配置该项。
49
+ * 2、VUE_APP_PROTOCOL / VITE_APP_PROTOCOL 的值应该为 'https' 或者 'http'。
50
+ */
51
+ envProtocolName?: string;
52
+ /**
53
+ * 是否使用 https。
54
+ * 默认值:false。
55
+ * 注:
56
+ * 1、如果 includeBaseURL 为 false,则不需要配置该项。
57
+ * */
58
+ https?: boolean;
59
+ /**
60
+ * 生成的文件所在目录。
61
+ * 默认值:./apis。
62
+ * */
63
+ outputFolder?: string;
64
+ /**
65
+ * 需要引用的 axios 函数地址。
66
+ * 默认值:window.axios。
67
+ * */
68
+ improtAxiosPath?: string;
69
+ /**
70
+ * 是否生成 ts 文件。
71
+ * 默认值:false。
72
+ * */
73
+ typeScript?: boolean;
74
+ /**
75
+ * url是否放置于 options 中。
76
+ * 默认值:true。
77
+ * 注:
78
+ * 1、如为 false,则将放在第一个参数中。
79
+ * */
80
+ urlInOptions?: boolean;
81
+ }
82
+ declare interface Swagger {
83
+ path: string;
84
+ folderList: Folder[];
85
+ }
86
+ declare interface Folder {
87
+ name: string;
88
+ cliType: string;
89
+ baseURL: string;
90
+ host: string;
91
+ tagList: Tag[];
92
+ }
93
+ declare interface Tag {
94
+ name: string;
95
+ comment: string;
96
+ apiList: Api[];
97
+ }
1
98
  declare interface Api {
2
99
  url: string;
3
- method: string[];
100
+ method: string;
4
101
  comment: {
5
102
  summary: string;
6
103
  description: string;
7
- }[];
104
+ };
105
+ response?: any;
8
106
  }
9
- declare interface Tag {
107
+ /** 生成 mock 文件配置项 */
108
+ declare interface MockConfig {
109
+ /**
110
+ * 使用的 mock 服务器类型。
111
+ * 默认值:vite-plugin-mock。
112
+ */
113
+ mockType?: 'vite-plugin-mock' | 'umi';
114
+ /**
115
+ * 生成的文件所在目录。
116
+ * 默认值:./mocks。
117
+ * */
118
+ outputFolder?: string;
119
+ }
120
+ declare interface MockSwagger {
121
+ path: string;
122
+ folderList: MockFolder[];
123
+ }
124
+ declare interface MockFolder {
10
125
  name: string;
11
- comment: string;
12
- list: Api[];
126
+ tagList: MockTag[];
13
127
  }
14
- declare interface Folder {
128
+ declare interface MockTag {
15
129
  name: string;
16
- cliType: string;
17
- baseURL: string;
18
- host: string;
19
- list: Tag[];
130
+ comment: string;
131
+ apiList: MockApi[];
132
+ }
133
+ declare interface MockApi {
134
+ url: string;
135
+ method: string;
136
+ comment: {
137
+ summary: string;
138
+ description: string;
139
+ };
140
+ response?: any;
20
141
  }
@@ -1,9 +1,29 @@
1
+ import { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
2
+ /** 获取 swagger 文档 */
3
+ export declare const getSwaggerJson: ({ url, }: {
4
+ url: string;
5
+ }) => Promise<OpenAPIV3.Document | OpenAPIV3_1.Document | undefined>;
6
+ /**
7
+
8
+ * @param {SwaggerDocument[]} swaggerList - swagger 文档列表
9
+ * @param {Config['cliType']} cliType - cli类型
10
+ * @returns {Promise<Folder[]>} 文件夹数组
11
+ */
12
+ export declare const getFolderList: (swaggerList: SwaggerDocument[], cliType: string) => Promise<Folder[]>;
13
+ /** 重组 tag 数组 */
14
+ export declare const getTagList: (tags?: OpenAPIV3.TagObject[], paths?: OpenAPIV3.PathsObject) => Tag[];
15
+ /** 重组 response */
16
+ export declare const getResponse: (response?: OpenAPIV3.ResponseObject) => {
17
+ description: string;
18
+ data?: any;
19
+ } | undefined;
20
+ export declare const openapiTypeToTypeScript: (schemaObject: OpenAPIV3.SchemaObject) => string;
1
21
  /**
2
22
  * 写文件
3
23
  * @param {string} pathname
4
24
  * @param {string} dataBuffer
5
25
  */
6
- export declare const writeFile: (pathname: string, dataBuffer: string) => Promise<unknown>;
26
+ export declare const writeFile: (pathname: string, dataBuffer: string) => Promise<boolean>;
7
27
  /** 首字母大写 */
8
28
  export declare const upperFirstCase: (str: string) => string;
9
29
  /** 链接变成名称 */
@@ -1,22 +1,224 @@
1
- import fs from 'fs';
1
+ import fsPromises from 'fs/promises';
2
+ import SwaggerParser from '@apidevtools/swagger-parser';
3
+ import { convertObj } from 'swagger2openapi';
4
+ import lodash from 'lodash';
5
+ const mergeWith = lodash.mergeWith;
6
+ /** 获取 swagger 文档 */
7
+ export const getSwaggerJson = async ({ url, }) => {
8
+ try {
9
+ const swagger = await SwaggerParser.dereference(url);
10
+ if (swagger === undefined)
11
+ return undefined;
12
+ expandAllOf(swagger?.paths ?? {});
13
+ if ('definitions' in swagger) {
14
+ expandAllOf(swagger?.definitions ?? {});
15
+ }
16
+ if ('swagger' in swagger) {
17
+ const result = await convertObj(swagger, {});
18
+ return result.openapi;
19
+ }
20
+ return swagger;
21
+ }
22
+ catch (error) {
23
+ return undefined;
24
+ }
25
+ };
2
26
  /**
3
- * 写文件
4
- * @param {string} pathname
5
- * @param {string} dataBuffer
27
+
28
+ * @param {SwaggerDocument[]} swaggerList - swagger 文档列表
29
+ * @param {Config['cliType']} cliType - cli类型
30
+ * @returns {Promise<Folder[]>} 文件夹数组
6
31
  */
7
- export const writeFile = (pathname, dataBuffer) => {
8
- return new Promise((resolve, reject) => {
9
- fs.writeFile(pathname, dataBuffer, (err) => {
10
- if (err) {
11
- reject(err);
32
+ export const getFolderList = async (swaggerList, cliType) => {
33
+ const result = [];
34
+ for (const element of swaggerList) {
35
+ const { url, name = Math.random().toString() } = element;
36
+ const json = await getSwaggerJson({ url });
37
+ if (json === undefined)
38
+ continue;
39
+ const { tags, paths, servers } = json;
40
+ const basePath = servers?.[0].url.replace(/.+:\/\/.+\//, '/') ?? '';
41
+ // 三次替换,分别匹配 http://api.example.com/api , /api , //api.example.com,使结果保持为 api.example.com
42
+ const host = servers?.[0].url
43
+ .replace(/.+:\/\/(.+)\/.+/, '$1')
44
+ .replace(/^\/[\w|\d]+/, '')
45
+ .replace(/^\/\//, '') ?? '';
46
+ result.push({
47
+ name,
48
+ cliType,
49
+ baseURL: basePath,
50
+ host: host,
51
+ tagList: getTagList(tags, paths),
52
+ });
53
+ }
54
+ return result;
55
+ };
56
+ /** 重组 tag 数组 */
57
+ export const getTagList = (tags = [], paths) => {
58
+ const tagList = [];
59
+ // 获取文档的 tags,并插入文件夹对象的 list 字段中
60
+ for (const tag of tags) {
61
+ tagList.push({
62
+ name: tag.name,
63
+ comment: tag?.description ?? '',
64
+ apiList: [],
65
+ });
66
+ }
67
+ // 循环文档的 paths,取出 api 地址、类型、描述并放入 tag list 中
68
+ for (const path in paths) {
69
+ if (paths.hasOwnProperty(path)) {
70
+ const methods = paths[path];
71
+ if (!methods) {
72
+ continue;
12
73
  }
13
- else {
14
- // console.log(`${pathname.replace(/(.+\/)/, '')} 保存成功!`);
15
- resolve(true);
74
+ for (const name in methods) {
75
+ if (methods.hasOwnProperty(name)) {
76
+ const method = methods[name];
77
+ const methodTag = method?.tags?.[0] ?? '';
78
+ let tag = tagList.find((ele) => ele.name === methodTag);
79
+ if (!tag) {
80
+ tag = {
81
+ name: methodTag,
82
+ comment: '',
83
+ apiList: [],
84
+ };
85
+ tagList.push(tag);
86
+ }
87
+ tag.apiList.push({
88
+ url: path,
89
+ method: name,
90
+ comment: {
91
+ summary: method?.summary ?? '',
92
+ description: method?.description ?? '',
93
+ },
94
+ response: getResponse(method?.responses?.[200]),
95
+ });
96
+ }
97
+ }
98
+ }
99
+ }
100
+ return tagList;
101
+ };
102
+ /** 重组 response */
103
+ export const getResponse = (response) => {
104
+ if (response === undefined)
105
+ return response;
106
+ const result = {
107
+ description: response.description,
108
+ data: {},
109
+ };
110
+ result.data = openapiTypeToTypeScript(response?.content?.['application/json']?.schema ?? {});
111
+ console.log('result.data', result.data);
112
+ return result;
113
+ };
114
+ export const openapiTypeToTypeScript = (schemaObject) => {
115
+ const { type = '' } = schemaObject;
116
+ const numberEnum = [
117
+ 'int64',
118
+ 'integer',
119
+ 'long',
120
+ 'float',
121
+ 'double',
122
+ 'number',
123
+ 'int',
124
+ 'float',
125
+ 'double',
126
+ 'int32',
127
+ 'int64',
128
+ ];
129
+ const dateEnum = ['Date', 'date', 'dateTime', 'date-time', 'datetime'];
130
+ const stringEnum = ['string', 'email', 'password', 'url', 'byte', 'binary'];
131
+ if (numberEnum.includes(type)) {
132
+ return 'number';
133
+ }
134
+ if (dateEnum.includes(type)) {
135
+ return 'Date';
136
+ }
137
+ if (stringEnum.includes(type)) {
138
+ return 'string';
139
+ }
140
+ if (type === 'boolean') {
141
+ return 'boolean';
142
+ }
143
+ if (type === 'array') {
144
+ let { items = {} } = schemaObject;
145
+ if ('schema' in schemaObject) {
146
+ items = schemaObject?.schema?.items;
147
+ }
148
+ if (Array.isArray(items)) {
149
+ const arrayItemType = items
150
+ .map((subType) => openapiTypeToTypeScript(subType))
151
+ .toString();
152
+ return `[${arrayItemType}]`;
153
+ }
154
+ const arrayType = openapiTypeToTypeScript(items);
155
+ return arrayType.includes(' | ') ? `(${arrayType})[]` : `${arrayType}[]`;
156
+ }
157
+ if (type === 'object' || schemaObject.properties) {
158
+ const keys = Object.keys(schemaObject.properties || {});
159
+ if (!keys?.length) {
160
+ return 'Record<string, any>';
161
+ }
162
+ return `{ ${keys
163
+ .map((key) => {
164
+ const required = 'required' in (schemaObject?.properties?.[key] || {})
165
+ ? (schemaObject?.properties?.[key] || {}).required
166
+ : false;
167
+ /**
168
+ * 将类型属性变为字符串,兼容错误格式如:
169
+ * 3d_tile(数字开头)等错误命名,
170
+ * 在后面进行格式化的时候会将正确的字符串转换为正常形式,
171
+ * 错误的继续保留字符串。
172
+ * */
173
+ return `'${key}'${required ? '' : '?'}: ${openapiTypeToTypeScript(schemaObject?.properties &&
174
+ schemaObject?.properties?.[key])}; `;
175
+ })
176
+ .join('')}}`;
177
+ }
178
+ return 'any';
179
+ };
180
+ /**
181
+ * 合并 allOf
182
+ * @param object
183
+ */
184
+ const expandAllOf = (object) => {
185
+ while (object.hasOwnProperty('allOf')) {
186
+ const allOf = object.allOf;
187
+ delete object.allOf;
188
+ const override = mergeWith({}, ...allOf, object, function (target, source) {
189
+ if (Array.isArray(target)) {
190
+ return target.concat(source).filter((v, i, a) => a.indexOf(v) === i);
191
+ }
192
+ if (typeof target === 'object') {
193
+ expandAllOf(target);
194
+ }
195
+ if (typeof source === 'object') {
196
+ expandAllOf(source);
16
197
  }
17
198
  });
199
+ Object.assign(object, override);
200
+ }
201
+ Object.keys(object).forEach((key) => {
202
+ if (typeof object[key] === 'object') {
203
+ expandAllOf(object[key]);
204
+ }
18
205
  });
19
206
  };
207
+ /**
208
+ * 写文件
209
+ * @param {string} pathname
210
+ * @param {string} dataBuffer
211
+ */
212
+ export const writeFile = async (pathname, dataBuffer) => {
213
+ try {
214
+ await fsPromises.writeFile(pathname, dataBuffer);
215
+ }
216
+ catch (error) {
217
+ console.error(error);
218
+ throw '发生异常,已停止写文件';
219
+ }
220
+ return true;
221
+ };
20
222
  /** 首字母大写 */
21
223
  export const upperFirstCase = (str) => str.charAt(0).toUpperCase() + str.slice(1);
22
224
  /** 链接变成名称 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swagger-to-axios",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "将swagger转换成axios可用的api文件",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
@@ -14,7 +14,8 @@
14
14
  "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
15
15
  "lint": "tslint -p tsconfig.json",
16
16
  "pub": "npm version patch && npm publish",
17
- "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --config ./jest.config.js"
17
+ "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --config ./jest.config.js",
18
+ "coverage": "npm test -- --coverage"
18
19
  },
19
20
  "author": "FreezeNow",
20
21
  "keywords": [
@@ -26,14 +27,18 @@
26
27
  ],
27
28
  "license": "ISC",
28
29
  "dependencies": {
29
- "axios": "^0.21.4",
30
- "js-yaml": "4.1.0"
30
+ "@apidevtools/swagger-parser": "^10.1.0",
31
+ "lodash": "^4.17.21",
32
+ "swagger2openapi": "^7.0.8"
31
33
  },
32
34
  "devDependencies": {
33
- "@types/js-yaml": "^4.0.3",
35
+ "@types/lodash": "^4.14.199",
34
36
  "@types/node": "^16.9.1",
37
+ "@types/swagger2openapi": "^7.0.1",
35
38
  "eslint-plugin-tsdoc": "^0.2.17",
36
- "jest": "^29.5.0",
39
+ "jest": "^29.6.1",
40
+ "mock-fs": "^5.2.0",
41
+ "pactum": "^3.5.1",
37
42
  "prettier": "^2.4.0",
38
43
  "tslint": "^6.1.3",
39
44
  "tslint-config-prettier": "^1.18.0"
package/lib/typeing.js DELETED
@@ -1 +0,0 @@
1
- "use strict";