oas-toolkit 0.7.4 → 0.7.6
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 +60 -0
- package/components.test.js +37 -1
- package/merger.test.js +1 -1
- package/package.json +1 -1
package/components.js
CHANGED
|
@@ -2,6 +2,7 @@ const traverse = require("traverse");
|
|
|
2
2
|
const isEqual = require("lodash.isequal");
|
|
3
3
|
const difference = require("lodash.difference");
|
|
4
4
|
const intersection = require("lodash.intersection");
|
|
5
|
+
const uniqWith = require("lodash.uniqwith");
|
|
5
6
|
|
|
6
7
|
function removeUnusedComponents(oas) {
|
|
7
8
|
const used = getReferencedComponents(oas);
|
|
@@ -90,20 +91,79 @@ function getDefinedComponents(oas) {
|
|
|
90
91
|
}, []);
|
|
91
92
|
}
|
|
92
93
|
|
|
94
|
+
// This is a horrible global hack, but it works
|
|
95
|
+
const referencesTo = {};
|
|
93
96
|
function getUnusedComponents(all, referenced, oas) {
|
|
94
97
|
const unused = difference(all, referenced);
|
|
95
98
|
|
|
99
|
+
if (!oas) {
|
|
100
|
+
return unused;
|
|
101
|
+
}
|
|
102
|
+
|
|
96
103
|
// If we have a component that is only referenced by itself, it's unused
|
|
97
104
|
const used = intersection(all, referenced);
|
|
98
105
|
for (let component of used) {
|
|
106
|
+
if (component.startsWith("components.securitySchemes")) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
|
|
99
110
|
const references = getReferencesToComponent(oas, component);
|
|
100
111
|
if (references.length == 1 && references[0] === component) {
|
|
101
112
|
unused.push(component);
|
|
102
113
|
}
|
|
114
|
+
|
|
115
|
+
// If there's a circular dependency and nothing else, it can be removed
|
|
116
|
+
for (let ref of references) {
|
|
117
|
+
referencesTo[ref] = getRecursiveReferencesToComponent(oas, ref);
|
|
118
|
+
// Add all the references for each reference to build a complete list
|
|
119
|
+
referencesTo[ref] = referencesTo[ref].concat(
|
|
120
|
+
referencesTo[ref].flatMap((r) => {
|
|
121
|
+
if (!referencesTo[r]) {
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
return referencesTo[r];
|
|
125
|
+
})
|
|
126
|
+
);
|
|
127
|
+
referencesTo[ref] = uniqWith(referencesTo[ref], isEqual);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let shouldRemove = true;
|
|
131
|
+
for (let ref of references) {
|
|
132
|
+
if (!isEqual(referencesTo[component], referencesTo[ref])) {
|
|
133
|
+
shouldRemove = false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (shouldRemove) {
|
|
137
|
+
unused.push(component);
|
|
138
|
+
}
|
|
103
139
|
}
|
|
104
140
|
return unused;
|
|
105
141
|
}
|
|
106
142
|
|
|
143
|
+
const recursiveCache = {};
|
|
144
|
+
function getRecursiveReferencesToComponent(oas, component, originalComponents) {
|
|
145
|
+
if (recursiveCache[component]) {
|
|
146
|
+
return recursiveCache[component];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (!originalComponents) {
|
|
150
|
+
originalComponents = [];
|
|
151
|
+
}
|
|
152
|
+
originalComponents.push(component);
|
|
153
|
+
let refs = getReferencesToComponent(oas, component);
|
|
154
|
+
for (const ref of refs) {
|
|
155
|
+
if (!originalComponents.includes(ref)) {
|
|
156
|
+
refs = refs.concat(
|
|
157
|
+
getRecursiveReferencesToComponent(oas, ref, originalComponents)
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
refs.sort();
|
|
162
|
+
|
|
163
|
+
recursiveCache[component] = refs;
|
|
164
|
+
return refs;
|
|
165
|
+
}
|
|
166
|
+
|
|
107
167
|
module.exports = {
|
|
108
168
|
getReferencedComponents,
|
|
109
169
|
getDefinedComponents,
|
package/components.test.js
CHANGED
|
@@ -253,7 +253,7 @@ describe("#components", () => {
|
|
|
253
253
|
});
|
|
254
254
|
});
|
|
255
255
|
|
|
256
|
-
it("Removes schemas that are circular", () => {
|
|
256
|
+
it("Removes schemas that are circular (self reference)", () => {
|
|
257
257
|
expect(
|
|
258
258
|
c.removeUnusedComponents({
|
|
259
259
|
info: { title: "One" },
|
|
@@ -276,6 +276,42 @@ describe("#components", () => {
|
|
|
276
276
|
});
|
|
277
277
|
});
|
|
278
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
|
+
|
|
279
315
|
it("Does not remove circular schemas that are also referenced elsewhere", () => {
|
|
280
316
|
expect(
|
|
281
317
|
c.removeUnusedComponents({
|
package/merger.test.js
CHANGED