oas-toolkit 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components.js +71 -3
- package/components.test.js +143 -0
- package/package.json +2 -1
package/components.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
const traverse = require("traverse");
|
|
2
2
|
const isEqual = require("lodash.isequal");
|
|
3
3
|
const difference = require("lodash.difference");
|
|
4
|
+
const intersection = require("lodash.intersection");
|
|
4
5
|
|
|
5
6
|
function removeUnusedComponents(oas) {
|
|
6
7
|
const used = getReferencedComponents(oas);
|
|
7
8
|
const defined = getDefinedComponents(oas);
|
|
8
|
-
const unused = getUnusedComponents(defined, used);
|
|
9
|
+
const unused = getUnusedComponents(defined, used, oas);
|
|
9
10
|
|
|
10
11
|
const result = removeSpecifiedComponents(oas, unused);
|
|
11
12
|
|
|
@@ -18,6 +19,20 @@ function removeUnusedComponents(oas) {
|
|
|
18
19
|
return removeUnusedComponents(result);
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
function getReferencesToComponent(oas, component) {
|
|
23
|
+
return traverse(oas).reduce(function (acc, x) {
|
|
24
|
+
if (
|
|
25
|
+
this.isLeaf &&
|
|
26
|
+
this.key == "$ref" &&
|
|
27
|
+
x == `#/${component.replace(/\./g, "/")}`
|
|
28
|
+
) {
|
|
29
|
+
acc.push(this.path.slice(0, 3).join("."));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return acc;
|
|
33
|
+
}, []);
|
|
34
|
+
}
|
|
35
|
+
|
|
21
36
|
function removeSpecifiedComponents(oas, unused) {
|
|
22
37
|
oas = traverse(oas).clone();
|
|
23
38
|
return traverse(oas).forEach(function (x) {
|
|
@@ -75,8 +90,61 @@ function getDefinedComponents(oas) {
|
|
|
75
90
|
}, []);
|
|
76
91
|
}
|
|
77
92
|
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
// This is a horrible global hack, but it works
|
|
94
|
+
const referencesTo = {};
|
|
95
|
+
function getUnusedComponents(all, referenced, oas) {
|
|
96
|
+
const unused = difference(all, referenced);
|
|
97
|
+
|
|
98
|
+
if (!oas) {
|
|
99
|
+
return unused;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// If we have a component that is only referenced by itself, it's unused
|
|
103
|
+
const used = intersection(all, referenced);
|
|
104
|
+
for (let component of used) {
|
|
105
|
+
if (component.startsWith("components.securitySchemes")) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const references = getReferencesToComponent(oas, component);
|
|
110
|
+
if (references.length == 1 && references[0] === component) {
|
|
111
|
+
unused.push(component);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// If there's a circular dependency and nothing else, it can be removed
|
|
115
|
+
for (let ref of references) {
|
|
116
|
+
referencesTo[ref] = getRecursiveReferencesToComponent(oas, ref);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let shouldRemove = true;
|
|
120
|
+
for (let ref of references) {
|
|
121
|
+
if (!isEqual(referencesTo[component], referencesTo[ref])) {
|
|
122
|
+
shouldRemove = false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (shouldRemove) {
|
|
126
|
+
unused.push(component);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return unused;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function getRecursiveReferencesToComponent(oas, component, originalComponents) {
|
|
133
|
+
if (!originalComponents) {
|
|
134
|
+
originalComponents = [];
|
|
135
|
+
}
|
|
136
|
+
originalComponents.push(component);
|
|
137
|
+
let refs = getReferencesToComponent(oas, component);
|
|
138
|
+
for (const ref of refs) {
|
|
139
|
+
if (!originalComponents.includes(ref)) {
|
|
140
|
+
refs = refs.concat(
|
|
141
|
+
getRecursiveReferencesToComponent(oas, ref, originalComponents)
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
refs.sort();
|
|
146
|
+
|
|
147
|
+
return refs;
|
|
80
148
|
}
|
|
81
149
|
|
|
82
150
|
module.exports = {
|
package/components.test.js
CHANGED
|
@@ -253,6 +253,149 @@ describe("#components", () => {
|
|
|
253
253
|
});
|
|
254
254
|
});
|
|
255
255
|
|
|
256
|
+
it("Removes schemas that are circular (self reference)", () => {
|
|
257
|
+
expect(
|
|
258
|
+
c.removeUnusedComponents({
|
|
259
|
+
info: { title: "One" },
|
|
260
|
+
components: {
|
|
261
|
+
schemas: {
|
|
262
|
+
MySchema: {
|
|
263
|
+
type: "object",
|
|
264
|
+
properties: {
|
|
265
|
+
subSchema: {
|
|
266
|
+
$ref: "#/components/schemas/MySchema",
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
})
|
|
273
|
+
).toEqual({
|
|
274
|
+
info: { title: "One" },
|
|
275
|
+
components: {},
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it("Removes schemas that are circular (loop)", () => {
|
|
280
|
+
expect(
|
|
281
|
+
c.removeUnusedComponents({
|
|
282
|
+
info: { title: "One" },
|
|
283
|
+
components: {
|
|
284
|
+
schemas: {
|
|
285
|
+
SchemaA: {
|
|
286
|
+
properties: {
|
|
287
|
+
subSchema: {
|
|
288
|
+
$ref: "#/components/schemas/SchemaC",
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
SchemaB: {
|
|
293
|
+
properties: {
|
|
294
|
+
subSchema: {
|
|
295
|
+
$ref: "#/components/schemas/SchemaA",
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
SchemaC: {
|
|
300
|
+
properties: {
|
|
301
|
+
subSchema: {
|
|
302
|
+
$ref: "#/components/schemas/SchemaB",
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
})
|
|
309
|
+
).toEqual({
|
|
310
|
+
info: { title: "One" },
|
|
311
|
+
components: {},
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it("Does not remove circular schemas that are also referenced elsewhere", () => {
|
|
316
|
+
expect(
|
|
317
|
+
c.removeUnusedComponents({
|
|
318
|
+
info: { title: "One" },
|
|
319
|
+
paths: {
|
|
320
|
+
"/foo": {
|
|
321
|
+
get: {
|
|
322
|
+
responses: {
|
|
323
|
+
200: {
|
|
324
|
+
content: {
|
|
325
|
+
"application/json": {
|
|
326
|
+
schema: {
|
|
327
|
+
$ref: "#/components/schemas/AnotherSchema",
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
components: {
|
|
337
|
+
schemas: {
|
|
338
|
+
MySchema: {
|
|
339
|
+
type: "object",
|
|
340
|
+
properties: {
|
|
341
|
+
subSchema: {
|
|
342
|
+
$ref: "#/components/schemas/MySchema",
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
AnotherSchema: {
|
|
347
|
+
type: "object",
|
|
348
|
+
properties: {
|
|
349
|
+
Foo: {
|
|
350
|
+
$ref: "#/components/schemas/MySchema",
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
})
|
|
357
|
+
).toEqual({
|
|
358
|
+
info: { title: "One" },
|
|
359
|
+
paths: {
|
|
360
|
+
"/foo": {
|
|
361
|
+
get: {
|
|
362
|
+
responses: {
|
|
363
|
+
200: {
|
|
364
|
+
content: {
|
|
365
|
+
"application/json": {
|
|
366
|
+
schema: {
|
|
367
|
+
$ref: "#/components/schemas/AnotherSchema",
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
components: {
|
|
377
|
+
schemas: {
|
|
378
|
+
MySchema: {
|
|
379
|
+
type: "object",
|
|
380
|
+
properties: {
|
|
381
|
+
subSchema: {
|
|
382
|
+
$ref: "#/components/schemas/MySchema",
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
AnotherSchema: {
|
|
387
|
+
type: "object",
|
|
388
|
+
properties: {
|
|
389
|
+
Foo: {
|
|
390
|
+
$ref: "#/components/schemas/MySchema",
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
|
|
256
399
|
it("removes unused security schemes", () => {
|
|
257
400
|
const securityOas = {
|
|
258
401
|
info: { title: "One" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oas-toolkit",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"jsonpath-plus": "^7.2.0",
|
|
22
22
|
"lodash.difference": "^4.5.0",
|
|
23
23
|
"lodash.get": "^4.4.2",
|
|
24
|
+
"lodash.intersection": "^4.4.0",
|
|
24
25
|
"lodash.isequal": "^4.5.0",
|
|
25
26
|
"lodash.uniqwith": "^4.5.0",
|
|
26
27
|
"mergician": "^1.1.0",
|