@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.
Files changed (96) hide show
  1. package/__tests__/utils.ts +11 -1
  2. package/lib/bundle.d.ts +3 -1
  3. package/lib/bundle.js +30 -8
  4. package/lib/config/builtIn.js +18 -4
  5. package/lib/config/config.d.ts +2 -9
  6. package/lib/{rules → decorators}/common/info-description-override.d.ts +0 -0
  7. package/lib/{rules → decorators}/common/info-description-override.js +0 -0
  8. package/lib/{rules → decorators}/common/operation-description-override.d.ts +0 -0
  9. package/lib/{rules → decorators}/common/operation-description-override.js +0 -0
  10. package/lib/{rules → decorators}/common/registry-dependencies.d.ts +0 -0
  11. package/lib/{rules → decorators}/common/registry-dependencies.js +0 -0
  12. package/lib/decorators/common/remove-x-internal.d.ts +2 -0
  13. package/lib/decorators/common/remove-x-internal.js +58 -0
  14. package/lib/{rules → decorators}/common/tag-description-override.d.ts +0 -0
  15. package/lib/{rules → decorators}/common/tag-description-override.js +0 -0
  16. package/lib/decorators/oas2/index.d.ts +8 -0
  17. package/lib/decorators/oas2/index.js +15 -0
  18. package/lib/decorators/oas3/index.d.ts +8 -0
  19. package/lib/decorators/oas3/index.js +15 -0
  20. package/lib/format/format.d.ts +1 -1
  21. package/lib/format/format.js +39 -1
  22. package/lib/js-yaml/index.js +1 -1
  23. package/lib/resolve.d.ts +1 -0
  24. package/lib/resolve.js +7 -3
  25. package/lib/rules/oas2/index.d.ts +1 -7
  26. package/lib/rules/oas2/index.js +1 -11
  27. package/lib/rules/oas2/remove-unused-components.d.ts +2 -0
  28. package/lib/rules/oas2/remove-unused-components.js +73 -0
  29. package/lib/rules/oas3/index.d.ts +0 -7
  30. package/lib/rules/oas3/index.js +1 -11
  31. package/lib/rules/oas3/remove-unused-components.d.ts +2 -0
  32. package/lib/rules/oas3/remove-unused-components.js +83 -0
  33. package/lib/typings/swagger.d.ts +14 -0
  34. package/lib/utils.d.ts +2 -0
  35. package/lib/utils.js +9 -1
  36. package/lib/walk.js +5 -8
  37. package/package.json +1 -1
  38. package/src/__tests__/js-yaml.test.ts +29 -5
  39. package/src/__tests__/lint.test.ts +1 -3
  40. package/src/bundle.ts +37 -8
  41. package/src/config/builtIn.ts +20 -7
  42. package/src/config/config.ts +2 -3
  43. package/src/decorators/__tests__/remove-x-internal.test.ts +316 -0
  44. package/src/{rules → decorators}/common/info-description-override.ts +0 -0
  45. package/src/{rules → decorators}/common/operation-description-override.ts +0 -0
  46. package/src/{rules → decorators}/common/registry-dependencies.ts +0 -0
  47. package/src/decorators/common/remove-x-internal.ts +59 -0
  48. package/src/{rules → decorators}/common/tag-description-override.ts +0 -0
  49. package/src/decorators/oas2/index.ts +14 -0
  50. package/src/decorators/oas3/index.ts +14 -0
  51. package/src/format/format.ts +47 -2
  52. package/src/js-yaml/index.ts +1 -2
  53. package/src/resolve.ts +6 -6
  54. package/src/rules/__tests__/no-unresolved-refs.test.ts +1 -4
  55. package/src/rules/common/__tests__/info-description.test.ts +1 -3
  56. package/src/rules/common/__tests__/info-license.test.ts +1 -2
  57. package/src/rules/common/__tests__/license-url.test.ts +1 -2
  58. package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -2
  59. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +1 -2
  60. package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -2
  61. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +1 -2
  62. package/src/rules/common/__tests__/operation-2xx-response.test.ts +1 -2
  63. package/src/rules/common/__tests__/operation-4xx-response.test.ts +1 -2
  64. package/src/rules/common/__tests__/operation-operationId-unique.test.ts +1 -2
  65. package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -2
  66. package/src/rules/common/__tests__/operation-parameters-unique.test.ts +1 -2
  67. package/src/rules/common/__tests__/operation-security-defined.test.ts +1 -2
  68. package/src/rules/common/__tests__/operation-singular-tag.test.ts +1 -2
  69. package/src/rules/common/__tests__/path-http-verbs-order.test.ts +1 -2
  70. package/src/rules/common/__tests__/path-not-include-query.test.ts +1 -2
  71. package/src/rules/common/__tests__/path-params-defined.test.ts +1 -2
  72. package/src/rules/common/__tests__/paths-kebab-case.test.ts +1 -2
  73. package/src/rules/common/__tests__/tag-description.test.ts +1 -2
  74. package/src/rules/common/__tests__/tags-alphabetical.test.ts +1 -2
  75. package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +1 -2
  76. package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +1 -2
  77. package/src/rules/oas2/index.ts +1 -11
  78. package/src/rules/oas2/remove-unused-components.ts +76 -0
  79. package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +1 -2
  80. package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +1 -2
  81. package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +1 -2
  82. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +1 -2
  83. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +1 -2
  84. package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +1 -2
  85. package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -2
  86. package/src/rules/oas3/index.ts +0 -12
  87. package/src/rules/oas3/remove-unused-components.ts +84 -0
  88. package/src/types/oas2.ts +0 -3
  89. package/src/typings/swagger.ts +7 -0
  90. package/src/utils.ts +8 -0
  91. package/src/walk.ts +6 -13
  92. package/tsconfig.tsbuildinfo +1 -1
  93. package/lib/rules/builtin.d.ts +0 -20
  94. package/lib/rules/builtin.js +0 -17
  95. package/src/rules/__tests__/config.ts +0 -10
  96. 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 () => {
@@ -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', () => {
@@ -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
  };
@@ -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 + '::' + ref.$ref;
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,