-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.js
167 lines (156 loc) · 5.79 KB
/
utils.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
167
const fs = require('fs');
const yaml = require('js-yaml');
/**
* Alter any methods of any paths matching a pattern to have only one tag
* @param {string} doc the yml object
* @param {string} pattern a search string for paths
* @param {string} tag the tag to set for each method in matching paths
* @return {any} a new object representation of yml
*/
const setTag = (doc, pattern, tag) => {
const result = { ...doc }
Object.keys(result.paths).filter(path => path.startsWith(pattern)).forEach(
path => {
const pathObj = result.paths[path];
Object.keys(pathObj).forEach(
method => {
pathObj[method].tags = [ tag ]
}
)
}
)
return result;
}
/**
* Recursively traverse a yml document and apply a transformation function
* @param {any} doc Object to recurse through
* @param {func} transform A transformation function to apply in place
*/
const recurse = (doc, transform) => {
if (doc === null) {
return;
}
// Apply transform function
transform(doc);
if (Array.isArray(doc)) {
doc.forEach(
element => recurse(element, transform)
)
} else if (typeof doc === "object") {
Object.keys(doc).forEach(
key => recurse(doc[key], transform)
)
}
}
/**
* Replaces schema names, including refs
* @param {any} doc the yml object
* @param {string} oldSchema the original schema name
* @param {string} newSchema the new name for the schema
*/
const renameSchema = (doc, oldSchema, newSchema) => {
const result = { ...doc }
const transform = (obj) => {
if (obj instanceof Array || !(obj instanceof Object)) {
return;
}
Object.keys(obj).forEach(
key => {
if (key === '$ref') {
if (obj[key] === `#/components/schemas/${oldSchema}`) {
obj[key] = `#/components/schemas/${newSchema}`;
}
}
}
)
}
recurse(result, transform);
result.components.schemas[newSchema] = { ...result.components.schemas[oldSchema] }
delete result.components.schemas[oldSchema];
return result;
}
/**
* Prepend all paths with a prefix
* @param {any} doc
* @param {string} prefix
*/
const prependPaths = (doc, prefix) => {
const result = { ...doc };
Object.keys(result.paths).forEach(
path => {
result.paths[`${prefix}${path}`] = { ...result.paths[path] };
delete result.paths[path]
}
)
return result;
}
/**
* Expand BasicResponse discriminators into explicit type
* @param {any} doc
*/
const expandBasicResponses = (doc) => {
const result = { ...doc }
Object.keys(result.paths).forEach(
path => {
const pathRef = result.paths[path];
Object.keys(pathRef).forEach(
method => {
const methodRef = pathRef[method];
Object.keys(methodRef.responses).forEach(
status => {
const statusRef = methodRef.responses[status];
const schemaRef = statusRef['content'][Object.keys(statusRef.content)[0]]['schema'];
if ('allOf' in schemaRef &&
'$ref' in schemaRef['allOf'][0] &&
schemaRef['allOf'][0]["$ref"] === '#/components/schemas/BasicResponse') {
const spliced = methodRef.operationId.split('_').reduce(
(accumulator, current) => {
return accumulator
+ current.charAt(0).toUpperCase()
+ current.slice(1);
}
)
const newSchema = "Resp" + spliced.charAt(0).toUpperCase() + spliced.slice(1);
result.components.schemas[newSchema] = JSON.parse(JSON.stringify(result.components.schemas.BasicResponse))
result.components.schemas[newSchema].properties = {
...result.components.schemas[newSchema].properties,
...schemaRef.properties
}
statusRef['content']['application/json']['schema'] = {
"$ref": `#/components/schemas/${newSchema}`
}
}
}
)
}
)
}
)
return result;
}
/**
* Copy a service's yml file directly to the transformed_openapi directory
* if no transformations are required
* @param {string} service service name
*/
const copy = (service) => {
fs.copyFileSync(`./services/${service}/spec.yml`, `./services/${service}/transformed_spec.yml`);
}
/**
* Load a service's yml file and return it as a
* @param {string} service service name
* @return {any} object representation of yml
*/
const read = (service) => {
return yaml.load(fs.readFileSync(`./services/${service}/spec.yml`, 'utf8'));
}
const write = (doc, service) => {
fs.writeFileSync(`./services/${service}/transformed_spec.yml`, yaml.dump(doc));
}
module.exports.setTag = setTag;
module.exports.copy = copy;
module.exports.read = read;
module.exports.write = write;
module.exports.renameSchema = renameSchema;
module.exports.prependPaths = prependPaths;
module.exports.expandBasicResponses = expandBasicResponses;