@redocly/openapi-core 1.0.0-beta.76 → 1.0.0-beta.80
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/__tests__/utils.ts +11 -1
- package/lib/bundle.d.ts +3 -1
- package/lib/bundle.js +30 -8
- package/lib/config/builtIn.js +18 -4
- package/lib/config/config.d.ts +2 -9
- package/lib/{rules → decorators}/common/info-description-override.d.ts +0 -0
- package/lib/{rules → decorators}/common/info-description-override.js +0 -0
- package/lib/{rules → decorators}/common/operation-description-override.d.ts +0 -0
- package/lib/{rules → decorators}/common/operation-description-override.js +0 -0
- package/lib/{rules → decorators}/common/registry-dependencies.d.ts +0 -0
- package/lib/{rules → decorators}/common/registry-dependencies.js +0 -0
- package/lib/decorators/common/remove-x-internal.d.ts +2 -0
- package/lib/decorators/common/remove-x-internal.js +58 -0
- package/lib/{rules → decorators}/common/tag-description-override.d.ts +0 -0
- package/lib/{rules → decorators}/common/tag-description-override.js +0 -0
- package/lib/decorators/oas2/index.d.ts +8 -0
- package/lib/decorators/oas2/index.js +15 -0
- package/lib/decorators/oas3/index.d.ts +8 -0
- package/lib/decorators/oas3/index.js +15 -0
- package/lib/format/format.d.ts +1 -1
- package/lib/format/format.js +39 -1
- package/lib/js-yaml/index.js +1 -1
- package/lib/resolve.d.ts +1 -0
- package/lib/resolve.js +7 -3
- package/lib/rules/oas2/index.d.ts +1 -7
- package/lib/rules/oas2/index.js +1 -11
- package/lib/rules/oas2/remove-unused-components.d.ts +2 -0
- package/lib/rules/oas2/remove-unused-components.js +73 -0
- package/lib/rules/oas3/index.d.ts +0 -7
- package/lib/rules/oas3/index.js +1 -11
- package/lib/rules/oas3/remove-unused-components.d.ts +2 -0
- package/lib/rules/oas3/remove-unused-components.js +83 -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 +5 -8
- package/package.json +1 -1
- package/src/__tests__/js-yaml.test.ts +29 -5
- package/src/__tests__/lint.test.ts +1 -3
- package/src/bundle.ts +37 -8
- package/src/config/builtIn.ts +20 -7
- package/src/config/config.ts +2 -3
- package/src/decorators/__tests__/remove-x-internal.test.ts +316 -0
- package/src/{rules → decorators}/common/info-description-override.ts +0 -0
- package/src/{rules → decorators}/common/operation-description-override.ts +0 -0
- package/src/{rules → decorators}/common/registry-dependencies.ts +0 -0
- package/src/decorators/common/remove-x-internal.ts +59 -0
- package/src/{rules → decorators}/common/tag-description-override.ts +0 -0
- package/src/decorators/oas2/index.ts +14 -0
- package/src/decorators/oas3/index.ts +14 -0
- package/src/format/format.ts +47 -2
- package/src/js-yaml/index.ts +1 -2
- package/src/resolve.ts +6 -6
- package/src/rules/__tests__/no-unresolved-refs.test.ts +1 -4
- package/src/rules/common/__tests__/info-description.test.ts +1 -3
- package/src/rules/common/__tests__/info-license.test.ts +1 -2
- package/src/rules/common/__tests__/license-url.test.ts +1 -2
- package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -2
- package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +1 -2
- package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -2
- package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +1 -2
- package/src/rules/common/__tests__/operation-2xx-response.test.ts +1 -2
- package/src/rules/common/__tests__/operation-4xx-response.test.ts +1 -2
- package/src/rules/common/__tests__/operation-operationId-unique.test.ts +1 -2
- package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -2
- package/src/rules/common/__tests__/operation-parameters-unique.test.ts +1 -2
- package/src/rules/common/__tests__/operation-security-defined.test.ts +1 -2
- package/src/rules/common/__tests__/operation-singular-tag.test.ts +1 -2
- package/src/rules/common/__tests__/path-http-verbs-order.test.ts +1 -2
- package/src/rules/common/__tests__/path-not-include-query.test.ts +1 -2
- package/src/rules/common/__tests__/path-params-defined.test.ts +1 -2
- package/src/rules/common/__tests__/paths-kebab-case.test.ts +1 -2
- package/src/rules/common/__tests__/tag-description.test.ts +1 -2
- package/src/rules/common/__tests__/tags-alphabetical.test.ts +1 -2
- package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +1 -2
- package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +1 -2
- package/src/rules/oas2/index.ts +1 -11
- package/src/rules/oas2/remove-unused-components.ts +76 -0
- package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-server-example.com.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -2
- package/src/rules/oas3/index.ts +0 -12
- package/src/rules/oas3/remove-unused-components.ts +84 -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 +6 -13
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/rules/builtin.d.ts +0 -20
- package/lib/rules/builtin.js +0 -17
- package/src/rules/__tests__/config.ts +0 -10
- package/src/rules/builtin.ts +0 -18
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 operation-parameters-unique', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 operation-security-defined', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 operation-singular-tag', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Common path-http-verbs-order', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 path-not-include-query', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 path-params-defined', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 paths-kebab-case', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 tag-description', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 tags-alphabetical', () => {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
3
|
-
import { makeConfig } from '../../__tests__/config';
|
|
2
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
4
3
|
import { lintDocument } from '../../../lint';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../../__tests__/utils';
|
|
2
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../../__tests__/utils';
|
|
3
3
|
import { lintDocument } from '../../../../lint';
|
|
4
4
|
import { BaseResolver } from '../../../../resolve';
|
|
5
|
-
import { makeConfig } from '../../../__tests__/config';
|
|
6
5
|
|
|
7
6
|
describe('Referenceable scalars', () => {
|
|
8
7
|
it('should not report $ref description', async () => {
|
package/src/rules/oas2/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Oas2Rule } from '../../visitors';
|
|
1
2
|
import { OasSpec } from '../common/spec';
|
|
2
3
|
import { NoInvalidSchemaExamples } from '../common/no-invalid-schema-examples';
|
|
3
4
|
import { NoInvalidParameterExamples } from '../common/no-invalid-parameter-examples';
|
|
@@ -26,8 +27,6 @@ import { OperationSingularTag } from '../common/operation-singular-tag';
|
|
|
26
27
|
import { OperationSecurityDefined } from '../common/operation-security-defined';
|
|
27
28
|
import { NoUnresolvedRefs } from '../no-unresolved-refs';
|
|
28
29
|
import { PathHttpVerbsOrder } from '../common/path-http-verbs-order';
|
|
29
|
-
import { Oas2Decorator, Oas2Rule } from '../../visitors';
|
|
30
|
-
import { RegistryDependencies } from '../common/registry-dependencies';
|
|
31
30
|
import { NoIdenticalPaths } from '../common/no-identical-paths';
|
|
32
31
|
import { OperationOperationId } from '../common/operation-operationId';
|
|
33
32
|
import { OperationSummary } from '../common/operation-summary';
|
|
@@ -37,9 +36,6 @@ import { PathExcludesPatterns } from '../common/path-excludes-patterns';
|
|
|
37
36
|
import { RequestMimeType } from './request-mime-type';
|
|
38
37
|
import { ResponseMimeType } from './response-mime-type';
|
|
39
38
|
import { PathSegmentPlural } from '../common/path-segment-plural';
|
|
40
|
-
import { OperationDescriptionOverride } from '../common/operation-description-override';
|
|
41
|
-
import { TagDescriptionOverride } from '../common/tag-description-override';
|
|
42
|
-
import { InfoDescriptionOverride } from '../common/info-description-override';
|
|
43
39
|
|
|
44
40
|
export const rules = {
|
|
45
41
|
spec: OasSpec as Oas2Rule,
|
|
@@ -83,9 +79,3 @@ export const rules = {
|
|
|
83
79
|
};
|
|
84
80
|
|
|
85
81
|
export const preprocessors = {};
|
|
86
|
-
export const decorators = {
|
|
87
|
-
'registry-dependencies': RegistryDependencies as Oas2Decorator,
|
|
88
|
-
'operation-description-override': OperationDescriptionOverride as Oas2Decorator,
|
|
89
|
-
'tag-description-override': TagDescriptionOverride as Oas2Decorator,
|
|
90
|
-
'info-description-override': InfoDescriptionOverride as Oas2Decorator,
|
|
91
|
-
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Oas2Rule } from '../../visitors';
|
|
2
|
+
import { Location } from '../../ref-utils';
|
|
3
|
+
import { Oas2Components } from '../../typings/swagger';
|
|
4
|
+
import { isEmptyObject } from '../../utils';
|
|
5
|
+
|
|
6
|
+
export const RemoveUnusedComponents: Oas2Rule = () => {
|
|
7
|
+
let components = new Map<string, { used: boolean; componentType?: keyof Oas2Components; name: string }>();
|
|
8
|
+
|
|
9
|
+
function registerComponent(location: Location, componentType: keyof Oas2Components, name: string): void {
|
|
10
|
+
components.set(location.absolutePointer, {
|
|
11
|
+
used: components.get(location.absolutePointer)?.used || false,
|
|
12
|
+
componentType,
|
|
13
|
+
name,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
ref: {
|
|
19
|
+
leave(ref, { type, resolve, key }) {
|
|
20
|
+
if (
|
|
21
|
+
['Schema', 'Parameter', 'Response', 'SecurityScheme'].includes(type.name)
|
|
22
|
+
) {
|
|
23
|
+
const resolvedRef = resolve(ref);
|
|
24
|
+
if (!resolvedRef.location) return;
|
|
25
|
+
components.set(resolvedRef.location.absolutePointer, {
|
|
26
|
+
used: true,
|
|
27
|
+
name: key.toString(),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
DefinitionRoot: {
|
|
33
|
+
leave(root, ctx) {
|
|
34
|
+
const data = ctx.getVisitorData() as { removedCount: number };
|
|
35
|
+
data.removedCount = 0;
|
|
36
|
+
|
|
37
|
+
let rootComponents = new Set<keyof Oas2Components>();
|
|
38
|
+
components.forEach(usageInfo => {
|
|
39
|
+
const { used, name, componentType } = usageInfo;
|
|
40
|
+
if (!used && componentType) {
|
|
41
|
+
rootComponents.add(componentType);
|
|
42
|
+
delete root[componentType]![name];
|
|
43
|
+
data.removedCount++;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
for (const component of rootComponents) {
|
|
47
|
+
if (isEmptyObject(root[component])) {
|
|
48
|
+
delete root[component];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
NamedSchemas: {
|
|
54
|
+
Schema(schema, { location, key }) {
|
|
55
|
+
if (!schema.allOf) {
|
|
56
|
+
registerComponent(location, 'definitions', key.toString());
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
NamedParameters: {
|
|
61
|
+
Parameter(_parameter, { location, key }) {
|
|
62
|
+
registerComponent(location, 'parameters', key.toString());
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
NamedResponses: {
|
|
66
|
+
Response(_response, { location, key }) {
|
|
67
|
+
registerComponent(location, 'responses', key.toString());
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
NamedSecuritySchemes: {
|
|
71
|
+
SecurityScheme(_securityScheme, { location, key }) {
|
|
72
|
+
registerComponent(location, 'securityDefinitions', key.toString());
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
3
|
-
import { makeConfig } from '../../__tests__/config';
|
|
2
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
4
3
|
import { lintDocument } from '../../../lint';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
4
4
|
import { BaseResolver } from '../../../resolve';
|
|
5
|
-
import { makeConfig } from '../../__tests__/config';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 as3-no-servers-empty-enum', () => {
|
|
8
7
|
it('oas3-no-servers-empty-enum: should report on server object with empty enum and unknown enum value', async () => {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
4
4
|
import { BaseResolver } from '../../../resolve';
|
|
5
|
-
import { makeConfig } from '../../__tests__/config';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 oas3-no-example-value-and-externalValue', () => {
|
|
8
7
|
it('oas3-no-example-value-and-externalValue: should report on example object with both value and external value', async () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('no-invalid-media-type-examples', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 oas3-no-server-example.com', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 oas3-no-server-trailing-slash', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { outdent } from 'outdent';
|
|
2
2
|
import { lintDocument } from '../../../lint';
|
|
3
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
|
4
|
-
import { makeConfig } from '../../__tests__/config';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
5
4
|
import { BaseResolver } from '../../../resolve';
|
|
6
5
|
|
|
7
6
|
describe('Oas3 no-unused-components', () => {
|
package/src/rules/oas3/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Oas3RuleSet } from '../../oas-types';
|
|
2
|
-
import { Oas3Decorator } from '../../visitors';
|
|
3
2
|
import { OasSpec } from '../common/spec';
|
|
4
3
|
import { Operation2xxResponse } from '../common/operation-2xx-response';
|
|
5
4
|
import { Operation4xxResponse } from '../common/operation-4xx-response';
|
|
@@ -32,7 +31,6 @@ import { PathsKebabCase } from '../common/paths-kebab-case';
|
|
|
32
31
|
import { PathHttpVerbsOrder } from '../common/path-http-verbs-order';
|
|
33
32
|
import { NoEmptyServers } from './no-empty-servers';
|
|
34
33
|
import { ValidContentExamples } from './no-invalid-media-type-examples';
|
|
35
|
-
import { RegistryDependencies } from '../common/registry-dependencies';
|
|
36
34
|
import { NoIdenticalPaths } from '../common/no-identical-paths';
|
|
37
35
|
import { NoUndefinedServerVariable } from './no-undefined-server-variable';
|
|
38
36
|
import { OperationOperationId } from '../common/operation-operationId';
|
|
@@ -43,9 +41,6 @@ import { NoHttpVerbsInPaths } from '../common/no-http-verbs-in-paths';
|
|
|
43
41
|
import { RequestMimeType } from './request-mime-type';
|
|
44
42
|
import { ResponseMimeType } from './response-mime-type';
|
|
45
43
|
import { PathSegmentPlural } from '../common/path-segment-plural';
|
|
46
|
-
import { OperationDescriptionOverride } from '../common/operation-description-override';
|
|
47
|
-
import { TagDescriptionOverride } from '../common/tag-description-override';
|
|
48
|
-
import { InfoDescriptionOverride } from '../common/info-description-override';
|
|
49
44
|
import { PathExcludesPatterns } from '../common/path-excludes-patterns';
|
|
50
45
|
import { NoInvalidSchemaExamples } from '../common/no-invalid-schema-examples';
|
|
51
46
|
import { NoInvalidParameterExamples } from '../common/no-invalid-parameter-examples';
|
|
@@ -100,10 +95,3 @@ export const rules = {
|
|
|
100
95
|
} as Oas3RuleSet;
|
|
101
96
|
|
|
102
97
|
export const preprocessors = {};
|
|
103
|
-
|
|
104
|
-
export const decorators = {
|
|
105
|
-
'registry-dependencies': RegistryDependencies as Oas3Decorator,
|
|
106
|
-
'operation-description-override': OperationDescriptionOverride as Oas3Decorator,
|
|
107
|
-
'tag-description-override': TagDescriptionOverride as Oas3Decorator,
|
|
108
|
-
'info-description-override': InfoDescriptionOverride as Oas3Decorator,
|
|
109
|
-
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Oas3Rule } from '../../visitors';
|
|
2
|
+
import { Location } from '../../ref-utils';
|
|
3
|
+
import { Oas3Components } from '../../typings/openapi'
|
|
4
|
+
import { isEmptyObject } from '../../utils';
|
|
5
|
+
|
|
6
|
+
export const RemoveUnusedComponents: Oas3Rule = () => {
|
|
7
|
+
let components = new Map<string, { used: boolean; componentType?: keyof Oas3Components; name: string }>();
|
|
8
|
+
|
|
9
|
+
function registerComponent(location: Location, componentType: keyof Oas3Components, name: string): void {
|
|
10
|
+
components.set(location.absolutePointer, {
|
|
11
|
+
used: components.get(location.absolutePointer)?.used || false,
|
|
12
|
+
componentType,
|
|
13
|
+
name,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
ref: {
|
|
19
|
+
leave(ref, { type, resolve, key }) {
|
|
20
|
+
if (
|
|
21
|
+
['Schema', 'Header', 'Parameter', 'Response', 'Example', 'RequestBody'].includes(type.name)
|
|
22
|
+
) {
|
|
23
|
+
const resolvedRef = resolve(ref);
|
|
24
|
+
if (!resolvedRef.location) return;
|
|
25
|
+
components.set(resolvedRef.location.absolutePointer, {
|
|
26
|
+
used: true,
|
|
27
|
+
name: key.toString(),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
DefinitionRoot: {
|
|
33
|
+
leave(root, ctx) {
|
|
34
|
+
const data = ctx.getVisitorData() as { removedCount: number };
|
|
35
|
+
data.removedCount = 0;
|
|
36
|
+
|
|
37
|
+
components.forEach(usageInfo => {
|
|
38
|
+
const { used, componentType, name } = usageInfo;
|
|
39
|
+
if (!used && componentType) {
|
|
40
|
+
let componentChild = root.components![componentType];
|
|
41
|
+
delete componentChild![name];
|
|
42
|
+
data.removedCount++;
|
|
43
|
+
if (isEmptyObject(componentChild)) {
|
|
44
|
+
delete root.components![componentType];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
if (isEmptyObject(root.components)) { delete root.components; }
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
NamedSchemas: {
|
|
52
|
+
Schema(schema, { location, key }) {
|
|
53
|
+
if (!schema.allOf) {
|
|
54
|
+
registerComponent(location, 'schemas', key.toString());
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
NamedParameters: {
|
|
59
|
+
Parameter(_parameter, { location, key }) {
|
|
60
|
+
registerComponent(location, 'parameters', key.toString());
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
NamedResponses: {
|
|
64
|
+
Response(_response, { location, key }) {
|
|
65
|
+
registerComponent(location, 'responses', key.toString());
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
NamedExamples: {
|
|
69
|
+
Example(_example, { location, key }) {
|
|
70
|
+
registerComponent(location, 'examples', key.toString());
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
NamedRequestBodies: {
|
|
74
|
+
RequestBody(_requestBody, { location, key }) {
|
|
75
|
+
registerComponent(location, 'requestBodies', key.toString());
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
NamedHeaders: {
|
|
79
|
+
Header(_header, { location, key }) {
|
|
80
|
+
registerComponent(location, 'headers', key.toString());
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
};
|
package/src/types/oas2.ts
CHANGED
|
@@ -383,13 +383,10 @@ export const Oas2Types: Record<string, NodeType> = {
|
|
|
383
383
|
Schema,
|
|
384
384
|
Xml,
|
|
385
385
|
SchemaProperties,
|
|
386
|
-
|
|
387
386
|
NamedSchemas: mapOf('Schema'),
|
|
388
387
|
NamedResponses: mapOf('Response'),
|
|
389
388
|
NamedParameters: mapOf('Parameter'),
|
|
390
389
|
NamedSecuritySchemes: mapOf('SecurityScheme'),
|
|
391
|
-
|
|
392
390
|
SecurityScheme,
|
|
393
|
-
|
|
394
391
|
XCodeSample,
|
|
395
392
|
};
|
package/src/typings/swagger.ts
CHANGED
|
@@ -20,6 +20,13 @@ export interface Oas2Definition {
|
|
|
20
20
|
externalDocs?: Oas2ExternalDocs;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
export interface Oas2Components {
|
|
24
|
+
definitions?: { [name: string]: Record<string, Oas2Schema> };
|
|
25
|
+
securityDefinitions?: { [name: string]: Record<string, Oas2SecurityScheme> };
|
|
26
|
+
responses?: { [name: string]: Record<string, Oas2Response> };
|
|
27
|
+
parameters?: { [name: string]: Record<string, Oas2Parameter> };
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
export interface Oas2Info {
|
|
24
31
|
title: string;
|
|
25
32
|
version: string;
|
package/src/utils.ts
CHANGED
|
@@ -40,6 +40,14 @@ export function isPlainObject(value: any): value is object {
|
|
|
40
40
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
export function isEmptyObject(value: any): value is object {
|
|
44
|
+
return isPlainObject(value) && Object.keys(value).length === 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function isEmptyArray(value: any) {
|
|
48
|
+
return Array.isArray(value) && value.length === 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
export async function readFileFromUrl(url: string, config: HttpResolveConfig) {
|
|
44
52
|
const headers: Record<string, string> = {};
|
|
45
53
|
for (const header of config.headers) {
|
package/src/walk.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
VisitFunction,
|
|
8
8
|
} from './visitors';
|
|
9
9
|
|
|
10
|
-
import { ResolvedRefMap, Document, ResolveError, YamlParseError, Source } from './resolve';
|
|
10
|
+
import { ResolvedRefMap, Document, ResolveError, YamlParseError, Source, makeRefId } from './resolve';
|
|
11
11
|
import { pushStack, popStack } from './utils';
|
|
12
12
|
import { OasVersion } from './oas-types';
|
|
13
13
|
import { NormalizedNodeType, isNamedType } from './types';
|
|
@@ -212,16 +212,14 @@ export function walkDocument<T>(opts: {
|
|
|
212
212
|
if (!activatedOn.skipped) {
|
|
213
213
|
visitedBySome = true;
|
|
214
214
|
enteredContexts.add(context);
|
|
215
|
-
const ignoreNextVisitorsOnNode = visitWithContext(
|
|
215
|
+
const { ignoreNextVisitorsOnNode } = visitWithContext(
|
|
216
216
|
visit,
|
|
217
217
|
resolvedNode,
|
|
218
218
|
context,
|
|
219
219
|
ruleId,
|
|
220
220
|
severity,
|
|
221
221
|
);
|
|
222
|
-
if (ignoreNextVisitorsOnNode)
|
|
223
|
-
break;
|
|
224
|
-
}
|
|
222
|
+
if (ignoreNextVisitorsOnNode) break;
|
|
225
223
|
}
|
|
226
224
|
}
|
|
227
225
|
}
|
|
@@ -358,16 +356,13 @@ export function walkDocument<T>(opts: {
|
|
|
358
356
|
key,
|
|
359
357
|
parentLocations: collectParentsLocations(context),
|
|
360
358
|
oasVersion: ctx.oasVersion,
|
|
361
|
-
ignoreNextVisitorsOnNode: () => {
|
|
362
|
-
ignoreNextVisitorsOnNode = true;
|
|
363
|
-
},
|
|
359
|
+
ignoreNextVisitorsOnNode: () => { ignoreNextVisitorsOnNode = true; },
|
|
364
360
|
getVisitorData: getVisitorDataFn.bind(undefined, ruleId),
|
|
365
361
|
},
|
|
366
362
|
collectParents(context),
|
|
367
363
|
context,
|
|
368
364
|
);
|
|
369
|
-
|
|
370
|
-
return ignoreNextVisitorsOnNode;
|
|
365
|
+
return { ignoreNextVisitorsOnNode };
|
|
371
366
|
}
|
|
372
367
|
|
|
373
368
|
function resolve<T>(
|
|
@@ -375,10 +370,8 @@ export function walkDocument<T>(opts: {
|
|
|
375
370
|
from: string = currentLocation.source.absoluteRef,
|
|
376
371
|
): ResolveResult<T> {
|
|
377
372
|
if (!isRef(ref)) return { location, node: ref };
|
|
378
|
-
const refId = from
|
|
379
|
-
|
|
373
|
+
const refId = makeRefId(from, ref.$ref);
|
|
380
374
|
const resolvedRef = resolvedRefMap.get(refId);
|
|
381
|
-
|
|
382
375
|
if (!resolvedRef) {
|
|
383
376
|
return {
|
|
384
377
|
location: undefined,
|