Skip to content

Commit 91da53b

Browse files
authored
Merge pull request #692 from postmanlabs/feature/validate-transactions-v2-update-path-logic
Rewrote the logic to generate the paths computation for folders for folder strategy paths
2 parents c959595 + 8555758 commit 91da53b

File tree

7 files changed

+472
-5389
lines changed

7 files changed

+472
-5389
lines changed

libV2/helpers/collection/generateSkeletionTreeFromOpenAPI.js

Lines changed: 244 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ let _ = require('lodash'),
1414
trace: true
1515
},
1616

17-
_generateTreeFromPaths = function (openapi, { includeDeprecated }) {
17+
18+
_generateTreeFromPathsV2 = function (openapi, { includeDeprecated }) {
1819
/**
1920
* We will create a unidirectional graph
2021
*/
@@ -26,13 +27,32 @@ let _ = require('lodash'),
2627
meta: {}
2728
});
2829

29-
_.forEach(openapi.paths, function (methods, path) {
30-
let pathSplit = path === '/' ? [path] : _.compact(path.split('/'));
30+
/**
31+
* Get all the paths sorted in desc order.
32+
*/
33+
const paths = Object.keys(openapi.paths).sort((a, b) => {
34+
return (a > b ? -1 : 1);
35+
});
3136

32-
// if after path split we just have one entry
33-
// that means no folders need to be generated.
34-
// check for all the methods inside it and expand.
37+
if (_.isEmpty(paths)) {
38+
return tree;
39+
}
40+
41+
_.forEach(paths, function (completePath) {
42+
let pathSplit = completePath === '/' ? [completePath] : _.compact(completePath.split('/'));
43+
44+
/**
45+
* /user
46+
* /team
47+
* /hi
48+
* /bye
49+
*
50+
* In this scenario, always create a base folder for the path
51+
* and then add and link the request inside the created folder.
52+
*/
3553
if (pathSplit.length === 1) {
54+
let methods = openapi.paths[completePath];
55+
3656
_.forEach(methods, function (data, method) {
3757
if (!ALLOWED_HTTP_METHODS[method]) {
3858
return;
@@ -46,94 +66,254 @@ let _ = require('lodash'),
4666
return;
4767
}
4868

49-
tree.setNode(`path:${pathSplit[0]}:${method}`, {
69+
if (!tree.hasNode(`path:folder:${pathSplit[0]}`)) {
70+
tree.setNode(`path:folder:${pathSplit[0]}`, {
71+
type: 'folder',
72+
meta: {
73+
name: pathSplit[0],
74+
path: pathSplit[0],
75+
pathIdentifier: pathSplit[0]
76+
},
77+
data: {}
78+
});
79+
80+
tree.setEdge('root:collection', `path:folder:${pathSplit[0]}`);
81+
}
82+
83+
tree.setNode(`path:request:${pathSplit[0]}:${method}`, {
5084
type: 'request',
85+
data: {},
5186
meta: {
52-
path: path,
87+
path: completePath,
5388
method: method,
5489
pathIdentifier: pathSplit[0]
55-
},
56-
data: {}
90+
}
5791
});
5892

59-
tree.setEdge('root:collection', `path:${pathSplit[0]}:${method}`);
93+
tree.setEdge(`path:folder:${pathSplit[0]}`, `path:request:${pathSplit[0]}:${method}`);
6094
});
6195
}
6296

6397
else {
64-
_.forEach(pathSplit, function (p, index) {
98+
_.forEach(pathSplit, function (path, index) {
6599
let previousPathIdentified = pathSplit.slice(0, index).join('/'),
66100
pathIdentifier = pathSplit.slice(0, index + 1).join('/');
67101

68-
/**
69-
* Always first try to find the node if it already exists.
70-
* if yes, bail out nothing is needed to be done.
71-
*/
72-
if (tree.hasNode(`path:${pathIdentifier}`)) {
73-
return;
102+
if ((index + 1) === pathSplit.length) {
103+
let methods = openapi.paths[completePath];
104+
105+
_.forEach(methods, function (data, method) {
106+
if (!ALLOWED_HTTP_METHODS[method]) {
107+
return;
108+
}
109+
110+
/**
111+
* include deprecated handling.
112+
* If true, add in the postman collection. If false ignore the request.
113+
*/
114+
if (!includeDeprecated && data.deprecated) {
115+
return;
116+
}
117+
118+
/**
119+
* If it is the last node,
120+
* it might happen that this exists as a folder.
121+
*
122+
* If yes add a request inside that folder else
123+
* add as a request on the previous path idendified which will be a folder.
124+
*/
125+
if (!tree.hasNode(`path:folder:${pathIdentifier}`)) {
126+
tree.setNode(`path:folder:${pathIdentifier}`, {
127+
type: 'folder',
128+
meta: {
129+
name: path,
130+
path: path,
131+
pathIdentifier: pathIdentifier
132+
},
133+
data: {}
134+
});
135+
136+
tree.setEdge(index === 0 ? 'root:collection' : `path:folder:${previousPathIdentified}`,
137+
`path:folder:${pathIdentifier}`);
138+
}
139+
140+
tree.setNode(`path:request:${pathIdentifier}:${method}`, {
141+
type: 'request',
142+
data: {},
143+
meta: {
144+
path: completePath,
145+
method: method,
146+
pathIdentifier: pathIdentifier
147+
}
148+
});
149+
150+
tree.setEdge(`path:folder:${pathIdentifier}`, `path:request:${pathIdentifier}:${method}`);
151+
});
74152
}
75153

76154
else {
77-
tree.setNode(`path:${pathIdentifier}`, {
155+
tree.setNode(`path:folder:${pathIdentifier}`, {
78156
type: 'folder',
79157
meta: {
80-
name: p,
81-
path: p,
158+
name: path,
159+
path: path,
82160
pathIdentifier: pathIdentifier
83161
},
84162
data: {}
85163
});
86164

87-
/**
88-
* If index is 0, this means that we are on the first level.
89-
* Hence it is folder/request to be added on the first level
90-
*
91-
* If after the split we have more than one paths, then we need
92-
* to add to the previous node.
93-
*/
94-
tree.setEdge(index === 0 ? 'root:collection' : `path:${previousPathIdentified}`, `path:${pathIdentifier}`);
95-
}
96-
});
97-
98-
/**
99-
* Now for all the methods present in the path, add the request nodes.
100-
*/
101-
102-
_.forEach(methods, function (data, method) {
103-
if (!ALLOWED_HTTP_METHODS[method]) {
104-
return;
105-
}
106-
107-
/**
108-
* include deprecated handling.
109-
* If true, add in the postman collection. If false ignore the request.
110-
*/
111-
if (!includeDeprecated && data.deprecated) {
112-
return;
165+
tree.setEdge(index === 0 ? 'root:collection' : `path:folder:${previousPathIdentified}`,
166+
`path:folder:${pathIdentifier}`);
113167
}
114-
115-
// join till the last path i.e. the folder.
116-
let previousPathIdentified = pathSplit.slice(0, (pathSplit.length)).join('/'),
117-
pathIdentifier = `${pathSplit.join('/')}:${method}`;
118-
119-
tree.setNode(`path:${pathIdentifier}`, {
120-
type: 'request',
121-
data: {},
122-
meta: {
123-
path: path,
124-
method: method,
125-
pathIdentifier: pathIdentifier
126-
}
127-
});
128-
129-
tree.setEdge(`path:${previousPathIdentified}`, `path:${pathIdentifier}`);
130168
});
131169
}
132170
});
133171

134172
return tree;
135173
},
136174

175+
// _generateTreeFromPaths = function (openapi, { includeDeprecated }) {
176+
// /**
177+
// * We will create a unidirectional graph
178+
// */
179+
// let tree = new Graph();
180+
181+
// tree.setNode('root:collection', {
182+
// type: 'collection',
183+
// data: {},
184+
// meta: {}
185+
// });
186+
187+
// _.forEach(openapi.paths, function (methods, path) {
188+
// let pathSplit = path === '/' ? [path] : _.compact(path.split('/'));
189+
190+
// // if after path split we just have one entry
191+
// // that means no folders need to be generated.
192+
// // check for all the methods inside it and expand.
193+
// if (pathSplit.length === 1) {
194+
// /**
195+
// * Always first try to find the node if it already exists.
196+
// * if yes, bail out nothing is needed to be done.
197+
// *
198+
// * if the path length is 1, then also generate
199+
// * the folder otherwise /pet and /pet/:id will never be in same folder.
200+
// */
201+
// // if (!tree.hasNode(`path:${pathSplit[0]}`)) {
202+
// // tree.setNode(`path:${pathSplit[0]}`, {
203+
// // type: 'folder',
204+
// // meta: {
205+
// // name: pathSplit[0],
206+
// // path: pathSplit[0],
207+
// // pathIdentifier: pathIdentifier
208+
// // },
209+
// // data: {}
210+
// // });
211+
212+
// // tree.setEdge('root:collection', `path:${pathSplit[0]}`);
213+
// // }
214+
215+
216+
// _.forEach(methods, function (data, method) {
217+
// if (!ALLOWED_HTTP_METHODS[method]) {
218+
// return;
219+
// }
220+
221+
// /**
222+
// * include deprecated handling.
223+
// * If true, add in the postman collection. If false ignore the request.
224+
// */
225+
// if (!includeDeprecated && data.deprecated) {
226+
// return;
227+
// }
228+
229+
// tree.setNode(`path:${pathSplit[0]}:${method}`, {
230+
// type: 'request',
231+
// meta: {
232+
// path: path,
233+
// method: method,
234+
// pathIdentifier: pathSplit[0]
235+
// },
236+
// data: {}
237+
// });
238+
239+
// tree.setEdge(`path:${pathSplit[0]}`, `path:${pathSplit[0]}:${method}`);
240+
// });
241+
// }
242+
243+
// else {
244+
// _.forEach(pathSplit, function (p, index) {
245+
// let previousPathIdentified = pathSplit.slice(0, index).join('/'),
246+
// pathIdentifier = pathSplit.slice(0, index + 1).join('/');
247+
248+
// /**
249+
// * Always first try to find the node if it already exists.
250+
// * if yes, bail out nothing is needed to be done.
251+
// */
252+
// if (tree.hasNode(`path:${pathIdentifier}`)) {
253+
// return;
254+
// }
255+
256+
// else {
257+
// tree.setNode(`path:${pathIdentifier}`, {
258+
// type: 'folder',
259+
// meta: {
260+
// name: p,
261+
// path: p,
262+
// pathIdentifier: pathIdentifier
263+
// },
264+
// data: {}
265+
// });
266+
267+
// /**
268+
// * If index is 0, this means that we are on the first level.
269+
// * Hence it is folder/request to be added on the first level
270+
// *
271+
// * If after the split we have more than one paths, then we need
272+
// * to add to the previous node.
273+
// */
274+
// tree.setEdge(index === 0 ? 'root:collection' : `path:${previousPathIdentified}`, `path:${pathIdentifier}`);
275+
// }
276+
// });
277+
278+
// /**
279+
// * Now for all the methods present in the path, add the request nodes.
280+
// */
281+
282+
// _.forEach(methods, function (data, method) {
283+
// if (!ALLOWED_HTTP_METHODS[method]) {
284+
// return;
285+
// }
286+
287+
// /**
288+
// * include deprecated handling.
289+
// * If true, add in the postman collection. If false ignore the request.
290+
// */
291+
// if (!includeDeprecated && data.deprecated) {
292+
// return;
293+
// }
294+
295+
// // join till the last path i.e. the folder.
296+
// let previousPathIdentified = pathSplit.slice(0, (pathSplit.length)).join('/'),
297+
// pathIdentifier = `${pathSplit.join('/')}:${method}`;
298+
299+
// tree.setNode(`path:${pathIdentifier}`, {
300+
// type: 'request',
301+
// data: {},
302+
// meta: {
303+
// path: path,
304+
// method: method,
305+
// pathIdentifier: pathIdentifier
306+
// }
307+
// });
308+
309+
// tree.setEdge(`path:${previousPathIdentified}`, `path:${pathIdentifier}`);
310+
// });
311+
// }
312+
// });
313+
314+
// return tree;
315+
// },
316+
137317
_generateTreeFromTags = function (openapi, { includeDeprecated }) {
138318
let tree = new Graph(),
139319

@@ -295,7 +475,7 @@ module.exports = function (openapi, { folderStrategy, includeWebhooks, includeDe
295475
break;
296476

297477
case 'paths':
298-
skeletonTree = _generateTreeFromPaths(openapi, { includeDeprecated });
478+
skeletonTree = _generateTreeFromPathsV2(openapi, { includeDeprecated });
299479
break;
300480

301481
default:

0 commit comments

Comments
 (0)