@redocly/openapi-core 1.0.0-beta.77 → 1.0.0-beta.78
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/lib/bundle.d.ts +3 -1
- package/lib/bundle.js +12 -1
- package/lib/config/config.d.ts +2 -9
- package/lib/rules/builtin.d.ts +2 -0
- package/lib/rules/common/remove-x-internal.d.ts +2 -0
- package/lib/rules/common/remove-x-internal.js +40 -0
- package/lib/rules/oas2/index.d.ts +1 -0
- package/lib/rules/oas2/index.js +2 -0
- package/lib/rules/oas2/remove-unused-components.d.ts +2 -0
- package/lib/rules/oas2/remove-unused-components.js +71 -0
- package/lib/rules/oas3/index.d.ts +1 -0
- package/lib/rules/oas3/index.js +2 -0
- package/lib/rules/oas3/remove-unused-components.d.ts +2 -0
- package/lib/rules/oas3/remove-unused-components.js +81 -0
- package/lib/typings/swagger.d.ts +14 -0
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +9 -1
- package/lib/walk.js +4 -7
- package/package.json +1 -1
- package/src/bundle.ts +16 -0
- package/src/config/config.ts +2 -3
- package/src/rules/__tests__/config.ts +5 -4
- package/src/rules/__tests__/hide-internals.test.ts +234 -0
- package/src/rules/common/remove-x-internal.ts +42 -0
- package/src/rules/oas2/index.ts +3 -1
- package/src/rules/oas2/remove-unused-components.ts +74 -0
- package/src/rules/oas3/index.ts +2 -0
- package/src/rules/oas3/remove-unused-components.ts +82 -0
- package/src/types/oas2.ts +0 -3
- package/src/typings/swagger.ts +7 -0
- package/src/utils.ts +8 -0
- package/src/walk.ts +4 -9
- package/tsconfig.tsbuildinfo +1 -1
package/lib/bundle.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare function bundle(opts: {
|
|
|
17
17
|
dereference?: boolean;
|
|
18
18
|
base?: string;
|
|
19
19
|
skipRedoclyRegistryRefs?: boolean;
|
|
20
|
+
removeUnusedComponents?: boolean;
|
|
20
21
|
}): Promise<{
|
|
21
22
|
bundle: Document;
|
|
22
23
|
problems: import("./walk").NormalizedProblem[];
|
|
@@ -32,6 +33,7 @@ export declare function bundleDocument(opts: {
|
|
|
32
33
|
externalRefResolver: BaseResolver;
|
|
33
34
|
dereference?: boolean;
|
|
34
35
|
skipRedoclyRegistryRefs?: boolean;
|
|
36
|
+
removeUnusedComponents?: boolean;
|
|
35
37
|
}): Promise<{
|
|
36
38
|
bundle: Document;
|
|
37
39
|
problems: import("./walk").NormalizedProblem[];
|
|
@@ -40,4 +42,4 @@ export declare function bundleDocument(opts: {
|
|
|
40
42
|
refTypes: Map<string, NormalizedNodeType> | undefined;
|
|
41
43
|
visitorsData: Record<string, Record<string, unknown>>;
|
|
42
44
|
}>;
|
|
43
|
-
export declare function mapTypeToComponent(typeName: string, version: OasMajorVersion): "headers" | "responses" | "
|
|
45
|
+
export declare function mapTypeToComponent(typeName: string, version: OasMajorVersion): "headers" | "responses" | "definitions" | "parameters" | "schemas" | "examples" | "requestBodies" | "securitySchemes" | "links" | "callbacks" | null;
|
package/lib/bundle.js
CHANGED
|
@@ -24,6 +24,8 @@ const rules_1 = require("./config/rules");
|
|
|
24
24
|
const no_unresolved_refs_1 = require("./rules/no-unresolved-refs");
|
|
25
25
|
const utils_1 = require("./utils");
|
|
26
26
|
const redocly_1 = require("./redocly");
|
|
27
|
+
const remove_unused_components_1 = require("./rules/oas2/remove-unused-components");
|
|
28
|
+
const remove_unused_components_2 = require("./rules/oas3/remove-unused-components");
|
|
27
29
|
var OasVersion;
|
|
28
30
|
(function (OasVersion) {
|
|
29
31
|
OasVersion["Version2"] = "oas2";
|
|
@@ -46,7 +48,7 @@ function bundle(opts) {
|
|
|
46
48
|
exports.bundle = bundle;
|
|
47
49
|
function bundleDocument(opts) {
|
|
48
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
-
const { document, config, customTypes, externalRefResolver, dereference = false, skipRedoclyRegistryRefs = false, } = opts;
|
|
51
|
+
const { document, config, customTypes, externalRefResolver, dereference = false, skipRedoclyRegistryRefs = false, removeUnusedComponents = false, } = opts;
|
|
50
52
|
const oasVersion = oas_types_1.detectOpenAPI(document.parsed);
|
|
51
53
|
const oasMajorVersion = oas_types_1.openAPIMajor(oasVersion);
|
|
52
54
|
const rules = config.getRulesForOasVersion(oasMajorVersion);
|
|
@@ -63,6 +65,15 @@ function bundleDocument(opts) {
|
|
|
63
65
|
refTypes: new Map(),
|
|
64
66
|
visitorsData: {},
|
|
65
67
|
};
|
|
68
|
+
if (removeUnusedComponents) {
|
|
69
|
+
decorators.push({
|
|
70
|
+
severity: 'error',
|
|
71
|
+
ruleId: 'remove-unused-components',
|
|
72
|
+
visitor: oasMajorVersion === oas_types_1.OasMajorVersion.Version2
|
|
73
|
+
? remove_unused_components_1.RemoveUnusedComponents({})
|
|
74
|
+
: remove_unused_components_2.RemoveUnusedComponents({})
|
|
75
|
+
});
|
|
76
|
+
}
|
|
66
77
|
const bundleVisitor = visitors_1.normalizeVisitors([
|
|
67
78
|
...preprocessors,
|
|
68
79
|
{
|
package/lib/config/config.d.ts
CHANGED
|
@@ -5,10 +5,9 @@ export declare const IGNORE_FILE = ".redocly.lint-ignore.yaml";
|
|
|
5
5
|
export declare type RuleConfig = ProblemSeverity | 'off' | ({
|
|
6
6
|
severity?: ProblemSeverity;
|
|
7
7
|
} & Record<string, any>);
|
|
8
|
-
export declare type PreprocessorConfig = ProblemSeverity | 'off' | 'on' | {
|
|
8
|
+
export declare type PreprocessorConfig = ProblemSeverity | 'off' | 'on' | ({
|
|
9
9
|
severity?: ProblemSeverity;
|
|
10
|
-
|
|
11
|
-
};
|
|
10
|
+
} & Record<string, any>);
|
|
12
11
|
export declare type DecoratorConfig = PreprocessorConfig;
|
|
13
12
|
export declare type LintRawConfig = {
|
|
14
13
|
plugins?: (string | Plugin)[];
|
|
@@ -107,15 +106,9 @@ export declare class LintConfig {
|
|
|
107
106
|
};
|
|
108
107
|
getPreprocessorSettings(ruleId: string, oasVersion: OasVersion): {
|
|
109
108
|
severity: ProblemSeverity | "off";
|
|
110
|
-
} | {
|
|
111
|
-
severity: ProblemSeverity;
|
|
112
|
-
options?: Record<string, any> | undefined;
|
|
113
109
|
};
|
|
114
110
|
getDecoratorSettings(ruleId: string, oasVersion: OasVersion): {
|
|
115
111
|
severity: ProblemSeverity | "off";
|
|
116
|
-
} | {
|
|
117
|
-
severity: ProblemSeverity;
|
|
118
|
-
options?: Record<string, any> | undefined;
|
|
119
112
|
};
|
|
120
113
|
getUnusedRules(): {
|
|
121
114
|
rules: string[];
|
package/lib/rules/builtin.d.ts
CHANGED
|
@@ -10,11 +10,13 @@ export declare const decorators: {
|
|
|
10
10
|
'operation-description-override': import("../visitors").Oas3Decorator;
|
|
11
11
|
'tag-description-override': import("../visitors").Oas3Decorator;
|
|
12
12
|
'info-description-override': import("../visitors").Oas3Decorator;
|
|
13
|
+
'remove-x-internal': import("../visitors").Oas3Decorator;
|
|
13
14
|
};
|
|
14
15
|
oas2: {
|
|
15
16
|
'registry-dependencies': import("../visitors").Oas2Decorator;
|
|
16
17
|
'operation-description-override': import("../visitors").Oas2Decorator;
|
|
17
18
|
'tag-description-override': import("../visitors").Oas2Decorator;
|
|
18
19
|
'info-description-override': import("../visitors").Oas2Decorator;
|
|
20
|
+
'remove-x-internal': import("../visitors").Oas2Decorator;
|
|
19
21
|
};
|
|
20
22
|
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RemoveXInternal = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const DEFAULT_INTERNAL_PROPERTY_NAME = 'x-internal';
|
|
6
|
+
const RemoveXInternal = ({ internalFlagProperty }) => {
|
|
7
|
+
const hiddenTag = internalFlagProperty || DEFAULT_INTERNAL_PROPERTY_NAME;
|
|
8
|
+
function removeInternal(node, ctx) {
|
|
9
|
+
const { parent, key } = ctx;
|
|
10
|
+
let didDelete = false;
|
|
11
|
+
if (Array.isArray(node)) {
|
|
12
|
+
for (let i = 0; i < node.length; i++) {
|
|
13
|
+
if (node[i] && node[i][hiddenTag]) {
|
|
14
|
+
node.splice(i, 1);
|
|
15
|
+
didDelete = true;
|
|
16
|
+
i--;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else if (utils_1.isPlainObject(node)) {
|
|
21
|
+
for (const key of Object.keys(node)) {
|
|
22
|
+
if (node[key][hiddenTag]) {
|
|
23
|
+
delete node[key];
|
|
24
|
+
didDelete = true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (didDelete && (utils_1.isEmptyObject(node) || utils_1.isEmptyArray(node))) {
|
|
29
|
+
delete parent[key];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
any: {
|
|
34
|
+
enter: (node, ctx) => {
|
|
35
|
+
removeInternal(node, ctx);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
exports.RemoveXInternal = RemoveXInternal;
|
package/lib/rules/oas2/index.js
CHANGED
|
@@ -42,6 +42,7 @@ const path_segment_plural_1 = require("../common/path-segment-plural");
|
|
|
42
42
|
const operation_description_override_1 = require("../common/operation-description-override");
|
|
43
43
|
const tag_description_override_1 = require("../common/tag-description-override");
|
|
44
44
|
const info_description_override_1 = require("../common/info-description-override");
|
|
45
|
+
const remove_x_internal_1 = require("../common/remove-x-internal");
|
|
45
46
|
exports.rules = {
|
|
46
47
|
spec: spec_1.OasSpec,
|
|
47
48
|
'no-invalid-schema-examples': no_invalid_schema_examples_1.NoInvalidSchemaExamples,
|
|
@@ -88,4 +89,5 @@ exports.decorators = {
|
|
|
88
89
|
'operation-description-override': operation_description_override_1.OperationDescriptionOverride,
|
|
89
90
|
'tag-description-override': tag_description_override_1.TagDescriptionOverride,
|
|
90
91
|
'info-description-override': info_description_override_1.InfoDescriptionOverride,
|
|
92
|
+
'remove-x-internal': remove_x_internal_1.RemoveXInternal
|
|
91
93
|
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RemoveUnusedComponents = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const RemoveUnusedComponents = () => {
|
|
6
|
+
let components = new Map();
|
|
7
|
+
function registerComponent(location, componentType, name) {
|
|
8
|
+
var _a;
|
|
9
|
+
components.set(location.absolutePointer, {
|
|
10
|
+
used: ((_a = components.get(location.absolutePointer)) === null || _a === void 0 ? void 0 : _a.used) || false,
|
|
11
|
+
componentType,
|
|
12
|
+
name,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
ref(ref, { type, resolve, key }) {
|
|
17
|
+
if (['Schema', 'Parameter', 'Response', 'SecurityScheme'].includes(type.name)) {
|
|
18
|
+
const resolvedRef = resolve(ref);
|
|
19
|
+
if (!resolvedRef.location)
|
|
20
|
+
return;
|
|
21
|
+
components.set(resolvedRef.location.absolutePointer, {
|
|
22
|
+
used: true,
|
|
23
|
+
name: key.toString(),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
DefinitionRoot: {
|
|
28
|
+
leave(root, ctx) {
|
|
29
|
+
const data = ctx.getVisitorData();
|
|
30
|
+
data.removedCount = 0;
|
|
31
|
+
let rootComponents = new Set();
|
|
32
|
+
components.forEach(usageInfo => {
|
|
33
|
+
const { used, name, componentType } = usageInfo;
|
|
34
|
+
if (!used && componentType) {
|
|
35
|
+
rootComponents.add(componentType);
|
|
36
|
+
delete root[componentType][name];
|
|
37
|
+
data.removedCount++;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
for (const component of rootComponents) {
|
|
41
|
+
if (utils_1.isEmptyObject(root[component])) {
|
|
42
|
+
delete root[component];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
NamedSchemas: {
|
|
48
|
+
Schema(schema, { location, key }) {
|
|
49
|
+
if (!schema.allOf) {
|
|
50
|
+
registerComponent(location, 'definitions', key.toString());
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
NamedParameters: {
|
|
55
|
+
Parameter(_parameter, { location, key }) {
|
|
56
|
+
registerComponent(location, 'parameters', key.toString());
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
NamedResponses: {
|
|
60
|
+
Response(_response, { location, key }) {
|
|
61
|
+
registerComponent(location, 'responses', key.toString());
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
NamedSecuritySchemes: {
|
|
65
|
+
SecurityScheme(_securityScheme, { location, key }) {
|
|
66
|
+
registerComponent(location, 'securityDefinitions', key.toString());
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
exports.RemoveUnusedComponents = RemoveUnusedComponents;
|
package/lib/rules/oas3/index.js
CHANGED
|
@@ -50,6 +50,7 @@ const info_description_override_1 = require("../common/info-description-override
|
|
|
50
50
|
const path_excludes_patterns_1 = require("../common/path-excludes-patterns");
|
|
51
51
|
const no_invalid_schema_examples_1 = require("../common/no-invalid-schema-examples");
|
|
52
52
|
const no_invalid_parameter_examples_1 = require("../common/no-invalid-parameter-examples");
|
|
53
|
+
const remove_x_internal_1 = require("../common/remove-x-internal");
|
|
53
54
|
exports.rules = {
|
|
54
55
|
spec: spec_1.OasSpec,
|
|
55
56
|
'info-description': info_description_1.InfoDescription,
|
|
@@ -104,4 +105,5 @@ exports.decorators = {
|
|
|
104
105
|
'operation-description-override': operation_description_override_1.OperationDescriptionOverride,
|
|
105
106
|
'tag-description-override': tag_description_override_1.TagDescriptionOverride,
|
|
106
107
|
'info-description-override': info_description_override_1.InfoDescriptionOverride,
|
|
108
|
+
'remove-x-internal': remove_x_internal_1.RemoveXInternal
|
|
107
109
|
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RemoveUnusedComponents = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const RemoveUnusedComponents = () => {
|
|
6
|
+
let components = new Map();
|
|
7
|
+
function registerComponent(location, componentType, name) {
|
|
8
|
+
var _a;
|
|
9
|
+
components.set(location.absolutePointer, {
|
|
10
|
+
used: ((_a = components.get(location.absolutePointer)) === null || _a === void 0 ? void 0 : _a.used) || false,
|
|
11
|
+
componentType,
|
|
12
|
+
name,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
ref(ref, { type, resolve, key }) {
|
|
17
|
+
if (['Schema', 'Header', 'Parameter', 'Response', 'Example', 'RequestBody'].includes(type.name)) {
|
|
18
|
+
const resolvedRef = resolve(ref);
|
|
19
|
+
if (!resolvedRef.location)
|
|
20
|
+
return;
|
|
21
|
+
components.set(resolvedRef.location.absolutePointer, {
|
|
22
|
+
used: true,
|
|
23
|
+
name: key.toString(),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
DefinitionRoot: {
|
|
28
|
+
leave(root, ctx) {
|
|
29
|
+
const data = ctx.getVisitorData();
|
|
30
|
+
data.removedCount = 0;
|
|
31
|
+
components.forEach(usageInfo => {
|
|
32
|
+
const { used, componentType, name } = usageInfo;
|
|
33
|
+
if (!used && componentType) {
|
|
34
|
+
let componentChild = root.components[componentType];
|
|
35
|
+
delete componentChild[name];
|
|
36
|
+
data.removedCount++;
|
|
37
|
+
if (utils_1.isEmptyObject(componentChild)) {
|
|
38
|
+
delete root.components[componentType];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
if (utils_1.isEmptyObject(root.components)) {
|
|
43
|
+
delete root.components;
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
NamedSchemas: {
|
|
48
|
+
Schema(schema, { location, key }) {
|
|
49
|
+
if (!schema.allOf) {
|
|
50
|
+
registerComponent(location, 'schemas', key.toString());
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
NamedParameters: {
|
|
55
|
+
Parameter(_parameter, { location, key }) {
|
|
56
|
+
registerComponent(location, 'parameters', key.toString());
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
NamedResponses: {
|
|
60
|
+
Response(_response, { location, key }) {
|
|
61
|
+
registerComponent(location, 'responses', key.toString());
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
NamedExamples: {
|
|
65
|
+
Example(_example, { location, key }) {
|
|
66
|
+
registerComponent(location, 'examples', key.toString());
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
NamedRequestBodies: {
|
|
70
|
+
RequestBody(_requestBody, { location, key }) {
|
|
71
|
+
registerComponent(location, 'requestBodies', key.toString());
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
NamedHeaders: {
|
|
75
|
+
Header(_header, { location, key }) {
|
|
76
|
+
registerComponent(location, 'headers', key.toString());
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
exports.RemoveUnusedComponents = RemoveUnusedComponents;
|
package/lib/typings/swagger.d.ts
CHANGED
|
@@ -16,6 +16,20 @@ export interface Oas2Definition {
|
|
|
16
16
|
tags?: Oas2Tag[];
|
|
17
17
|
externalDocs?: Oas2ExternalDocs;
|
|
18
18
|
}
|
|
19
|
+
export interface Oas2Components {
|
|
20
|
+
definitions?: {
|
|
21
|
+
[name: string]: Record<string, Oas2Schema>;
|
|
22
|
+
};
|
|
23
|
+
securityDefinitions?: {
|
|
24
|
+
[name: string]: Record<string, Oas2SecurityScheme>;
|
|
25
|
+
};
|
|
26
|
+
responses?: {
|
|
27
|
+
[name: string]: Record<string, Oas2Response>;
|
|
28
|
+
};
|
|
29
|
+
parameters?: {
|
|
30
|
+
[name: string]: Record<string, Oas2Parameter>;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
19
33
|
export interface Oas2Info {
|
|
20
34
|
title: string;
|
|
21
35
|
version: string;
|
package/lib/utils.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export declare type BundleOutputFormat = 'json' | 'yml' | 'yaml';
|
|
|
16
16
|
export declare function loadYaml(filename: string): Promise<unknown>;
|
|
17
17
|
export declare function notUndefined<T>(x: T | undefined): x is T;
|
|
18
18
|
export declare function isPlainObject(value: any): value is object;
|
|
19
|
+
export declare function isEmptyObject(value: any): value is object;
|
|
20
|
+
export declare function isEmptyArray(value: any): boolean;
|
|
19
21
|
export declare function readFileFromUrl(url: string, config: HttpResolveConfig): Promise<{
|
|
20
22
|
body: any;
|
|
21
23
|
mimeType: any;
|
package/lib/utils.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.match = exports.readFileFromUrl = exports.isPlainObject = exports.notUndefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
|
|
12
|
+
exports.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.match = exports.readFileFromUrl = exports.isEmptyArray = exports.isEmptyObject = exports.isPlainObject = exports.notUndefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
|
|
13
13
|
const fs = require("fs");
|
|
14
14
|
const minimatch = require("minimatch");
|
|
15
15
|
const node_fetch_1 = require("node-fetch");
|
|
@@ -42,6 +42,14 @@ function isPlainObject(value) {
|
|
|
42
42
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
43
43
|
}
|
|
44
44
|
exports.isPlainObject = isPlainObject;
|
|
45
|
+
function isEmptyObject(value) {
|
|
46
|
+
return isPlainObject(value) && Object.keys(value).length === 0;
|
|
47
|
+
}
|
|
48
|
+
exports.isEmptyObject = isEmptyObject;
|
|
49
|
+
function isEmptyArray(value) {
|
|
50
|
+
return Array.isArray(value) && value.length === 0;
|
|
51
|
+
}
|
|
52
|
+
exports.isEmptyArray = isEmptyArray;
|
|
45
53
|
function readFileFromUrl(url, config) {
|
|
46
54
|
return __awaiter(this, void 0, void 0, function* () {
|
|
47
55
|
const headers = {};
|
package/lib/walk.js
CHANGED
|
@@ -101,10 +101,9 @@ function walkDocument(opts) {
|
|
|
101
101
|
if (!activatedOn.skipped) {
|
|
102
102
|
visitedBySome = true;
|
|
103
103
|
enteredContexts.add(context);
|
|
104
|
-
const ignoreNextVisitorsOnNode = visitWithContext(visit, resolvedNode, context, ruleId, severity);
|
|
105
|
-
if (ignoreNextVisitorsOnNode)
|
|
104
|
+
const { ignoreNextVisitorsOnNode } = visitWithContext(visit, resolvedNode, context, ruleId, severity);
|
|
105
|
+
if (ignoreNextVisitorsOnNode)
|
|
106
106
|
break;
|
|
107
|
-
}
|
|
108
107
|
}
|
|
109
108
|
}
|
|
110
109
|
}
|
|
@@ -211,12 +210,10 @@ function walkDocument(opts) {
|
|
|
211
210
|
key,
|
|
212
211
|
parentLocations: collectParentsLocations(context),
|
|
213
212
|
oasVersion: ctx.oasVersion,
|
|
214
|
-
ignoreNextVisitorsOnNode: () => {
|
|
215
|
-
ignoreNextVisitorsOnNode = true;
|
|
216
|
-
},
|
|
213
|
+
ignoreNextVisitorsOnNode: () => { ignoreNextVisitorsOnNode = true; },
|
|
217
214
|
getVisitorData: getVisitorDataFn.bind(undefined, ruleId),
|
|
218
215
|
}, collectParents(context), context);
|
|
219
|
-
return ignoreNextVisitorsOnNode;
|
|
216
|
+
return { ignoreNextVisitorsOnNode };
|
|
220
217
|
}
|
|
221
218
|
function resolve(ref, from = currentLocation.source.absoluteRef) {
|
|
222
219
|
if (!ref_utils_1.isRef(ref))
|
package/package.json
CHANGED
package/src/bundle.ts
CHANGED
|
@@ -14,6 +14,8 @@ import { reportUnresolvedRef } from './rules/no-unresolved-refs';
|
|
|
14
14
|
import { isPlainObject } from './utils';
|
|
15
15
|
import { OasRef } from './typings/openapi';
|
|
16
16
|
import { isRedoclyRegistryURL } from './redocly';
|
|
17
|
+
import { RemoveUnusedComponents as RemoveUnusedComponentsOas2 } from './rules/oas2/remove-unused-components';
|
|
18
|
+
import { RemoveUnusedComponents as RemoveUnusedComponentsOas3 } from './rules/oas3/remove-unused-components';
|
|
17
19
|
|
|
18
20
|
export type Oas3RuleSet = Record<string, Oas3Rule>;
|
|
19
21
|
|
|
@@ -31,6 +33,7 @@ export async function bundle(opts: {
|
|
|
31
33
|
dereference?: boolean;
|
|
32
34
|
base?: string;
|
|
33
35
|
skipRedoclyRegistryRefs?: boolean;
|
|
36
|
+
removeUnusedComponents?: boolean;
|
|
34
37
|
}) {
|
|
35
38
|
const {
|
|
36
39
|
ref,
|
|
@@ -66,6 +69,7 @@ export async function bundleDocument(opts: {
|
|
|
66
69
|
externalRefResolver: BaseResolver;
|
|
67
70
|
dereference?: boolean;
|
|
68
71
|
skipRedoclyRegistryRefs?: boolean;
|
|
72
|
+
removeUnusedComponents?: boolean;
|
|
69
73
|
}) {
|
|
70
74
|
const {
|
|
71
75
|
document,
|
|
@@ -74,6 +78,7 @@ export async function bundleDocument(opts: {
|
|
|
74
78
|
externalRefResolver,
|
|
75
79
|
dereference = false,
|
|
76
80
|
skipRedoclyRegistryRefs = false,
|
|
81
|
+
removeUnusedComponents = false,
|
|
77
82
|
} = opts;
|
|
78
83
|
const oasVersion = detectOpenAPI(document.parsed);
|
|
79
84
|
const oasMajorVersion = openAPIMajor(oasVersion);
|
|
@@ -92,6 +97,7 @@ export async function bundleDocument(opts: {
|
|
|
92
97
|
|
|
93
98
|
const preprocessors = initRules(rules as any, config, 'preprocessors', oasVersion);
|
|
94
99
|
const decorators = initRules(rules as any, config, 'decorators', oasVersion);
|
|
100
|
+
|
|
95
101
|
const ctx: BundleContext = {
|
|
96
102
|
problems: [],
|
|
97
103
|
oasVersion: oasVersion,
|
|
@@ -99,6 +105,16 @@ export async function bundleDocument(opts: {
|
|
|
99
105
|
visitorsData: {},
|
|
100
106
|
};
|
|
101
107
|
|
|
108
|
+
if (removeUnusedComponents) {
|
|
109
|
+
decorators.push({
|
|
110
|
+
severity: 'error',
|
|
111
|
+
ruleId: 'remove-unused-components',
|
|
112
|
+
visitor: oasMajorVersion === OasMajorVersion.Version2
|
|
113
|
+
? RemoveUnusedComponentsOas2({})
|
|
114
|
+
: RemoveUnusedComponentsOas3({})
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
102
118
|
const bundleVisitor = normalizeVisitors(
|
|
103
119
|
[
|
|
104
120
|
...preprocessors,
|
package/src/config/config.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { LintConfig, RuleConfig } from
|
|
1
|
+
import { DecoratorConfig, LintConfig, RuleConfig } from '../../config/config';
|
|
2
2
|
import { defaultPlugin } from '../../config/builtIn';
|
|
3
3
|
|
|
4
|
-
export function makeConfig(rules: Record<string, RuleConfig>) {
|
|
4
|
+
export function makeConfig(rules: Record<string, RuleConfig>, decorators?: Record<string, DecoratorConfig>) {
|
|
5
5
|
return new LintConfig({
|
|
6
6
|
plugins: [defaultPlugin],
|
|
7
7
|
extends: [],
|
|
8
|
-
rules
|
|
8
|
+
rules,
|
|
9
|
+
decorators,
|
|
9
10
|
});
|
|
10
|
-
}
|
|
11
|
+
}
|