-
Notifications
You must be signed in to change notification settings - Fork 229
/
specification.js
166 lines (154 loc) · 4.66 KB
/
specification.js
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* eslint no-param-reassign: 0 */
/**
* Checks if tag is already contained withing target.
* The tag is an object of type http://swagger.io/specification/#tagObject
* The target, is the part of the swagger specification that holds all tags.
* @param {object} target - Swagger object place to include the tags data.
* @param {object} tag - Swagger tag object to be included.
* @returns {boolean} Does tag is already present in target
*/
function tagDuplicated(target, tag) {
// Check input is workable.
if (target && target.length && tag) {
for (let i = 0; i < target.length; i += 1) {
const targetTag = target[i];
// The name of the tag to include already exists in the taget.
// Therefore, it's not necessary to be added again.
if (targetTag.name === tag.name) {
return true;
}
}
}
// This will indicate that `tag` is not present in `target`.
return false;
}
/**
* Adds the tags property to a swagger object.
* @param {object} conf - Flexible configuration.
*/
function attachTags(conf) {
const { tag, swaggerObject, propertyName } = conf;
// Correct deprecated property.
if (propertyName === 'tag') {
conf.propertyName = 'tags';
}
if (Array.isArray(tag)) {
for (let i = 0; i < tag.length; i += 1) {
if (!tagDuplicated(swaggerObject[propertyName], tag[i])) {
swaggerObject[propertyName].push(tag[i]);
}
}
} else if (!tagDuplicated(swaggerObject[propertyName], tag)) {
swaggerObject[propertyName].push(tag);
}
}
/**
* List of deprecated or wrong swagger schema properties in singular.
* @returns {array} The list of deprecated property names.
*/
function getSwaggerSchemaWrongProperties() {
return [
'consume',
'produce',
'path',
'tag',
'definition',
'securityDefinition',
'scheme',
'response',
'parameter',
];
}
/**
* Makes a deprecated property plural if necessary.
* @param {string} propertyName - The swagger property name to check.
* @returns {string} The updated propertyName if neccessary.
*/
function correctSwaggerKey(propertyName) {
const wrong = getSwaggerSchemaWrongProperties();
if (wrong.indexOf(propertyName) > 0) {
// Returns the corrected property name.
return `${propertyName}s`;
}
return propertyName;
}
/**
* Handles swagger propertyName in pathObject context for swaggerObject.
* @param {object} swaggerObject - The swagger object to update.
* @param {object} pathObject - The input context of an item for swaggerObject.
* @param {string} propertyName - The property to handle.
*/
function organizeSwaggerProperties(swaggerObject, pathObject, propertyName) {
const simpleProperties = [
'component',
'components',
'consume',
'consumes',
'produce',
'produces',
'path',
'paths',
'schema',
'schemas',
'securityDefinition',
'securityDefinitions',
'response',
'responses',
'parameter',
'parameters',
'definition',
'definitions',
];
// Common properties.
if (simpleProperties.indexOf(propertyName) !== -1) {
const keyName = correctSwaggerKey(propertyName);
const definitionNames = Object.getOwnPropertyNames(
pathObject[propertyName]
);
for (let k = 0; k < definitionNames.length; k += 1) {
const definitionName = definitionNames[k];
swaggerObject[keyName][definitionName] = {
...swaggerObject[keyName][definitionName],
...pathObject[propertyName][definitionName],
};
}
// Tags.
} else if (propertyName === 'tag' || propertyName === 'tags') {
const tag = pathObject[propertyName];
attachTags({
tag,
swaggerObject,
propertyName,
});
// Paths.
} else {
swaggerObject.paths[propertyName] = {
...swaggerObject.paths[propertyName],
...pathObject[propertyName],
};
}
}
/**
* Adds the data in to the swagger object.
* @param {object} swaggerObject - Swagger object which will be written to
* @param {object[]} data - objects of parsed swagger data from yml or jsDoc
* comments
*/
function addDataToSwaggerObject(swaggerObject, data) {
if (!swaggerObject || !data) {
throw new Error('swaggerObject and data are required!');
}
for (let i = 0; i < data.length; i += 1) {
const pathObject = data[i];
const propertyNames = Object.getOwnPropertyNames(pathObject);
// Iterating the properties of the a given pathObject.
for (let j = 0; j < propertyNames.length; j += 1) {
const propertyName = propertyNames[j];
// Do what's necessary to organize the end specification.
organizeSwaggerProperties(swaggerObject, pathObject, propertyName);
}
}
}
module.exports = {
addDataToSwaggerObject,
};