/
api-parameters.explorer.ts
93 lines (87 loc) · 3.08 KB
/
api-parameters.explorer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { Type } from '@nestjs/common';
import { assign, find, isNil, map, omitBy, some, unionWith } from 'lodash';
import { DECORATORS } from '../constants';
import { SchemaObject } from '../interfaces/open-api-spec.interface';
import { ModelPropertiesAccessor } from '../services/model-properties-accessor';
import {
ParameterMetadataAccessor,
ParamWithTypeMetadata
} from '../services/parameter-metadata-accessor';
import { ParametersMetadataMapper } from '../services/parameters-metadata-mapper';
import { SchemaObjectFactory } from '../services/schema-object-factory';
import { SwaggerTypesMapper } from '../services/swagger-types-mapper';
import { GlobalParametersStorage } from '../storages/global-parameters.storage';
const parameterMetadataAccessor = new ParameterMetadataAccessor();
const modelPropertiesAccessor = new ModelPropertiesAccessor();
const parametersMetadataMapper = new ParametersMetadataMapper(
modelPropertiesAccessor
);
const swaggerTypesMapper = new SwaggerTypesMapper();
const schemaObjectFactory = new SchemaObjectFactory(
modelPropertiesAccessor,
swaggerTypesMapper
);
export const exploreApiParametersMetadata = (
schemas: Record<string, SchemaObject>,
instance: object,
prototype: Type<unknown>,
method: Function
) => {
const explicitParameters: any[] = Reflect.getMetadata(
DECORATORS.API_PARAMETERS,
method
);
const globalParameters = GlobalParametersStorage.getAll();
const parametersMetadata = parameterMetadataAccessor.explore(
instance,
prototype,
method
);
const noExplicitAndGlobalMetadata =
isNil(explicitParameters) && isNil(globalParameters);
if (noExplicitAndGlobalMetadata && isNil(parametersMetadata)) {
return undefined;
}
const reflectedParametersAsProperties =
parametersMetadataMapper.transformModelToProperties(
parametersMetadata || {}
);
let properties = reflectedParametersAsProperties;
if (!noExplicitAndGlobalMetadata) {
const mergeImplicitAndExplicit = (item: ParamWithTypeMetadata) =>
assign(item, find(explicitParameters, ['name', item.name]));
properties = removeBodyMetadataIfExplicitExists(
properties,
explicitParameters
);
properties = map(properties, mergeImplicitAndExplicit);
properties = unionWith(
properties,
explicitParameters,
globalParameters,
(arrVal, othVal) => {
return arrVal.name === othVal.name && arrVal.in === othVal.in;
}
);
}
const paramsWithDefinitions = schemaObjectFactory.createFromModel(
properties,
schemas
);
const parameters = swaggerTypesMapper.mapParamTypes(paramsWithDefinitions);
return parameters ? { parameters } : undefined;
};
function removeBodyMetadataIfExplicitExists(
properties: ParamWithTypeMetadata[],
explicitParams: any[]
) {
const isBodyReflected = some(properties, (p) => p.in === 'body');
const isBodyDefinedExplicitly = some(explicitParams, (p) => p.in === 'body');
if (isBodyReflected && isBodyDefinedExplicitly) {
return omitBy(
properties,
(p) => p.in === 'body'
) as ParamWithTypeMetadata[];
}
return properties;
}