oas-toolkit 0.7.7 → 0.8.0

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 CHANGED
@@ -1,11 +1,16 @@
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");
5
- const uniqWith = require("lodash.uniqwith");
4
+ const get = require("lodash.get");
6
5
 
6
+ let seenItems = {};
7
7
  function removeUnusedComponents(oas) {
8
- const used = getReferencedComponents(oas);
8
+ // Reset all caches on each invocation
9
+ seenItems = {};
10
+
11
+ let used = findReferencesRecursive("paths", oas);
12
+ // Add global security schemes
13
+ used = used.concat(getSecuritySchemes(oas));
9
14
  const defined = getDefinedComponents(oas);
10
15
  const unused = getUnusedComponents(defined, used, oas);
11
16
 
@@ -20,31 +25,25 @@ function removeUnusedComponents(oas) {
20
25
  return removeUnusedComponents(result);
21
26
  }
22
27
 
23
- function getReferencesToComponent(oas, component) {
24
- return traverse(oas).reduce(function (acc, x) {
25
- if (
26
- this.isLeaf &&
27
- this.key == "$ref" &&
28
- x == `#/${component.replace(/\./g, "/")}`
29
- ) {
30
- acc.push(this.path.slice(0, 3).join("."));
31
- }
32
-
33
- return acc;
34
- }, []);
35
- }
36
-
37
- function removeSpecifiedComponents(oas, unused) {
38
- oas = traverse(oas).clone();
39
- return traverse(oas).forEach(function (x) {
40
- const path = this.path.join(".");
41
- if (unused.includes(path)) {
42
- this.remove();
43
- if (Object.keys(this.parent.node).length === 0) {
44
- this.parent.remove();
28
+ function findReferencesRecursive(ref, completeOas) {
29
+ if (seenItems[ref]) {
30
+ return [];
31
+ }
32
+ seenItems[ref] = true;
33
+
34
+ let refs = [];
35
+ const section = get(completeOas, ref);
36
+ if (section) {
37
+ refs = getReferencedComponents(section);
38
+ if (refs.length) {
39
+ for (let ref of refs) {
40
+ const found = findReferencesRecursive(ref, completeOas);
41
+ refs = refs.concat(found);
45
42
  }
46
43
  }
47
- });
44
+ }
45
+
46
+ return Array.from(new Set(refs));
48
47
  }
49
48
 
50
49
  function getReferencedComponents(oas) {
@@ -64,7 +63,11 @@ function getReferencedComponents(oas) {
64
63
  return acc;
65
64
  }, []);
66
65
 
67
- // Add global security schemes
66
+ return Array.from(new Set(components));
67
+ }
68
+
69
+ function getSecuritySchemes(oas) {
70
+ const components = [];
68
71
  if (oas.security) {
69
72
  for (let item of oas.security) {
70
73
  for (let key of Object.keys(item)) {
@@ -72,10 +75,22 @@ function getReferencedComponents(oas) {
72
75
  }
73
76
  }
74
77
  }
75
-
76
78
  return components;
77
79
  }
78
80
 
81
+ function removeSpecifiedComponents(oas, unused) {
82
+ oas = traverse(oas).clone();
83
+ return traverse(oas).forEach(function (x) {
84
+ const path = this.path.join(".");
85
+ if (unused.includes(path)) {
86
+ this.remove();
87
+ if (Object.keys(this.parent.node).length === 0) {
88
+ this.parent.remove();
89
+ }
90
+ }
91
+ });
92
+ }
93
+
79
94
  function getDefinedComponents(oas) {
80
95
  return traverse(oas).reduce(function (acc, x) {
81
96
  if (this.path[0] !== "components") {
@@ -91,82 +106,8 @@ function getDefinedComponents(oas) {
91
106
  }, []);
92
107
  }
93
108
 
94
- // This is a horrible global hack, but it works
95
- const referencesTo = {};
96
109
  function getUnusedComponents(all, referenced, oas) {
97
- const unused = difference(all, referenced);
98
-
99
- if (!oas) {
100
- return unused;
101
- }
102
-
103
- // If we have a component that is only referenced by itself, it's unused
104
- const used = intersection(all, referenced);
105
- for (let component of used) {
106
- if (component.startsWith("components.securitySchemes")) {
107
- continue;
108
- }
109
-
110
- const references = getReferencesToComponent(oas, component);
111
- if (references.length == 1 && references[0] === component) {
112
- unused.push(component);
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
- }
139
- }
140
- return unused;
141
- }
142
-
143
- let recursiveCache = {};
144
-
145
- function resetReferenceCache() {
146
- recursiveCache = {};
147
- }
148
-
149
- function getRecursiveReferencesToComponent(oas, component, originalComponents) {
150
- if (recursiveCache[component]) {
151
- return recursiveCache[component];
152
- }
153
-
154
- if (!originalComponents) {
155
- originalComponents = [];
156
- }
157
- originalComponents.push(component);
158
- let refs = getReferencesToComponent(oas, component);
159
- for (const ref of refs) {
160
- if (!originalComponents.includes(ref)) {
161
- refs = refs.concat(
162
- getRecursiveReferencesToComponent(oas, ref, originalComponents)
163
- );
164
- }
165
- }
166
- refs.sort();
167
-
168
- recursiveCache[component] = refs;
169
- return refs;
110
+ return difference(all, referenced);
170
111
  }
171
112
 
172
113
  module.exports = {
@@ -175,5 +116,5 @@ module.exports = {
175
116
  getUnusedComponents,
176
117
  removeSpecifiedComponents,
177
118
  removeUnusedComponents,
178
- resetReferenceCache,
119
+ getSecuritySchemes,
179
120
  };
@@ -69,6 +69,11 @@ describe("#components", () => {
69
69
  expect(c.getReferencedComponents(oas)).toEqual([
70
70
  "components.requestBodies.CreateFoo",
71
71
  "components.schemas.Foo",
72
+ ]);
73
+ });
74
+
75
+ it("extracts security schemes", () => {
76
+ expect(c.getSecuritySchemes(oas)).toEqual([
72
77
  "components.securitySchemes.personalAccessToken",
73
78
  ]);
74
79
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oas-toolkit",
3
- "version": "0.7.7",
3
+ "version": "0.8.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {