@midwayjs/swagger 3.15.10 → 3.16.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/dist/decorators/api-header.decorator.js +1 -1
- package/dist/swaggerExplorer.d.ts +26 -2
- package/dist/swaggerExplorer.js +267 -178
- package/package.json +9 -10
|
@@ -27,7 +27,7 @@ function ApiHeader(options) {
|
|
|
27
27
|
}
|
|
28
28
|
return (target, key, descriptor) => {
|
|
29
29
|
if (descriptor) {
|
|
30
|
-
return (0, helpers_1.
|
|
30
|
+
return (0, helpers_1.createMixedDecorator)(constants_1.DECORATORS.API_HEADERS, param)(target, key, descriptor);
|
|
31
31
|
}
|
|
32
32
|
return (0, helpers_1.createMixedDecorator)(constants_1.DECORATORS.API_HEADERS, param)(target, undefined, undefined);
|
|
33
33
|
};
|
|
@@ -14,19 +14,43 @@ export declare class SwaggerExplorer {
|
|
|
14
14
|
*/
|
|
15
15
|
private generateRouteMethod;
|
|
16
16
|
getOperationId(controllerKey: string, webRouter: RouterOption): string;
|
|
17
|
-
private expandSchemaRef;
|
|
18
17
|
/**
|
|
19
18
|
* 提取参数
|
|
20
19
|
* @param params
|
|
21
20
|
* @param p
|
|
22
21
|
*/
|
|
23
|
-
|
|
22
|
+
protected parseFromParamsToP(paramMeta: any, p: any): void;
|
|
24
23
|
/**
|
|
25
24
|
* 解析 ApiExtraModel
|
|
26
25
|
* @param clzz
|
|
27
26
|
*/
|
|
28
27
|
private parseExtraModel;
|
|
29
28
|
protected parseSubPropertyType(metadata: any): any;
|
|
29
|
+
protected formatType(metadata: {
|
|
30
|
+
type: any;
|
|
31
|
+
items?: any;
|
|
32
|
+
format?: string;
|
|
33
|
+
oneOf?: any[];
|
|
34
|
+
allOf?: any[];
|
|
35
|
+
anyOf?: any[];
|
|
36
|
+
not?: any;
|
|
37
|
+
enum?: any[];
|
|
38
|
+
properties?: any;
|
|
39
|
+
additionalProperties?: any;
|
|
40
|
+
$ref?: any;
|
|
41
|
+
}): {
|
|
42
|
+
type: any;
|
|
43
|
+
items?: any;
|
|
44
|
+
format?: string;
|
|
45
|
+
oneOf?: any[];
|
|
46
|
+
allOf?: any[];
|
|
47
|
+
anyOf?: any[];
|
|
48
|
+
not?: any;
|
|
49
|
+
enum?: any[];
|
|
50
|
+
properties?: any;
|
|
51
|
+
additionalProperties?: any;
|
|
52
|
+
$ref?: any;
|
|
53
|
+
};
|
|
30
54
|
/**
|
|
31
55
|
* 解析类型的 ApiProperty
|
|
32
56
|
* @param clzz
|
package/dist/swaggerExplorer.js
CHANGED
|
@@ -242,7 +242,7 @@ let SwaggerExplorer = class SwaggerExplorer {
|
|
|
242
242
|
* 构造 router 提取方法
|
|
243
243
|
*/
|
|
244
244
|
generateRouteMethod(url, webRouter, paths, metaForMethods, routerArgs, headers, target) {
|
|
245
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
245
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
246
246
|
const operMeta = metaForMethods.filter(item => item.key === constants_1.DECORATORS.API_OPERATION &&
|
|
247
247
|
item.propertyName === webRouter.method)[0];
|
|
248
248
|
let opts = paths[url];
|
|
@@ -253,12 +253,13 @@ let SwaggerExplorer = class SwaggerExplorer {
|
|
|
253
253
|
opts[webRouter.requestMethod] = {
|
|
254
254
|
summary: getNotEmptyValue((_a = operMeta === null || operMeta === void 0 ? void 0 : operMeta.metadata) === null || _a === void 0 ? void 0 : _a.summary, webRouter.summary),
|
|
255
255
|
description: getNotEmptyValue((_b = operMeta === null || operMeta === void 0 ? void 0 : operMeta.metadata) === null || _b === void 0 ? void 0 : _b.description, webRouter.description),
|
|
256
|
-
operationId:
|
|
257
|
-
|
|
256
|
+
operationId: ((_c = operMeta === null || operMeta === void 0 ? void 0 : operMeta.metadata) === null || _c === void 0 ? void 0 : _c.operationId) ||
|
|
257
|
+
this.getOperationId(target.name, webRouter),
|
|
258
|
+
tags: ((_d = operMeta === null || operMeta === void 0 ? void 0 : operMeta.metadata) === null || _d === void 0 ? void 0 : _d.tags) || [],
|
|
258
259
|
};
|
|
259
|
-
if (((
|
|
260
|
+
if (((_e = operMeta === null || operMeta === void 0 ? void 0 : operMeta.metadata) === null || _e === void 0 ? void 0 : _e.deprecated) != null) {
|
|
260
261
|
opts[webRouter.requestMethod].deprecated =
|
|
261
|
-
!!((
|
|
262
|
+
!!((_f = operMeta === null || operMeta === void 0 ? void 0 : operMeta.metadata) === null || _f === void 0 ? void 0 : _f.deprecated);
|
|
262
263
|
}
|
|
263
264
|
/**
|
|
264
265
|
* [{"key":"web:router_param","parameterIndex":1,"propertyName":"create","metadata":{"type":2}},
|
|
@@ -273,13 +274,75 @@ let SwaggerExplorer = class SwaggerExplorer {
|
|
|
273
274
|
const types = (0, core_1.getMethodParamTypes)(target, webRouter.method);
|
|
274
275
|
const params = metaForMethods.filter(item => item.key === constants_1.DECORATORS.API_PARAMETERS &&
|
|
275
276
|
item.propertyName === webRouter.method);
|
|
277
|
+
// set params information from @ApiQuery() to parameters
|
|
278
|
+
for (const param of params) {
|
|
279
|
+
// rebuild query param to swagger format
|
|
280
|
+
if (param.metadata.schema === undefined) {
|
|
281
|
+
param.metadata.schema = {};
|
|
282
|
+
if (param.metadata.type) {
|
|
283
|
+
param.metadata.schema['type'] = param.metadata.type;
|
|
284
|
+
delete param.metadata.type;
|
|
285
|
+
}
|
|
286
|
+
if (param.metadata.isArray !== undefined) {
|
|
287
|
+
param.metadata.schema['items'] = {
|
|
288
|
+
type: param.metadata.schema['type'],
|
|
289
|
+
};
|
|
290
|
+
param.metadata.schema['type'] = 'array';
|
|
291
|
+
delete param.metadata.isArray;
|
|
292
|
+
}
|
|
293
|
+
if (param.metadata.enum !== undefined) {
|
|
294
|
+
param.metadata.schema.enum = param.metadata.enum;
|
|
295
|
+
delete param.metadata.enum;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
// if schema is defined, then type is not needed
|
|
300
|
+
delete param.metadata.type;
|
|
301
|
+
delete param.metadata.isArray;
|
|
302
|
+
delete param.metadata.enum;
|
|
303
|
+
}
|
|
304
|
+
const p = param.metadata;
|
|
305
|
+
p.schema = this.formatType(param.metadata.schema);
|
|
306
|
+
if (p.in === 'query' || p.in === 'path' || p.in === 'header') {
|
|
307
|
+
parameters.push(p);
|
|
308
|
+
}
|
|
309
|
+
else if (p.in === 'body') {
|
|
310
|
+
p.content = (_g = p.content) !== null && _g !== void 0 ? _g : {};
|
|
311
|
+
if (Object.keys(p.content).length === 0) {
|
|
312
|
+
p.content[p.contentType || 'application/json'] = (_h = p.content[p.contentType || 'application/json']) !== null && _h !== void 0 ? _h : {
|
|
313
|
+
schema: p.schema,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
// format schema
|
|
317
|
+
for (const key in p.content) {
|
|
318
|
+
p.content[key].schema = this.formatType(p.content[key].schema);
|
|
319
|
+
}
|
|
320
|
+
// if requestBody is already set, skip
|
|
321
|
+
opts[webRouter.requestMethod].requestBody =
|
|
322
|
+
(_j = opts[webRouter.requestMethod].requestBody) !== null && _j !== void 0 ? _j : {};
|
|
323
|
+
opts[webRouter.requestMethod].requestBody.description =
|
|
324
|
+
(_k = opts[webRouter.requestMethod].requestBody.description) !== null && _k !== void 0 ? _k : p.description;
|
|
325
|
+
opts[webRouter.requestMethod].requestBody.content =
|
|
326
|
+
(_l = opts[webRouter.requestMethod].requestBody.content) !== null && _l !== void 0 ? _l : p.content;
|
|
327
|
+
opts[webRouter.requestMethod].requestBody.required =
|
|
328
|
+
(_m = opts[webRouter.requestMethod].requestBody.required) !== null && _m !== void 0 ? _m : p.required;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
276
331
|
for (const arg of args) {
|
|
277
332
|
const currentType = types[arg.parameterIndex];
|
|
278
333
|
const p = {
|
|
279
|
-
name: (
|
|
280
|
-
in: convertTypeToString((
|
|
334
|
+
name: (_o = arg === null || arg === void 0 ? void 0 : arg.metadata) === null || _o === void 0 ? void 0 : _o.propertyData,
|
|
335
|
+
in: convertTypeToString((_p = arg.metadata) === null || _p === void 0 ? void 0 : _p.type),
|
|
281
336
|
required: false,
|
|
282
337
|
};
|
|
338
|
+
const existsParam = parameters.find(item => {
|
|
339
|
+
var _a;
|
|
340
|
+
return item.name === ((_a = arg === null || arg === void 0 ? void 0 : arg.metadata) === null || _a === void 0 ? void 0 : _a.propertyData) && item.in === p.in;
|
|
341
|
+
});
|
|
342
|
+
// if exists same param from @ApiQuery and other decorator, just skip
|
|
343
|
+
if (existsParam) {
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
283
346
|
if (p.in === 'path') {
|
|
284
347
|
p.required = true;
|
|
285
348
|
if (url.indexOf('{' + p.name + '}') === -1) {
|
|
@@ -288,100 +351,112 @@ let SwaggerExplorer = class SwaggerExplorer {
|
|
|
288
351
|
}
|
|
289
352
|
if (core_1.Types.isClass(currentType)) {
|
|
290
353
|
this.parseClzz(currentType);
|
|
291
|
-
|
|
354
|
+
}
|
|
355
|
+
if (p.in === 'query' || p.in === 'path') {
|
|
356
|
+
if (core_1.Types.isClass(currentType)) {
|
|
292
357
|
// 如果@Query()装饰的 是一个对象,则把该对象的子属性作为多个@Query参数
|
|
293
358
|
const schema = this.documentBuilder.getSchema(currentType.name);
|
|
294
359
|
Object.keys(schema.properties).forEach(pName => {
|
|
295
|
-
const ppt = schema.properties[pName];
|
|
296
360
|
const pp = {
|
|
297
361
|
name: pName,
|
|
298
362
|
in: p.in,
|
|
363
|
+
schema: schema.properties[pName],
|
|
299
364
|
};
|
|
300
|
-
this.parseFromParamsToP({ metadata: ppt }, pp);
|
|
301
365
|
parameters.push(pp);
|
|
302
366
|
});
|
|
303
367
|
continue;
|
|
304
368
|
}
|
|
305
369
|
else {
|
|
370
|
+
if (!p.name) {
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
306
373
|
p.schema = {
|
|
307
|
-
|
|
374
|
+
type: convertSchemaType((_q = currentType === null || currentType === void 0 ? void 0 : currentType.name) !== null && _q !== void 0 ? _q : currentType),
|
|
308
375
|
};
|
|
309
376
|
}
|
|
310
377
|
}
|
|
311
|
-
else {
|
|
312
|
-
p.schema = {
|
|
313
|
-
type: convertSchemaType((_j = currentType === null || currentType === void 0 ? void 0 : currentType.name) !== null && _j !== void 0 ? _j : currentType),
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
this.parseFromParamsToP(params[params.length - 1 - arg.parameterIndex], p);
|
|
317
|
-
if (p.in === 'body') {
|
|
378
|
+
else if (p.in === 'body') {
|
|
318
379
|
if (webRouter.requestMethod === core_1.RequestMethod.GET) {
|
|
319
380
|
continue;
|
|
320
381
|
}
|
|
382
|
+
// if requestBody is already set, skip
|
|
383
|
+
if (opts[webRouter.requestMethod].requestBody) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
321
386
|
// 这里兼容一下 @File()、@Files()、@Fields() 装饰器
|
|
322
|
-
if (((
|
|
323
|
-
p.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
type: '
|
|
330
|
-
|
|
387
|
+
if (((_r = arg.metadata) === null || _r === void 0 ? void 0 : _r.type) === core_1.RouteParamTypes.FILESSTREAM) {
|
|
388
|
+
p.content = {};
|
|
389
|
+
p.content[_1.BodyContentType.Multipart] = {
|
|
390
|
+
schema: {
|
|
391
|
+
type: 'object',
|
|
392
|
+
properties: {
|
|
393
|
+
files: {
|
|
394
|
+
type: 'array',
|
|
395
|
+
items: {
|
|
396
|
+
type: 'string',
|
|
397
|
+
format: 'binary',
|
|
398
|
+
},
|
|
399
|
+
description: p.description,
|
|
331
400
|
},
|
|
332
|
-
description: p.description,
|
|
333
401
|
},
|
|
334
402
|
},
|
|
335
403
|
};
|
|
336
|
-
p.contentType = _1.BodyContentType.Multipart;
|
|
337
404
|
}
|
|
338
|
-
if (((
|
|
339
|
-
p.
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
405
|
+
else if (((_s = arg.metadata) === null || _s === void 0 ? void 0 : _s.type) === core_1.RouteParamTypes.FILESTREAM) {
|
|
406
|
+
p.content = {};
|
|
407
|
+
p.content[_1.BodyContentType.Multipart] = {
|
|
408
|
+
schema: {
|
|
409
|
+
type: 'object',
|
|
410
|
+
properties: {
|
|
411
|
+
file: {
|
|
412
|
+
type: 'string',
|
|
413
|
+
format: 'binary',
|
|
414
|
+
description: p.description,
|
|
415
|
+
},
|
|
346
416
|
},
|
|
347
417
|
},
|
|
348
418
|
};
|
|
349
|
-
p.contentType = _1.BodyContentType.Multipart;
|
|
350
|
-
}
|
|
351
|
-
if (((_m = arg.metadata) === null || _m === void 0 ? void 0 : _m.type) === core_1.RouteParamTypes.FIELDS) {
|
|
352
|
-
this.expandSchemaRef(p);
|
|
353
|
-
p.contentType = _1.BodyContentType.Multipart;
|
|
354
|
-
}
|
|
355
|
-
if (!p.content) {
|
|
356
|
-
p.content = {};
|
|
357
|
-
p.content[p.contentType || 'application/json'] = {
|
|
358
|
-
schema: p.schema,
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
if (!opts[webRouter.requestMethod].requestBody) {
|
|
362
|
-
const requestBody = {
|
|
363
|
-
required: true,
|
|
364
|
-
description: p.description || p.name,
|
|
365
|
-
content: p.content,
|
|
366
|
-
};
|
|
367
|
-
opts[webRouter.requestMethod].requestBody = requestBody;
|
|
368
419
|
}
|
|
369
420
|
else {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
421
|
+
if (core_1.Types.isClass(currentType)) {
|
|
422
|
+
p.content = {
|
|
423
|
+
'application/json': {
|
|
424
|
+
schema: {
|
|
425
|
+
$ref: '#/components/schemas/' + currentType.name,
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
// base type
|
|
432
|
+
p.content = {
|
|
433
|
+
'text/plain': {
|
|
434
|
+
schema: {
|
|
435
|
+
type: convertSchemaType((_t = currentType === null || currentType === void 0 ? void 0 : currentType.name) !== null && _t !== void 0 ? _t : currentType),
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
};
|
|
439
|
+
}
|
|
373
440
|
}
|
|
374
|
-
|
|
375
|
-
|
|
441
|
+
opts[webRouter.requestMethod].requestBody = {
|
|
442
|
+
required: true,
|
|
443
|
+
description: p.description || p.name,
|
|
444
|
+
content: p.content,
|
|
445
|
+
};
|
|
376
446
|
// in body 不需要处理
|
|
377
447
|
continue;
|
|
378
448
|
}
|
|
379
449
|
parameters.push(p);
|
|
380
450
|
}
|
|
381
451
|
// class header 需要使用 ApiHeader 装饰器
|
|
382
|
-
if (headers) {
|
|
452
|
+
if (headers && headers.length) {
|
|
383
453
|
headers.forEach(header => parameters.unshift(header));
|
|
384
454
|
}
|
|
455
|
+
// 获取方法上的 @ApiHeader
|
|
456
|
+
const methodHeaders = metaForMethods.filter(item => item.key === constants_1.DECORATORS.API_HEADERS);
|
|
457
|
+
if (methodHeaders.length > 0) {
|
|
458
|
+
methodHeaders.forEach(item => parameters.unshift(item.metadata));
|
|
459
|
+
}
|
|
385
460
|
opts[webRouter.requestMethod].parameters = parameters;
|
|
386
461
|
const responses = metaForMethods.filter(item => item.key === constants_1.DECORATORS.API_RESPONSE &&
|
|
387
462
|
item.propertyName === webRouter.method);
|
|
@@ -449,25 +524,6 @@ let SwaggerExplorer = class SwaggerExplorer {
|
|
|
449
524
|
getOperationId(controllerKey, webRouter) {
|
|
450
525
|
return this.operationIdFactory(controllerKey, webRouter);
|
|
451
526
|
}
|
|
452
|
-
expandSchemaRef(p, name) {
|
|
453
|
-
let schemaName = name;
|
|
454
|
-
if (p.schema['$ref']) {
|
|
455
|
-
// 展开各个字段属性
|
|
456
|
-
schemaName = p.schema['$ref'].replace('#/components/schemas/', '');
|
|
457
|
-
delete p.schema['$ref'];
|
|
458
|
-
}
|
|
459
|
-
if (schemaName) {
|
|
460
|
-
const schema = this.documentBuilder.getSchema(schemaName);
|
|
461
|
-
const ss = JSON.parse(JSON.stringify(schema));
|
|
462
|
-
if (p.schema.properties) {
|
|
463
|
-
Object.assign(p.schema.properties, ss.properties);
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
p.schema = JSON.parse(JSON.stringify(schema));
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
return p;
|
|
470
|
-
}
|
|
471
527
|
/**
|
|
472
528
|
* 提取参数
|
|
473
529
|
* @param params
|
|
@@ -674,18 +730,104 @@ let SwaggerExplorer = class SwaggerExplorer {
|
|
|
674
730
|
}
|
|
675
731
|
return Object.assign(typeMeta, metadata);
|
|
676
732
|
}
|
|
733
|
+
formatType(metadata) {
|
|
734
|
+
if (metadata === null) {
|
|
735
|
+
return null;
|
|
736
|
+
}
|
|
737
|
+
// 如果有枚举,单独处理
|
|
738
|
+
if (metadata.enum) {
|
|
739
|
+
// enum 不需要处理
|
|
740
|
+
metadata.enum.map(item => this.formatType(item));
|
|
741
|
+
}
|
|
742
|
+
if (metadata.not) {
|
|
743
|
+
metadata.not = this.formatType(metadata.not);
|
|
744
|
+
}
|
|
745
|
+
if (metadata['$ref'] && typeof metadata['$ref'] === 'function') {
|
|
746
|
+
metadata['$ref'] = metadata['$ref']();
|
|
747
|
+
}
|
|
748
|
+
if (metadata.oneOf) {
|
|
749
|
+
metadata.oneOf = metadata.oneOf.map(item => this.formatType(item));
|
|
750
|
+
}
|
|
751
|
+
else if (metadata.anyOf) {
|
|
752
|
+
metadata.anyOf = metadata.anyOf.map(item => this.formatType(item));
|
|
753
|
+
}
|
|
754
|
+
else if (metadata.allOf) {
|
|
755
|
+
metadata.allOf = metadata.allOf.map(item => this.formatType(item));
|
|
756
|
+
}
|
|
757
|
+
// 有下面的这些属性,就不需要 type 了
|
|
758
|
+
['not', '$ref', 'oneOf', 'anyOf', 'allOf'].forEach(key => {
|
|
759
|
+
if (metadata[key]) {
|
|
760
|
+
delete metadata['type'];
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
if (metadata.properties) {
|
|
764
|
+
const properties = {};
|
|
765
|
+
for (const key in metadata.properties) {
|
|
766
|
+
properties[key] = this.formatType(metadata.properties[key]);
|
|
767
|
+
}
|
|
768
|
+
metadata.properties = properties;
|
|
769
|
+
}
|
|
770
|
+
if (metadata.additionalProperties) {
|
|
771
|
+
metadata.additionalProperties = this.formatType(metadata.additionalProperties);
|
|
772
|
+
}
|
|
773
|
+
// 处理类型
|
|
774
|
+
if (['string', 'number', 'boolean', 'integer'].includes(metadata.type)) {
|
|
775
|
+
// 不做处理
|
|
776
|
+
}
|
|
777
|
+
else if (metadata.type === Number) {
|
|
778
|
+
metadata.type = 'number';
|
|
779
|
+
}
|
|
780
|
+
else if (metadata.type === String) {
|
|
781
|
+
metadata.type = 'string';
|
|
782
|
+
}
|
|
783
|
+
else if (metadata.type === Boolean) {
|
|
784
|
+
metadata.type = 'boolean';
|
|
785
|
+
}
|
|
786
|
+
else if (metadata.type === 'date' ||
|
|
787
|
+
metadata.type === 'Date' ||
|
|
788
|
+
metadata.type === Date) {
|
|
789
|
+
metadata.type = 'string';
|
|
790
|
+
metadata.format = 'date-time';
|
|
791
|
+
}
|
|
792
|
+
else if (metadata.type === Array || metadata.type === 'array') {
|
|
793
|
+
// Array => { type: 'array' }
|
|
794
|
+
metadata.type = 'array';
|
|
795
|
+
if (metadata.items) {
|
|
796
|
+
metadata.items = this.formatType(metadata.items);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
else if (Array.isArray(metadata.type)) {
|
|
800
|
+
// [String] => { type: 'array', items: { type: 'string' } }
|
|
801
|
+
metadata.items = this.formatType({ type: metadata.type[0] });
|
|
802
|
+
metadata.type = 'array';
|
|
803
|
+
}
|
|
804
|
+
else if (metadata.type === Object || metadata.type === 'object') {
|
|
805
|
+
metadata.type = 'object';
|
|
806
|
+
}
|
|
807
|
+
else if (core_1.Types.isClass(metadata.type)) {
|
|
808
|
+
this.parseClzz(metadata.type);
|
|
809
|
+
metadata['$ref'] = '#/components/schemas/' + metadata.type.name;
|
|
810
|
+
delete metadata['type'];
|
|
811
|
+
}
|
|
812
|
+
else if (metadata.type instanceof Function) {
|
|
813
|
+
// () => String => { type: 'string' }
|
|
814
|
+
metadata.type = metadata.type();
|
|
815
|
+
this.formatType(metadata);
|
|
816
|
+
}
|
|
817
|
+
return metadata;
|
|
818
|
+
}
|
|
677
819
|
/**
|
|
678
820
|
* 解析类型的 ApiProperty
|
|
679
821
|
* @param clzz
|
|
680
822
|
*/
|
|
681
823
|
parseClzz(clzz) {
|
|
682
|
-
var _a, _b, _c;
|
|
683
824
|
if (this.documentBuilder.getSchema(clzz.name)) {
|
|
684
825
|
return this.documentBuilder.getSchema(clzz.name);
|
|
685
826
|
}
|
|
686
827
|
// 解析 ApiExtraModel
|
|
687
828
|
this.parseExtraModel(clzz);
|
|
688
829
|
// 解析类上的 ApiProperty
|
|
830
|
+
// TODO 这里后面不能用这个方法
|
|
689
831
|
const props = (0, core_1.getClassExtendedMetadata)(core_1.INJECT_CUSTOM_PROPERTY, clzz);
|
|
690
832
|
const tt = {
|
|
691
833
|
type: 'object',
|
|
@@ -697,115 +839,62 @@ let SwaggerExplorer = class SwaggerExplorer {
|
|
|
697
839
|
});
|
|
698
840
|
if (props) {
|
|
699
841
|
for (const key of Object.keys(props)) {
|
|
700
|
-
const metadata = {};
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
842
|
+
const metadata = props[key].metadata || {};
|
|
843
|
+
if (!metadata.type) {
|
|
844
|
+
// 推导类型
|
|
845
|
+
metadata.type = (0, core_1.getPropertyType)(clzz.prototype, key).name;
|
|
846
|
+
}
|
|
847
|
+
tt.properties[key] = tt.properties[key] || {};
|
|
848
|
+
// loop metadata
|
|
849
|
+
for (const metadataKey in metadata) {
|
|
850
|
+
if (metadataKey === 'required' && metadata['required']) {
|
|
851
|
+
// required 需要加到 schema 上
|
|
704
852
|
if (!tt.required) {
|
|
705
853
|
tt.required = [];
|
|
706
854
|
}
|
|
707
855
|
tt.required.push(key);
|
|
708
856
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
enum: metadata === null || metadata === void 0 ? void 0 : metadata.enum,
|
|
715
|
-
default: metadata === null || metadata === void 0 ? void 0 : metadata.default,
|
|
716
|
-
};
|
|
717
|
-
if (metadata === null || metadata === void 0 ? void 0 : metadata.description) {
|
|
718
|
-
tt.properties[key].description = metadata === null || metadata === void 0 ? void 0 : metadata.description;
|
|
857
|
+
else if (['oneOf', 'anyOf', 'allOf'].includes(metadataKey)) {
|
|
858
|
+
tt.properties[key][metadataKey] = [];
|
|
859
|
+
metadata[metadataKey].forEach((meta) => {
|
|
860
|
+
tt.properties[key][metadataKey].push(this.formatType(meta));
|
|
861
|
+
});
|
|
719
862
|
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
if ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.items) === null || _a === void 0 ? void 0 : _a.enum) {
|
|
723
|
-
tt.properties[key] = {
|
|
724
|
-
type: metadata === null || metadata === void 0 ? void 0 : metadata.type,
|
|
725
|
-
items: metadata === null || metadata === void 0 ? void 0 : metadata.items,
|
|
726
|
-
default: metadata === null || metadata === void 0 ? void 0 : metadata.default,
|
|
727
|
-
};
|
|
728
|
-
if (metadata === null || metadata === void 0 ? void 0 : metadata.description) {
|
|
729
|
-
tt.properties[key].description = metadata === null || metadata === void 0 ? void 0 : metadata.description;
|
|
863
|
+
else if (metadataKey === 'not') {
|
|
864
|
+
tt.properties[key][metadataKey] = this.formatType(metadata[metadataKey]);
|
|
730
865
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
metadata === null || metadata === void 0 ? true : delete metadata.type;
|
|
736
|
-
if (currentType === 'array') {
|
|
737
|
-
isArray = true;
|
|
738
|
-
currentType = parseTypeSchema((_b = metadata === null || metadata === void 0 ? void 0 : metadata.items) === null || _b === void 0 ? void 0 : _b.type);
|
|
739
|
-
metadata === null || metadata === void 0 ? true : delete metadata.items.type;
|
|
740
|
-
}
|
|
741
|
-
if (metadata === null || metadata === void 0 ? void 0 : metadata.oneOf) {
|
|
742
|
-
tt.properties[key] = {
|
|
743
|
-
oneOf: [],
|
|
744
|
-
};
|
|
745
|
-
metadata === null || metadata === void 0 ? void 0 : metadata.oneOf.forEach((meta) => {
|
|
746
|
-
tt.properties[key].oneOf.push(this.parseSubPropertyType(meta));
|
|
747
|
-
});
|
|
748
|
-
metadata === null || metadata === void 0 ? true : delete metadata.oneOf;
|
|
749
|
-
continue;
|
|
750
|
-
}
|
|
751
|
-
if (core_1.Types.isClass(currentType)) {
|
|
752
|
-
this.parseClzz(currentType);
|
|
753
|
-
if (isArray) {
|
|
754
|
-
tt.properties[key] = {
|
|
755
|
-
type: 'array',
|
|
756
|
-
items: {
|
|
757
|
-
$ref: '#/components/schemas/' + (currentType === null || currentType === void 0 ? void 0 : currentType.name),
|
|
758
|
-
},
|
|
759
|
-
};
|
|
760
|
-
}
|
|
761
|
-
else {
|
|
762
|
-
tt.properties[key] = {
|
|
763
|
-
$ref: '#/components/schemas/' + (currentType === null || currentType === void 0 ? void 0 : currentType.name),
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
delete metadata.items;
|
|
767
|
-
}
|
|
768
|
-
else {
|
|
769
|
-
if (isArray) {
|
|
770
|
-
// 没有配置类型则认为自己配置了 items 内容
|
|
771
|
-
if (!currentType) {
|
|
772
|
-
if ((_c = metadata === null || metadata === void 0 ? void 0 : metadata.items) === null || _c === void 0 ? void 0 : _c['$ref']) {
|
|
773
|
-
metadata.items['$ref'] = parseTypeSchema(metadata.items['$ref']);
|
|
774
|
-
}
|
|
775
|
-
tt.properties[key] = {
|
|
776
|
-
type: 'array',
|
|
777
|
-
items: metadata === null || metadata === void 0 ? void 0 : metadata.items,
|
|
778
|
-
};
|
|
866
|
+
else if (metadataKey === 'type') {
|
|
867
|
+
this.formatType(metadata);
|
|
868
|
+
if (metadata.type) {
|
|
869
|
+
tt.properties[key].type = metadata.type;
|
|
779
870
|
}
|
|
780
|
-
|
|
781
|
-
tt.properties[key] =
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
871
|
+
if (metadata['$ref']) {
|
|
872
|
+
tt.properties[key].$ref = metadata['$ref'];
|
|
873
|
+
}
|
|
874
|
+
if (metadata.items) {
|
|
875
|
+
tt.properties[key].items = metadata.items;
|
|
876
|
+
}
|
|
877
|
+
if (metadata.format) {
|
|
878
|
+
tt.properties[key].format = metadata.format;
|
|
879
|
+
}
|
|
880
|
+
if (metadata.pattern) {
|
|
881
|
+
tt.properties[key].pattern = metadata.pattern;
|
|
882
|
+
}
|
|
883
|
+
if (metadata.enum) {
|
|
884
|
+
tt.properties[key].enum = metadata.enum;
|
|
787
885
|
}
|
|
788
|
-
delete metadata.items;
|
|
789
886
|
}
|
|
790
|
-
else if (
|
|
791
|
-
|
|
887
|
+
else if (metadataKey === 'items' ||
|
|
888
|
+
metadataKey === 'pattern' ||
|
|
889
|
+
metadataKey === 'format' ||
|
|
890
|
+
metadataKey === 'enum' ||
|
|
891
|
+
metadataKey === '$ref') {
|
|
892
|
+
// type 中已经处理
|
|
792
893
|
}
|
|
793
894
|
else {
|
|
794
|
-
tt.properties[key] =
|
|
795
|
-
type: currentType !== null && currentType !== void 0 ? currentType : (0, core_1.getPropertyType)(clzz.prototype, key).name,
|
|
796
|
-
format: metadata === null || metadata === void 0 ? void 0 : metadata.format,
|
|
797
|
-
};
|
|
798
|
-
// Date 类型支持
|
|
799
|
-
if (tt.properties[key].type === 'Date') {
|
|
800
|
-
tt.properties[key].type = 'string';
|
|
801
|
-
if (!tt.properties[key].format) {
|
|
802
|
-
tt.properties[key].format = 'date';
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
delete metadata.format;
|
|
895
|
+
tt.properties[key][metadataKey] = metadata[metadataKey];
|
|
806
896
|
}
|
|
807
897
|
}
|
|
808
|
-
Object.assign(tt.properties[key], metadata);
|
|
809
898
|
}
|
|
810
899
|
}
|
|
811
900
|
// just for test
|
|
@@ -937,7 +1026,7 @@ function convertSchemaType(value) {
|
|
|
937
1026
|
case 'String':
|
|
938
1027
|
return 'string';
|
|
939
1028
|
default:
|
|
940
|
-
return
|
|
1029
|
+
return 'object';
|
|
941
1030
|
}
|
|
942
1031
|
}
|
|
943
1032
|
function getNotEmptyValue(...args) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midwayjs/swagger",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.16.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"typings": "index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -10,23 +10,22 @@
|
|
|
10
10
|
"index.html"
|
|
11
11
|
],
|
|
12
12
|
"devDependencies": {
|
|
13
|
-
"@midwayjs/core": "^3.
|
|
14
|
-
"@midwayjs/koa": "^3.
|
|
15
|
-
"@midwayjs/mock": "^3.
|
|
16
|
-
"@midwayjs/validate": "^3.
|
|
17
|
-
"swagger-ui-dist": "5.
|
|
13
|
+
"@midwayjs/core": "^3.16.0",
|
|
14
|
+
"@midwayjs/koa": "^3.16.0",
|
|
15
|
+
"@midwayjs/mock": "^3.16.0",
|
|
16
|
+
"@midwayjs/validate": "^3.16.0",
|
|
17
|
+
"swagger-ui-dist": "5.17.4"
|
|
18
18
|
},
|
|
19
19
|
"author": "Kurten Chan <chinkurten@gmail.com>",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "tsc",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"cov": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand --coverage --forceExit"
|
|
23
|
+
"test": "../../node_modules/.bin/jest --runInBand",
|
|
24
|
+
"cov": "../../node_modules/.bin/jest --runInBand --coverage --forceExit"
|
|
26
25
|
},
|
|
27
26
|
"repository": {
|
|
28
27
|
"type": "git",
|
|
29
28
|
"url": "https://github.com/midwayjs/midway.git"
|
|
30
29
|
},
|
|
31
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "7e75fe1bdc9a6df2956f9c22e704063aaa022d76"
|
|
32
31
|
}
|