openapi-ts-request 0.1.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -19
- package/dist/generator/config.d.ts +6 -1
- package/dist/generator/config.js +7 -1
- package/dist/generator/patchSchema.d.ts +2 -0
- package/dist/generator/patchSchema.js +51 -0
- package/dist/generator/serviceGenarator.d.ts +2 -1
- package/dist/generator/serviceGenarator.js +35 -6
- package/dist/generator/type.d.ts +4 -0
- package/dist/generator/util.d.ts +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.js +2 -1
- package/package.json +6 -5
- package/templates/displayTypeLabel.njk +42 -0
- package/templates/interface.njk +46 -44
- package/templates/schema.njk +8 -0
- package/templates/serviceIndex.njk +2 -0
package/README.md
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/openapi-ts-request)
|
|
5
5
|

|
|
6
6
|
|
|
7
|
-
根据 [Swagger2/OpenAPI3](https://swagger.io/blog/news/whats-new-in-openapi-3-0/) 文档生成 ts
|
|
7
|
+
根据 [Swagger2/OpenAPI3](https://swagger.io/blog/news/whats-new-in-openapi-3-0/) 文档生成 ts 类型, request client 请求代码, request mock 服务, 枚举, type 字段翻译, JSON Schemas
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
*
|
|
12
|
-
* generate TypeScript
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* support Swagger2.0/OpenAPI 3.0,3.1 specification
|
|
12
|
+
* generate TypeScript interface, reuquest client, request mock service, enum, type field label, JSON Schemas
|
|
13
|
+
* support custom request function, Fetch、Axios、Uniapp-Request、Node.js、XHR client available
|
|
14
|
+
* support filter specification by tags
|
|
15
|
+
* support JSON specification
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
@@ -108,6 +108,8 @@ npm run openapi
|
|
|
108
108
|
| requestOptionsType | 否 | 自定义请求方法 options 参数类型 | string | '{ [key: string]: unknown }' |
|
|
109
109
|
| requestImportStatement | 否 | 自定义请求方法表达式,例如:'@/request' | string | - |
|
|
110
110
|
| apiPrefix | 否 | api 的前缀,例如:'api'(动态变量), 指定字符串("'api'") | string | - |
|
|
111
|
+
| isDisplayTypeLabel | 否 | 是否生成 type 对应的label | boolean | false |
|
|
112
|
+
| isGenJsonSchemas | 否 | 是否生成 JSON Schemas | boolean | false |
|
|
111
113
|
| dataFields | 否 | 定义 response 中数据字段类型 | string[] | - |
|
|
112
114
|
| mockFolder | 否 | mock目录 | string | './mocks' |
|
|
113
115
|
| nullable | 否 | 使用null代替可选 | boolean | false |
|
|
@@ -125,6 +127,15 @@ npm run openapi
|
|
|
125
127
|
| customType | (<br>schemaObject: SchemaObject \| ReferenceObject,<br>namespace: string,<br>originGetType:(schemaObject: SchemaObject \| ReferenceObject, namespace: string) => string,<br>) => string | 自定义获取类型 <br> *返回非字符串将使用默认方法获取type* |
|
|
126
128
|
| customFileNames | (<br>operationObject: OperationObject,<br>apiPath: string,<br>apiMethod: string,<br>) => string[] | 自定义生成文件名,可返回多个,表示生成多个文件. <br> *返回为空,则使用默认的获取方法获取* |
|
|
127
129
|
|
|
130
|
+
## JSON Schemas
|
|
131
|
+
|
|
132
|
+
- 默认生成 [components.schemas](https://spec.openapis.org/oas/latest.html#components-object) 下面的 JSON Schemas, [paths](https://spec.openapis.org/oas/latest.html#paths-object) 对应的 JSON Schemas 目前需自行解析
|
|
133
|
+
- 提供一个解析 schema 的函数用于将 `$ref`, `$allOf` 的引用填充到 `当前schema`
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
export declare function patchSchema<T extends object>(schema: ISchemaObject, schemas: ComponentsObject["schemas"]): T;
|
|
137
|
+
```
|
|
138
|
+
|
|
128
139
|
## Mock
|
|
129
140
|
|
|
130
141
|
目前使用 [mockjs](http://mockjs.com) 生成 mock 数据,mocks 文件启动需要借助 [@umijs/server](https://umijs.org/docs/guides/mock),后面会寻找其他方案以达到更好的 mock 体验
|
|
@@ -133,16 +144,4 @@ npm run openapi
|
|
|
133
144
|
|
|
134
145
|
- [openapi2typescript](https://github.com/chenshuai2144/openapi2typescript)
|
|
135
146
|
|
|
136
|
-
ps:由于 openapi2typescript 仓库作者不怎么维护这个工具,不会主动增加功能,有些激进的pr
|
|
137
|
-
* 支持 tags 筛选api(对 apifox 工具管理接口非常有用)
|
|
138
|
-
* 支持枚举和枚举翻译
|
|
139
|
-
* 改善 interface 对枚举的引用方式,对 ast 提示更友好
|
|
140
|
-
* 改写 type 文件组织方式,引用 type 的提示更友好
|
|
141
|
-
* 解决 type 重名问题
|
|
142
|
-
* 支持配置文件方式使用,避免强制依赖 ts-node
|
|
143
|
-
* 支持自定义 prettier 配置,将作用于生成后的代码
|
|
144
|
-
* 替换 openapi 规范定义包:openapi3-ts => openapi-types
|
|
145
|
-
* 添加 eslint、tslint 规则,优化代码
|
|
146
|
-
* 添加 husky、lint-staged、commitlint 等等工程化工具
|
|
147
|
-
* 优化对外提供的参数
|
|
148
|
-
* 优化 npm 包依赖
|
|
147
|
+
ps:由于 openapi2typescript 仓库作者不怎么维护这个工具,不会主动增加功能,有些激进的pr也不再合并,为了更大的自主性,也为了方便自己更好的维护此工具,所以基于此仓库重构代码并添加了很多功能,感谢原作者!
|
|
@@ -3,11 +3,15 @@ import { ParameterObject, SchemaObject } from '../type';
|
|
|
3
3
|
export declare const serviceEntryFileName = "index";
|
|
4
4
|
export declare const interfaceFileName = "types";
|
|
5
5
|
export declare const displayEnumLabelFileName = "displayEnumLabel";
|
|
6
|
+
export declare const displayTypeLabelFileName = "displayTypeLabel";
|
|
7
|
+
export declare const schemaFileName = "schema";
|
|
6
8
|
export declare enum TypescriptFileType {
|
|
7
9
|
interface = "interface",
|
|
8
10
|
serviceController = "serviceController",
|
|
9
11
|
serviceIndex = "serviceIndex",
|
|
10
|
-
displayEnumLabel = "displayEnumLabel"
|
|
12
|
+
displayEnumLabel = "displayEnumLabel",
|
|
13
|
+
displayTypeLabel = "displayTypeLabel",
|
|
14
|
+
schema = "schema"
|
|
11
15
|
}
|
|
12
16
|
export declare const DEFAULT_SCHEMA: SchemaObject;
|
|
13
17
|
export declare const DEFAULT_PATH_PARAM: ParameterObject & Dictionary<unknown>;
|
|
@@ -27,3 +31,4 @@ export declare enum parametersInsEnum {
|
|
|
27
31
|
}
|
|
28
32
|
export declare const parametersIn: string[];
|
|
29
33
|
export declare const numberEnum: string[];
|
|
34
|
+
export declare const lineBreakReg: RegExp;
|
package/dist/generator/config.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.numberEnum = exports.parametersIn = exports.parametersInsEnum = exports.methods = exports.DEFAULT_PATH_PARAM = exports.DEFAULT_SCHEMA = exports.TypescriptFileType = exports.displayEnumLabelFileName = exports.interfaceFileName = exports.serviceEntryFileName = void 0;
|
|
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;
|
|
4
4
|
exports.serviceEntryFileName = 'index';
|
|
5
5
|
exports.interfaceFileName = 'types';
|
|
6
6
|
exports.displayEnumLabelFileName = 'displayEnumLabel';
|
|
7
|
+
exports.displayTypeLabelFileName = 'displayTypeLabel';
|
|
8
|
+
exports.schemaFileName = 'schema';
|
|
7
9
|
var TypescriptFileType;
|
|
8
10
|
(function (TypescriptFileType) {
|
|
9
11
|
TypescriptFileType["interface"] = "interface";
|
|
10
12
|
TypescriptFileType["serviceController"] = "serviceController";
|
|
11
13
|
TypescriptFileType["serviceIndex"] = "serviceIndex";
|
|
12
14
|
TypescriptFileType["displayEnumLabel"] = "displayEnumLabel";
|
|
15
|
+
TypescriptFileType["displayTypeLabel"] = "displayTypeLabel";
|
|
16
|
+
TypescriptFileType["schema"] = "schema";
|
|
13
17
|
})(TypescriptFileType || (exports.TypescriptFileType = TypescriptFileType = {}));
|
|
14
18
|
exports.DEFAULT_SCHEMA = {
|
|
15
19
|
type: 'object',
|
|
@@ -55,3 +59,5 @@ exports.numberEnum = [
|
|
|
55
59
|
'int32',
|
|
56
60
|
'int64',
|
|
57
61
|
];
|
|
62
|
+
// 匹配换行符的正则
|
|
63
|
+
exports.lineBreakReg = /[\r\n]+/g;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.patchSchema = void 0;
|
|
4
|
+
const lodash_1 = require("lodash");
|
|
5
|
+
const util_1 = require("./util");
|
|
6
|
+
function patchSchema(schema, schemas) {
|
|
7
|
+
if ((0, lodash_1.isEmpty)(schema)) {
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
if ((0, lodash_1.has)(schema, 'allOf')) {
|
|
11
|
+
return (0, lodash_1.reduce)(schema.allOf, (last, s) => {
|
|
12
|
+
const f = Object.assign({}, (last || {}));
|
|
13
|
+
const next = patchSchema(s, schemas);
|
|
14
|
+
(0, lodash_1.forEach)(next, (v, k) => {
|
|
15
|
+
switch (k) {
|
|
16
|
+
case 'properties':
|
|
17
|
+
f[k] = Object.assign(Object.assign({}, f[k]), (v || {}));
|
|
18
|
+
break;
|
|
19
|
+
case 'required':
|
|
20
|
+
f[k] = (0, lodash_1.uniq)((f[k] || []).concat(v));
|
|
21
|
+
break;
|
|
22
|
+
default: {
|
|
23
|
+
f[k] = v;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return f;
|
|
28
|
+
}, (0, lodash_1.omit)(schema, 'allOf'));
|
|
29
|
+
}
|
|
30
|
+
if ((0, util_1.isReferenceObject)(schema) &&
|
|
31
|
+
(0, lodash_1.startsWith)(schema.$ref, '#/components/schemas/')) {
|
|
32
|
+
const refId = (0, lodash_1.replace)(schema.$ref, '#/components/schemas/', '') ||
|
|
33
|
+
schema['x-id'];
|
|
34
|
+
if (schemas[refId]) {
|
|
35
|
+
return Object.assign(Object.assign(Object.assign({}, schema), patchSchema(schemas[refId], schemas)), { 'x-id': refId, $ref: undefined });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if ((0, util_1.isNonArraySchemaObject)(schema)) {
|
|
39
|
+
const patchedProperties = (0, lodash_1.mapValues)(schema.properties, (propSchema) => patchSchema(propSchema, schemas));
|
|
40
|
+
if ((0, lodash_1.isObject)(schema.additionalProperties)) {
|
|
41
|
+
const additionalProperties = patchSchema(schema.additionalProperties, schemas);
|
|
42
|
+
return Object.assign(Object.assign({}, schema), { additionalProperties });
|
|
43
|
+
}
|
|
44
|
+
return Object.assign(Object.assign({}, schema), { properties: patchedProperties });
|
|
45
|
+
}
|
|
46
|
+
if ((0, util_1.isArraySchemaObject)(schema)) {
|
|
47
|
+
return Object.assign(Object.assign({}, schema), { items: patchSchema(schema.items, schemas) });
|
|
48
|
+
}
|
|
49
|
+
return schema;
|
|
50
|
+
}
|
|
51
|
+
exports.patchSchema = patchSchema;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { GenerateServiceProps } from '../index';
|
|
2
2
|
import { OpenAPIObject } from '../type';
|
|
3
|
-
import { ControllerType, TagAPIDataType } from './type';
|
|
3
|
+
import { ControllerType, ISchemaItem, TagAPIDataType } from './type';
|
|
4
4
|
export default class ServiceGenerator {
|
|
5
5
|
protected apiData: TagAPIDataType;
|
|
6
6
|
protected classNameList: ControllerType[];
|
|
7
7
|
protected finalPath: string;
|
|
8
8
|
protected config: GenerateServiceProps;
|
|
9
9
|
protected openAPIData: OpenAPIObject;
|
|
10
|
+
protected schemaList: ISchemaItem[];
|
|
10
11
|
constructor(config: GenerateServiceProps, openAPIData: OpenAPIObject);
|
|
11
12
|
genFile(): void;
|
|
12
13
|
private getInterfaceTPConfigs;
|
|
@@ -11,12 +11,14 @@ const log_1 = tslib_1.__importDefault(require("../log"));
|
|
|
11
11
|
const type_1 = require("../type");
|
|
12
12
|
const config_1 = require("./config");
|
|
13
13
|
const file_1 = require("./file");
|
|
14
|
+
const patchSchema_1 = require("./patchSchema");
|
|
14
15
|
const util_1 = require("./util");
|
|
15
16
|
class ServiceGenerator {
|
|
16
17
|
constructor(config, openAPIData) {
|
|
17
18
|
var _a, _b;
|
|
18
19
|
this.apiData = {};
|
|
19
20
|
this.classNameList = [];
|
|
21
|
+
this.schemaList = [];
|
|
20
22
|
this.finalPath = '';
|
|
21
23
|
this.config = Object.assign({ templatesFolder: (0, path_1.join)(__dirname, '../../', 'templates') }, config);
|
|
22
24
|
const hookCustomFileNames = ((_a = this.config.hook) === null || _a === void 0 ? void 0 : _a.customFileNames) || util_1.getDefaultFileTag;
|
|
@@ -82,6 +84,14 @@ class ServiceGenerator {
|
|
|
82
84
|
namespace: this.config.namespace,
|
|
83
85
|
interfaceFileName: config_1.interfaceFileName,
|
|
84
86
|
});
|
|
87
|
+
// 生成 type 翻译
|
|
88
|
+
if (this.config.isDisplayTypeLabel) {
|
|
89
|
+
this.genFileFromTemplate(`${config_1.displayTypeLabelFileName}.ts`, config_1.TypescriptFileType.displayTypeLabel, {
|
|
90
|
+
list: (0, lodash_1.filter)(interfaceTPConfigs, (item) => !item.isEnum),
|
|
91
|
+
namespace: this.config.namespace,
|
|
92
|
+
interfaceFileName: config_1.interfaceFileName,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
85
95
|
const prettierError = [];
|
|
86
96
|
// 生成 service controller 文件
|
|
87
97
|
this.getServiceTPConfigs().forEach((tp) => {
|
|
@@ -96,7 +106,16 @@ class ServiceGenerator {
|
|
|
96
106
|
list: this.classNameList,
|
|
97
107
|
namespace: this.config.namespace,
|
|
98
108
|
interfaceFileName: config_1.interfaceFileName,
|
|
109
|
+
schemaFileName: config_1.schemaFileName,
|
|
99
110
|
});
|
|
111
|
+
if (this.config.isGenJsonSchemas) {
|
|
112
|
+
// 处理重复的 schemaName
|
|
113
|
+
(0, util_1.handleDuplicateTypeNames)(this.schemaList);
|
|
114
|
+
// 生成 schema 文件
|
|
115
|
+
this.genFileFromTemplate(`${config_1.schemaFileName}.ts`, config_1.TypescriptFileType.schema, {
|
|
116
|
+
list: this.schemaList,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
100
119
|
// 打印日志
|
|
101
120
|
(0, log_1.default)('✅ 成功生成 api 文件');
|
|
102
121
|
}
|
|
@@ -129,7 +148,7 @@ class ServiceGenerator {
|
|
|
129
148
|
var _a;
|
|
130
149
|
props.push({
|
|
131
150
|
name: parameter.name,
|
|
132
|
-
desc: (_a = parameter.description) !== null && _a !== void 0 ? _a : '',
|
|
151
|
+
desc: ((_a = parameter.description) !== null && _a !== void 0 ? _a : '').replace(config_1.lineBreakReg, ''),
|
|
133
152
|
required: parameter.required || false,
|
|
134
153
|
type: this.getType(parameter.schema),
|
|
135
154
|
});
|
|
@@ -139,7 +158,7 @@ class ServiceGenerator {
|
|
|
139
158
|
var _a;
|
|
140
159
|
props.push({
|
|
141
160
|
name: parameter.name,
|
|
142
|
-
desc: (_a = parameter.description) !== null && _a !== void 0 ? _a : '',
|
|
161
|
+
desc: ((_a = parameter.description) !== null && _a !== void 0 ? _a : '').replace(config_1.lineBreakReg, ''),
|
|
143
162
|
required: parameter.required,
|
|
144
163
|
type: this.getType(parameter.schema),
|
|
145
164
|
});
|
|
@@ -155,6 +174,7 @@ class ServiceGenerator {
|
|
|
155
174
|
});
|
|
156
175
|
});
|
|
157
176
|
(0, lodash_1.keys)(schemas).forEach((schemaKey) => {
|
|
177
|
+
var _a;
|
|
158
178
|
const schema = schemas[schemaKey];
|
|
159
179
|
const result = this.resolveObject(schema);
|
|
160
180
|
const getDefinesType = () => {
|
|
@@ -183,6 +203,7 @@ class ServiceGenerator {
|
|
|
183
203
|
}
|
|
184
204
|
});
|
|
185
205
|
}
|
|
206
|
+
// 判断哪些 schema 需要添加进 type, schemas 渲染数组
|
|
186
207
|
if ((0, lodash_1.isEmpty)(this.config.allowedTags) ||
|
|
187
208
|
schema.isAllowed) {
|
|
188
209
|
const isEnum = result.isEnum;
|
|
@@ -197,6 +218,12 @@ class ServiceGenerator {
|
|
|
197
218
|
: '',
|
|
198
219
|
enumLabelType: isEnum ? result.enumLabelType : '',
|
|
199
220
|
});
|
|
221
|
+
if (this.config.isGenJsonSchemas) {
|
|
222
|
+
this.schemaList.push({
|
|
223
|
+
typeName: `$${(0, util_1.resolveTypeName)(schemaKey)}`,
|
|
224
|
+
type: JSON.stringify((0, patchSchema_1.patchSchema)(schema, (_a = this.openAPIData.components) === null || _a === void 0 ? void 0 : _a.schemas)),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
200
227
|
}
|
|
201
228
|
});
|
|
202
229
|
return lastTypes === null || lastTypes === void 0 ? void 0 : lastTypes.sort((a, b) => a.typeName.localeCompare(b.typeName)); // typeName排序
|
|
@@ -279,7 +306,7 @@ class ServiceGenerator {
|
|
|
279
306
|
: functionName, typeName: this.getTypeName(newApi), path: getPrefixPath(), pathInComment: formattedPath.replace(/\*/g, '*'), hasPathVariables: formattedPath.includes('{'), hasApiPrefix: !!this.config.apiPrefix, method: newApi.method,
|
|
280
307
|
// 如果 functionName 和 summary 相同,则不显示 summary
|
|
281
308
|
desc: functionName === newApi.summary
|
|
282
|
-
? newApi.description
|
|
309
|
+
? (newApi.description || '').replace(config_1.lineBreakReg, '')
|
|
283
310
|
: [
|
|
284
311
|
newApi.summary,
|
|
285
312
|
newApi.description,
|
|
@@ -288,7 +315,8 @@ class ServiceGenerator {
|
|
|
288
315
|
: '',
|
|
289
316
|
]
|
|
290
317
|
.filter((s) => s)
|
|
291
|
-
.join(' ')
|
|
318
|
+
.join(' ')
|
|
319
|
+
.replace(config_1.lineBreakReg, ''), hasHeader: !!(params === null || params === void 0 ? void 0 : params.header) || !!(body === null || body === void 0 ? void 0 : body.mediaType), params: finalParams, hasParams: Boolean((0, lodash_1.keys)(finalParams).length), options: ((_f = (_e = this.config.hook) === null || _e === void 0 ? void 0 : _e.customOptionsDefaultValue) === null || _f === void 0 ? void 0 : _f.call(_e, newApi)) || {}, body,
|
|
292
320
|
file, hasFormData: formData, response });
|
|
293
321
|
}
|
|
294
322
|
catch (error) {
|
|
@@ -325,7 +353,7 @@ class ServiceGenerator {
|
|
|
325
353
|
nunjucks_1.default.configure({
|
|
326
354
|
autoescape: false,
|
|
327
355
|
});
|
|
328
|
-
return (0, file_1.writeFile)(this.config.serversPath, fileName, nunjucks_1.default.renderString(template, Object.assign({
|
|
356
|
+
return (0, file_1.writeFile)(this.config.serversPath, fileName, nunjucks_1.default.renderString(template, Object.assign({ disableTypeCheck: false }, params)));
|
|
329
357
|
}
|
|
330
358
|
catch (error) {
|
|
331
359
|
console.error('[GenSDK] file gen fail:', fileName, 'type:', type);
|
|
@@ -612,7 +640,8 @@ class ServiceGenerator {
|
|
|
612
640
|
// 复用 schema 部分字段
|
|
613
641
|
return Object.assign(Object.assign({}, schema), { name: propKey, type: this.getType(schema), desc: [schema.title, schema.description]
|
|
614
642
|
.filter((item) => item)
|
|
615
|
-
.join(' ')
|
|
643
|
+
.join(' ')
|
|
644
|
+
.replace(config_1.lineBreakReg, ''),
|
|
616
645
|
// 如果没有 required 信息,默认全部是非必填
|
|
617
646
|
required: requiredPropKeys
|
|
618
647
|
? requiredPropKeys.some((key) => key === propKey)
|
package/dist/generator/type.d.ts
CHANGED
package/dist/generator/util.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare function stripDot(str: string): string;
|
|
|
4
4
|
export declare function resolveTypeName(typeName: string): string;
|
|
5
5
|
export declare function getDefaultType(schemaObject?: ISchemaObject | string, namespace?: string, schemas?: ComponentsObject['schemas']): string;
|
|
6
6
|
export declare function getDefaultFileTag(operationObject: OperationObject, apiPath: string): string[];
|
|
7
|
-
export declare function handleDuplicateTypeNames(interfaceTPConfigs: ITypeItem
|
|
7
|
+
export declare function handleDuplicateTypeNames(interfaceTPConfigs: Array<Pick<ITypeItem, 'typeName' | 'displayLabelFuncName'>>): void;
|
|
8
8
|
export declare function getBasePrefix(paths: string[]): string;
|
|
9
9
|
export declare function genDefaultFunctionName(path: string, pathBasePrefix: string): string;
|
|
10
10
|
export declare function getFinalFileName(s: string): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { APIDataType } from './generator/type';
|
|
2
2
|
import { ComponentsObject, OpenAPIObject, OperationObject, ReferenceObject, SchemaObject } from './type';
|
|
3
|
+
export * from './generator/patchSchema';
|
|
3
4
|
export type GenerateServiceProps = {
|
|
4
5
|
/**
|
|
5
6
|
* Swagger 2.0 或 OpenAPI 3.0 的地址
|
|
@@ -38,6 +39,14 @@ export type GenerateServiceProps = {
|
|
|
38
39
|
namespace: string;
|
|
39
40
|
functionName: string;
|
|
40
41
|
}) => string);
|
|
42
|
+
/**
|
|
43
|
+
* 是否生成 type 对应的label, 默认: false
|
|
44
|
+
*/
|
|
45
|
+
isDisplayTypeLabel?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* 是否生成 JSON Schemas, 默认: false
|
|
48
|
+
*/
|
|
49
|
+
isGenJsonSchemas?: boolean;
|
|
41
50
|
/**
|
|
42
51
|
* response中数据字段
|
|
43
52
|
* example: ['result', 'res']
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ const lodash_1 = require("lodash");
|
|
|
6
6
|
const mockGenarator_1 = require("./generator/mockGenarator");
|
|
7
7
|
const serviceGenarator_1 = tslib_1.__importDefault(require("./generator/serviceGenarator"));
|
|
8
8
|
const util_1 = require("./util");
|
|
9
|
+
tslib_1.__exportStar(require("./generator/patchSchema"), exports);
|
|
9
10
|
function generateService(_a) {
|
|
10
11
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
11
12
|
var { requestLibPath, schemaPath, mockFolder, allowedTags } = _a, rest = tslib_1.__rest(_a, ["requestLibPath", "schemaPath", "mockFolder", "allowedTags"]);
|
|
@@ -17,7 +18,7 @@ function generateService(_a) {
|
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
19
20
|
const requestImportStatement = (0, util_1.getImportStatement)(requestLibPath);
|
|
20
|
-
const serviceGenerator = new serviceGenarator_1.default(Object.assign({ schemaPath, serversPath: './src/apis', requestImportStatement, requestOptionsType: '{[key: string]: unknown}', namespace: 'API', nullable: false, isCamelCase: true, allowedTags: allowedTags
|
|
21
|
+
const serviceGenerator = new serviceGenarator_1.default(Object.assign({ schemaPath, serversPath: './src/apis', requestImportStatement, requestOptionsType: '{[key: string]: unknown}', namespace: 'API', nullable: false, isCamelCase: true, isDisplayTypeLabel: false, isGenJsonSchemas: false, allowedTags: allowedTags
|
|
21
22
|
? (0, lodash_1.map)(allowedTags, (item) => item.toLowerCase())
|
|
22
23
|
: null }, rest), openAPI);
|
|
23
24
|
serviceGenerator.genFile();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openapi-ts-request",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Swagger2/OpenAPI3 to TypeScript,
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Swagger2/OpenAPI3 to TypeScript, request client, request mock service, enum, type field label, JSON Schemas",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+git@github.com:openapi-ui/openapi-ts-request.git"
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"reserved-words": "^0.1.2",
|
|
33
33
|
"rimraf": "^5.0.7",
|
|
34
34
|
"swagger2openapi": "^7.0.8",
|
|
35
|
-
"tiny-pinyin": "^1.3.2"
|
|
35
|
+
"tiny-pinyin": "^1.3.2",
|
|
36
|
+
"tslib": "^2.6.3"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@changesets/changelog-github": "^0.5.0",
|
|
@@ -54,7 +55,6 @@
|
|
|
54
55
|
"lint-staged": "^15.2.5",
|
|
55
56
|
"np": "^10.0.6",
|
|
56
57
|
"openapi-types": "^12.1.3",
|
|
57
|
-
"tslib": "^2.6.3",
|
|
58
58
|
"typescript": "5.4.5"
|
|
59
59
|
},
|
|
60
60
|
"keywords": [
|
|
@@ -65,7 +65,8 @@
|
|
|
65
65
|
"openapi to request client",
|
|
66
66
|
"openapi to axios client",
|
|
67
67
|
"openapi to fetch client",
|
|
68
|
-
"openapi to uni
|
|
68
|
+
"openapi to uni request client",
|
|
69
|
+
"openapi to JSON Schemas"
|
|
69
70
|
],
|
|
70
71
|
"scripts": {
|
|
71
72
|
"start": "tsc -w",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-ignore
|
|
3
|
+
import * as {{ namespace }} from './{{ interfaceFileName }}';
|
|
4
|
+
|
|
5
|
+
{% for type in list -%}
|
|
6
|
+
{%- if type.props.length %}
|
|
7
|
+
export function display{{ type.typeName }}(field: keyof {{ namespace }}.{{ type.typeName }}) {
|
|
8
|
+
return (
|
|
9
|
+
{%- for prop in type.props %}
|
|
10
|
+
{%- if prop.length > 1 %}
|
|
11
|
+
{
|
|
12
|
+
{%- endif %}
|
|
13
|
+
{%- if prop.length == 1 %}
|
|
14
|
+
{%- if not prop[0].$ref or prop[0].name %}
|
|
15
|
+
{
|
|
16
|
+
{%- endif %}
|
|
17
|
+
{%- endif %}
|
|
18
|
+
{%- for p in prop %}
|
|
19
|
+
{%- if p["$ref"] and not p.name %}
|
|
20
|
+
display{{ p.type | safe }}(field as keyof {{ namespace }}.{{ p.type }})
|
|
21
|
+
{%- else %}
|
|
22
|
+
{{ p.name }}: '{{ p.desc if p.desc else p.name }}',
|
|
23
|
+
{%- endif %}
|
|
24
|
+
{%- endfor %}
|
|
25
|
+
{%- if prop.length > 1 %}
|
|
26
|
+
}[field]
|
|
27
|
+
{%- endif %}
|
|
28
|
+
{%- if prop.length == 1 %}
|
|
29
|
+
{%- if not prop[0].$ref or prop[0].name %}
|
|
30
|
+
}[field]
|
|
31
|
+
{%- endif %}
|
|
32
|
+
{%- endif %}
|
|
33
|
+
{%- if prop.length == 0 %}
|
|
34
|
+
{}
|
|
35
|
+
{%- endif %}
|
|
36
|
+
{{ '' if loop.last === true else ' || ' }}
|
|
37
|
+
{%- endfor %}
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
{%- endif %}
|
|
41
|
+
|
|
42
|
+
{% endfor -%}
|
package/templates/interface.njk
CHANGED
|
@@ -1,54 +1,56 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
// @ts-ignore
|
|
3
|
-
{
|
|
4
|
-
{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
{%-
|
|
8
|
-
{
|
|
9
|
-
|
|
10
|
-
{%- if prop.length == 1 %}
|
|
11
|
-
{%- if not prop[0].$ref or prop[0].name %}
|
|
12
|
-
{
|
|
3
|
+
{%- if list.length > 0 %}
|
|
4
|
+
{% for type in list -%}
|
|
5
|
+
{%- if type.props.length %}
|
|
6
|
+
export type {{ type.typeName | safe }} =
|
|
7
|
+
{%- for prop in type.props %}
|
|
8
|
+
{%- if prop.length > 1 %}
|
|
9
|
+
{
|
|
13
10
|
{%- endif %}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{
|
|
17
|
-
/** {{ p.desc }} */
|
|
11
|
+
{%- if prop.length == 1 %}
|
|
12
|
+
{%- if not prop[0].$ref or prop[0].name %}
|
|
13
|
+
{
|
|
18
14
|
{%- endif %}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
{
|
|
22
|
-
|
|
23
|
-
{%-
|
|
24
|
-
|
|
15
|
+
{%- endif %}
|
|
16
|
+
{%- for p in prop %}
|
|
17
|
+
{%- if p.desc %}
|
|
18
|
+
/** {{ p.desc }} */
|
|
19
|
+
{%- endif %}
|
|
20
|
+
{%- if p["$ref"] and not p.name %}
|
|
21
|
+
// {{ p.$ref }}
|
|
22
|
+
{{ p.type | safe }}
|
|
25
23
|
{%- else %}
|
|
26
|
-
|
|
24
|
+
{%- if nullable %}
|
|
25
|
+
'{{ p.name }}': {{ p.type | safe }}{{'' if p.required else '| null'}};
|
|
26
|
+
{%- else %}
|
|
27
|
+
'{{ p.name }}'{{ '' if p.required else '?' }}: {{ p.type | safe }};
|
|
28
|
+
{%- endif %}
|
|
27
29
|
{%- endif %}
|
|
30
|
+
{%- endfor %}
|
|
31
|
+
{%- if prop.length > 1 %}
|
|
32
|
+
}
|
|
33
|
+
{%- endif %}
|
|
34
|
+
{%- if prop.length == 1 %}
|
|
35
|
+
{%- if not prop[0].$ref or prop[0].name %}
|
|
36
|
+
}
|
|
28
37
|
{%- endif %}
|
|
29
|
-
{%- endfor %}
|
|
30
|
-
{%- if prop.length > 1 %}
|
|
31
|
-
}
|
|
32
|
-
{%- endif %}
|
|
33
|
-
{%- if prop.length == 1 %}
|
|
34
|
-
{%- if not prop[0].$ref or prop[0].name %}
|
|
35
|
-
}
|
|
36
38
|
{%- endif %}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{}
|
|
40
|
-
|
|
41
|
-
{
|
|
42
|
-
{%- endfor %}
|
|
43
|
-
{%- else %}
|
|
44
|
-
{%- if type.isEnum %}
|
|
45
|
-
export enum {{ type.typeName | safe }} {{ type.type }};
|
|
46
|
-
|
|
47
|
-
export type I{{ type.typeName | safe }} = keyof typeof {{ type.typeName }}
|
|
39
|
+
{%- if prop.length == 0 %}
|
|
40
|
+
{}
|
|
41
|
+
{%- endif %}
|
|
42
|
+
{{ '' if loop.last === true else ' & ' }}
|
|
43
|
+
{%- endfor %}
|
|
48
44
|
{%- else %}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
{%- endif %}
|
|
52
|
-
{% endfor %}
|
|
45
|
+
{%- if type.isEnum %}
|
|
46
|
+
export enum {{ type.typeName | safe }} {{ type.type }};
|
|
53
47
|
|
|
54
|
-
export
|
|
48
|
+
export type I{{ type.typeName | safe }} = keyof typeof {{ type.typeName }}
|
|
49
|
+
{%- else %}
|
|
50
|
+
export type {{ type.typeName | safe }} = {{ type.type }};
|
|
51
|
+
{%- endif %}
|
|
52
|
+
{%- endif %}
|
|
53
|
+
{% endfor %}
|
|
54
|
+
{%- else %}
|
|
55
|
+
export default {}
|
|
56
|
+
{%- endif %}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
// @ts-ignore
|
|
3
3
|
import * as {{ namespace }} from './{{ interfaceFileName }}';
|
|
4
|
+
import * as schemas from './{{ schemaFileName }}';
|
|
4
5
|
{% for api in list -%}
|
|
5
6
|
import * as {{ api.controllerName }} from './{{ api.fileName }}';
|
|
6
7
|
{% endfor -%}
|
|
7
8
|
|
|
8
9
|
export default {
|
|
10
|
+
schemas,
|
|
9
11
|
{{ namespace }},
|
|
10
12
|
{% for api in list -%}
|
|
11
13
|
{{ api.controllerName }},
|