/
parameters.transform.ts
104 lines (96 loc) 路 3.57 KB
/
parameters.transform.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
94
95
96
97
98
99
100
101
102
103
104
import { OpenApiRequest, OpenApiRequestMetadata } from '../../framework/types';
import { ParametersParse } from './parameters.parse';
/**
* A class top arse incoing parameters and populate a list of request fields e.g. id and field types e.g. query
* whose value must later be parsed as a JSON object, JSON Exploded Object, JSON Array, or JSON Exploded Array
*/
export class ParametersTransform {
private parameters: ParametersParse;
private schema;
constructor(parseResult: ParametersParse, schema) {
this.parameters = parseResult;
this.schema = schema;
}
public applyExplodedJsonTransform(req: OpenApiRequest): void {
// forcing convert to object if scheme describes param as object + explode
// for easy validation, keep the schema but update whereabouts of its sub components
this.parameters.parseObjectExplode.forEach(item => {
if (req[item.reqField]) {
// check if there is at least one of the nested properties before create the parent
const atLeastOne = item.properties.some(p =>
req[item.reqField].hasOwnProperty(p),
);
if (atLeastOne) {
req[item.reqField][item.name] = {};
item.properties.forEach(property => {
if (req[item.reqField][property]) {
const type = this.schema.properties[item.reqField].properties[
item.name
].properties?.[property]?.type;
const value = req[item.reqField][property];
const coercedValue =
type === 'array' && !Array.isArray(value) ? [value] : value;
req[item.reqField][item.name][property] = coercedValue;
delete req[item.reqField][property];
}
});
}
}
});
}
public applyJsonTransform(req: OpenApiRequest): void {
/**
* support json in request params, query, headers and cookies
* like this filter={"type":"t-shirt","color":"blue"}
*
* https://swagger.io/docs/specification/describing-parameters/#schema-vs-content
*/
this.parameters.parseJson.forEach(item => {
if (req[item.reqField]?.[item.name]) {
try {
req[item.reqField][item.name] = JSON.parse(
req[item.reqField][item.name],
);
} catch (e) {
// NOOP If parsing failed but _should_ contain JSON, validator will catch it.
// May contain falsely flagged parameter (e.g. input was object OR string)
}
}
});
}
public applyJsonArrayTransform(req: OpenApiRequest): void {
/**
* array deserialization
* filter=foo,bar,baz
* filter=foo|bar|baz
* filter=foo%20bar%20baz
*/
this.parameters.parseArray.forEach(item => {
if (req[item.reqField]?.[item.name]) {
req[item.reqField][item.name] = req[item.reqField][item.name].split(
item.delimiter,
);
}
});
}
public applyExplodedJsonArrayTransform(req: OpenApiRequest): void {
/**
* forcing convert to array if scheme describes param as array + explode
*/
this.parameters.parseArrayExplode.forEach(item => {
if (
req[item.reqField]?.[item.name] &&
!(req[item.reqField][item.name] instanceof Array)
) {
req[item.reqField][item.name] = [req[item.reqField][item.name]];
}
});
}
public applyPathTransform(req: OpenApiRequest): void {
const openapi = <OpenApiRequestMetadata>req.openapi;
const shouldUpdatePathParams = Object.keys(openapi.pathParams).length > 0;
if (shouldUpdatePathParams) {
req.params = openapi.pathParams ?? req.params;
}
}
}