@redocly/openapi-core 1.0.0-beta.106 → 1.0.0-beta.109

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 (193) hide show
  1. package/lib/benchmark/benches/lint-with-top-level-rule-report.bench.js +0 -1
  2. package/lib/benchmark/benches/resolve-with-no-external.bench.js +1 -1
  3. package/lib/bundle.d.ts +1 -1
  4. package/lib/bundle.js +9 -6
  5. package/lib/config/all.js +5 -3
  6. package/lib/config/config-resolvers.js +32 -14
  7. package/lib/config/config.d.ts +3 -5
  8. package/lib/config/config.js +7 -4
  9. package/lib/config/load.d.ts +7 -0
  10. package/lib/config/load.js +14 -6
  11. package/lib/config/minimal.js +7 -4
  12. package/lib/config/recommended.js +7 -4
  13. package/lib/config/rules.d.ts +1 -1
  14. package/lib/config/rules.js +1 -1
  15. package/lib/config/types.d.ts +7 -0
  16. package/lib/config/utils.d.ts +2 -2
  17. package/lib/config/utils.js +49 -11
  18. package/lib/decorators/common/registry-dependencies.js +2 -2
  19. package/lib/env.d.ts +3 -0
  20. package/lib/env.js +8 -0
  21. package/lib/format/codeframes.js +16 -10
  22. package/lib/format/format.d.ts +1 -1
  23. package/lib/format/format.js +49 -26
  24. package/lib/index.d.ts +5 -5
  25. package/lib/index.js +3 -1
  26. package/lib/js-yaml/index.js +1 -0
  27. package/lib/lint.js +2 -2
  28. package/lib/logger.d.ts +10 -0
  29. package/lib/logger.js +31 -0
  30. package/lib/output.d.ts +3 -0
  31. package/lib/output.js +9 -0
  32. package/lib/redocly/index.js +10 -9
  33. package/lib/redocly/registry-api-types.d.ts +28 -30
  34. package/lib/redocly/registry-api.d.ts +3 -3
  35. package/lib/redocly/registry-api.js +7 -1
  36. package/lib/ref-utils.js +2 -1
  37. package/lib/resolve.d.ts +1 -1
  38. package/lib/resolve.js +4 -2
  39. package/lib/rules/ajv.d.ts +1 -1
  40. package/lib/rules/ajv.js +7 -7
  41. package/lib/rules/common/assertions/asserts.js +4 -4
  42. package/lib/rules/common/assertions/index.js +1 -1
  43. package/lib/rules/common/no-ambiguous-paths.js +1 -1
  44. package/lib/rules/common/no-identical-paths.js +1 -1
  45. package/lib/rules/common/no-invalid-parameter-examples.js +3 -3
  46. package/lib/rules/common/no-invalid-schema-examples.js +3 -3
  47. package/lib/rules/common/operation-2xx-response.js +1 -1
  48. package/lib/rules/common/operation-4xx-response.js +1 -1
  49. package/lib/rules/common/operation-operationId.js +1 -1
  50. package/lib/rules/common/operation-tag-defined.js +1 -1
  51. package/lib/rules/common/path-not-include-query.js +1 -1
  52. package/lib/rules/common/security-defined.d.ts +2 -0
  53. package/lib/rules/common/{operation-security-defined.js → security-defined.js} +19 -5
  54. package/lib/rules/common/spec.js +14 -3
  55. package/lib/rules/common/tags-alphabetical.js +1 -1
  56. package/lib/rules/oas2/index.d.ts +1 -1
  57. package/lib/rules/oas2/index.js +2 -2
  58. package/lib/rules/oas2/remove-unused-components.js +3 -3
  59. package/lib/rules/oas2/request-mime-type.js +1 -1
  60. package/lib/rules/oas2/response-mime-type.js +1 -1
  61. package/lib/rules/oas3/index.js +8 -4
  62. package/lib/rules/oas3/no-empty-servers.js +1 -1
  63. package/lib/rules/oas3/no-invalid-media-type-examples.js +2 -2
  64. package/lib/rules/oas3/no-server-variables-empty-enum.d.ts +2 -0
  65. package/lib/rules/oas3/{no-servers-empty-enum.js → no-server-variables-empty-enum.js} +5 -5
  66. package/lib/rules/oas3/no-unused-components.js +2 -2
  67. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.d.ts +5 -0
  68. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.js +36 -0
  69. package/lib/rules/oas3/remove-unused-components.js +4 -4
  70. package/lib/rules/oas3/request-mime-type.js +1 -1
  71. package/lib/rules/oas3/response-mime-type.js +1 -1
  72. package/lib/rules/oas3/spec-components-invalid-map-name.d.ts +2 -0
  73. package/lib/rules/oas3/spec-components-invalid-map-name.js +46 -0
  74. package/lib/rules/other/stats.d.ts +2 -2
  75. package/lib/rules/other/stats.js +2 -2
  76. package/lib/rules/utils.d.ts +3 -2
  77. package/lib/rules/utils.js +16 -4
  78. package/lib/types/oas2.js +5 -5
  79. package/lib/types/oas3.js +27 -20
  80. package/lib/types/oas3_1.js +3 -3
  81. package/lib/types/redocly-yaml.js +47 -56
  82. package/lib/utils.d.ts +6 -1
  83. package/lib/utils.js +24 -7
  84. package/lib/visitors.d.ts +12 -12
  85. package/lib/visitors.js +15 -3
  86. package/lib/walk.d.ts +2 -1
  87. package/lib/walk.js +6 -3
  88. package/package.json +2 -2
  89. package/src/__tests__/__snapshots__/bundle.test.ts.snap +3 -3
  90. package/src/__tests__/fixtures/extension.js +3 -3
  91. package/src/__tests__/format.test.ts +76 -0
  92. package/src/__tests__/lint.test.ts +106 -131
  93. package/src/__tests__/logger-browser.test.ts +53 -0
  94. package/src/__tests__/logger.test.ts +47 -0
  95. package/src/__tests__/output-browser.test.ts +18 -0
  96. package/src/__tests__/output.test.ts +15 -0
  97. package/src/__tests__/resolve-http.test.ts +1 -1
  98. package/src/__tests__/resolve.test.ts +9 -9
  99. package/src/__tests__/utils-browser.test.ts +11 -0
  100. package/src/__tests__/utils.test.ts +7 -0
  101. package/src/__tests__/walk.test.ts +78 -10
  102. package/src/benchmark/benches/lint-with-top-level-rule-report.bench.ts +0 -1
  103. package/src/benchmark/benches/resolve-with-no-external.bench.ts +1 -1
  104. package/src/bundle.ts +10 -7
  105. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +12 -6
  106. package/src/config/__tests__/config.test.ts +35 -0
  107. package/src/config/__tests__/fixtures/plugin-config.yaml +2 -3
  108. package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +11 -12
  109. package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +7 -8
  110. package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +18 -19
  111. package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +9 -10
  112. package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +3 -4
  113. package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +4 -5
  114. package/src/config/__tests__/load.test.ts +76 -1
  115. package/src/config/__tests__/utils.test.ts +64 -4
  116. package/src/config/all.ts +5 -3
  117. package/src/config/config-resolvers.ts +45 -19
  118. package/src/config/config.ts +10 -8
  119. package/src/config/load.ts +31 -7
  120. package/src/config/minimal.ts +7 -4
  121. package/src/config/recommended.ts +7 -4
  122. package/src/config/rules.ts +2 -2
  123. package/src/config/types.ts +11 -0
  124. package/src/config/utils.ts +115 -25
  125. package/src/decorators/common/registry-dependencies.ts +2 -2
  126. package/src/env.ts +5 -0
  127. package/src/format/codeframes.ts +15 -9
  128. package/src/format/format.ts +59 -34
  129. package/src/index.ts +6 -4
  130. package/src/js-yaml/index.ts +1 -0
  131. package/src/lint.ts +2 -2
  132. package/src/logger.ts +34 -0
  133. package/src/output.ts +7 -0
  134. package/src/redocly/index.ts +7 -4
  135. package/src/redocly/registry-api-types.ts +27 -29
  136. package/src/redocly/registry-api.ts +18 -7
  137. package/src/ref-utils.ts +2 -1
  138. package/src/resolve.ts +7 -5
  139. package/src/rules/__tests__/utils.test.ts +39 -1
  140. package/src/rules/ajv.ts +7 -7
  141. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +1 -0
  142. package/src/rules/common/__tests__/operation-2xx-response.test.ts +1 -1
  143. package/src/rules/common/__tests__/operation-4xx-response.test.ts +26 -3
  144. package/src/rules/common/__tests__/security-defined.test.ts +175 -0
  145. package/src/rules/common/__tests__/spec.test.ts +79 -0
  146. package/src/rules/common/assertions/__tests__/utils.test.ts +2 -2
  147. package/src/rules/common/assertions/asserts.ts +4 -4
  148. package/src/rules/common/assertions/index.ts +1 -1
  149. package/src/rules/common/no-ambiguous-paths.ts +1 -1
  150. package/src/rules/common/no-identical-paths.ts +1 -1
  151. package/src/rules/common/no-invalid-parameter-examples.ts +4 -4
  152. package/src/rules/common/no-invalid-schema-examples.ts +4 -4
  153. package/src/rules/common/operation-2xx-response.ts +1 -1
  154. package/src/rules/common/operation-4xx-response.ts +1 -1
  155. package/src/rules/common/operation-operationId.ts +1 -1
  156. package/src/rules/common/operation-tag-defined.ts +1 -1
  157. package/src/rules/common/path-not-include-query.ts +1 -1
  158. package/src/rules/common/{operation-security-defined.ts → security-defined.ts} +20 -5
  159. package/src/rules/common/spec.ts +17 -3
  160. package/src/rules/common/tags-alphabetical.ts +1 -1
  161. package/src/rules/oas2/index.ts +2 -2
  162. package/src/rules/oas2/remove-unused-components.ts +3 -3
  163. package/src/rules/oas2/request-mime-type.ts +1 -1
  164. package/src/rules/oas2/response-mime-type.ts +1 -1
  165. package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +16 -16
  166. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +5 -5
  167. package/src/rules/oas3/__tests__/operation-4xx-problem-details-rfc7807.test.ts +145 -0
  168. package/src/rules/oas3/__tests__/spec/spec.test.ts +10 -0
  169. package/src/rules/oas3/__tests__/spec-components-invalid-map-name.test.ts +217 -0
  170. package/src/rules/oas3/index.ts +8 -4
  171. package/src/rules/oas3/no-empty-servers.ts +1 -1
  172. package/src/rules/oas3/no-invalid-media-type-examples.ts +3 -3
  173. package/src/rules/oas3/{no-servers-empty-enum.ts → no-server-variables-empty-enum.ts} +3 -3
  174. package/src/rules/oas3/no-unused-components.ts +2 -2
  175. package/src/rules/oas3/operation-4xx-problem-details-rfc7807.ts +36 -0
  176. package/src/rules/oas3/remove-unused-components.ts +5 -5
  177. package/src/rules/oas3/request-mime-type.ts +1 -1
  178. package/src/rules/oas3/response-mime-type.ts +1 -1
  179. package/src/rules/oas3/spec-components-invalid-map-name.ts +53 -0
  180. package/src/rules/other/stats.ts +2 -2
  181. package/src/rules/utils.ts +17 -3
  182. package/src/types/index.ts +2 -2
  183. package/src/types/oas2.ts +5 -5
  184. package/src/types/oas3.ts +27 -20
  185. package/src/types/oas3_1.ts +3 -3
  186. package/src/types/redocly-yaml.ts +53 -41
  187. package/src/utils.ts +31 -4
  188. package/src/visitors.ts +34 -18
  189. package/src/walk.ts +15 -11
  190. package/tsconfig.tsbuildinfo +1 -1
  191. package/lib/rules/common/operation-security-defined.d.ts +0 -2
  192. package/lib/rules/oas3/no-servers-empty-enum.d.ts +0 -2
  193. package/src/rules/common/__tests__/operation-security-defined.test.ts +0 -69
package/src/types/oas3.ts CHANGED
@@ -2,7 +2,7 @@ import { NodeType, listOf, mapOf } from '.';
2
2
  import { isMappingRef } from '../ref-utils';
3
3
  const responseCodeRegexp = /^[0-9][0-9Xx]{2}$/;
4
4
 
5
- const DefinitionRoot: NodeType = {
5
+ const Root: NodeType = {
6
6
  properties: {
7
7
  openapi: null,
8
8
  info: 'Info',
@@ -10,7 +10,7 @@ const DefinitionRoot: NodeType = {
10
10
  security: listOf('SecurityRequirement'),
11
11
  tags: listOf('Tag'),
12
12
  externalDocs: 'ExternalDocs',
13
- paths: 'PathMap',
13
+ paths: 'PathsMap',
14
14
  components: 'Components',
15
15
  'x-webhooks': 'WebhooksMap',
16
16
  },
@@ -38,7 +38,7 @@ const Server: NodeType = {
38
38
  properties: {
39
39
  url: { type: 'string' },
40
40
  description: { type: 'string' },
41
- variables: mapOf('ServerVariable'),
41
+ variables: 'ServerVariablesMap',
42
42
  },
43
43
  required: ['url'],
44
44
  };
@@ -88,7 +88,7 @@ const License: NodeType = {
88
88
  required: ['name'],
89
89
  };
90
90
 
91
- const PathMap: NodeType = {
91
+ const PathsMap: NodeType = {
92
92
  properties: {},
93
93
  additionalProperties: (_value: any, key: string) =>
94
94
  key.startsWith('/') ? 'PathItem' : undefined,
@@ -132,8 +132,8 @@ const Parameter: NodeType = {
132
132
  allowReserved: { type: 'boolean' },
133
133
  schema: 'Schema',
134
134
  example: { isExample: true },
135
- examples: mapOf('Example'),
136
- content: 'MediaTypeMap',
135
+ examples: 'ExamplesMap',
136
+ content: 'MediaTypesMap',
137
137
  },
138
138
  required: ['name', 'in'],
139
139
  requiredOneOf: ['schema', 'content'],
@@ -155,7 +155,7 @@ const Operation: NodeType = {
155
155
  requestBody: 'RequestBody',
156
156
  responses: 'ResponsesMap',
157
157
  deprecated: { type: 'boolean' },
158
- callbacks: mapOf('Callback'),
158
+ callbacks: 'CallbacksMap',
159
159
  'x-codeSamples': listOf('XCodeSample'),
160
160
  'x-code-samples': listOf('XCodeSample'), // deprecated
161
161
  'x-hideTryItPanel': { type: 'boolean' },
@@ -175,12 +175,12 @@ const RequestBody: NodeType = {
175
175
  properties: {
176
176
  description: { type: 'string' },
177
177
  required: { type: 'boolean' },
178
- content: 'MediaTypeMap',
178
+ content: 'MediaTypesMap',
179
179
  },
180
180
  required: ['content'],
181
181
  };
182
182
 
183
- const MediaTypeMap: NodeType = {
183
+ const MediaTypesMap: NodeType = {
184
184
  properties: {},
185
185
  additionalProperties: 'MediaType',
186
186
  };
@@ -189,8 +189,8 @@ const MediaType: NodeType = {
189
189
  properties: {
190
190
  schema: 'Schema',
191
191
  example: { isExample: true },
192
- examples: mapOf('Example'),
193
- encoding: mapOf('Encoding'),
192
+ examples: 'ExamplesMap',
193
+ encoding: 'EncodingsMap',
194
194
  },
195
195
  };
196
196
 
@@ -206,7 +206,7 @@ const Example: NodeType = {
206
206
  const Encoding: NodeType = {
207
207
  properties: {
208
208
  contentType: { type: 'string' },
209
- headers: mapOf('Header'),
209
+ headers: 'HeadersMap',
210
210
  style: {
211
211
  enum: ['form', 'simple', 'label', 'matrix', 'spaceDelimited', 'pipeDelimited', 'deepObject'],
212
212
  },
@@ -228,9 +228,10 @@ const Header: NodeType = {
228
228
  allowReserved: { type: 'boolean' },
229
229
  schema: 'Schema',
230
230
  example: { isExample: true },
231
- examples: mapOf('Example'),
232
- content: 'MediaTypeMap',
231
+ examples: 'ExamplesMap',
232
+ content: 'MediaTypesMap',
233
233
  },
234
+ requiredOneOf: ['schema', 'content'],
234
235
  };
235
236
 
236
237
  const ResponsesMap: NodeType = {
@@ -242,9 +243,9 @@ const ResponsesMap: NodeType = {
242
243
  const Response: NodeType = {
243
244
  properties: {
244
245
  description: { type: 'string' },
245
- headers: mapOf('Header'),
246
- content: 'MediaTypeMap',
247
- links: mapOf('Link'),
246
+ headers: 'HeadersMap',
247
+ content: 'MediaTypesMap',
248
+ links: 'LinksMap',
248
249
  },
249
250
  required: ['description'],
250
251
  };
@@ -459,26 +460,31 @@ const SecurityScheme: NodeType = {
459
460
  };
460
461
 
461
462
  export const Oas3Types: Record<string, NodeType> = {
462
- DefinitionRoot,
463
+ Root,
463
464
  Tag,
464
465
  ExternalDocs,
465
466
  Server,
466
467
  ServerVariable,
468
+ ServerVariablesMap: mapOf('ServerVariable'),
467
469
  SecurityRequirement,
468
470
  Info,
469
471
  Contact,
470
472
  License,
471
- PathMap,
473
+ PathsMap,
472
474
  PathItem,
473
475
  Parameter,
474
476
  Operation,
475
477
  Callback: mapOf('PathItem'),
478
+ CallbacksMap: mapOf('Callback'),
476
479
  RequestBody,
477
- MediaTypeMap,
480
+ MediaTypesMap,
478
481
  MediaType,
479
482
  Example,
483
+ ExamplesMap: mapOf('Example'),
480
484
  Encoding,
485
+ EncodingsMap: mapOf('Encoding'),
481
486
  Header,
487
+ HeadersMap: mapOf('Header'),
482
488
  ResponsesMap,
483
489
  Response,
484
490
  Link,
@@ -488,6 +494,7 @@ export const Oas3Types: Record<string, NodeType> = {
488
494
  DiscriminatorMapping,
489
495
  Discriminator,
490
496
  Components,
497
+ LinksMap: mapOf('Link'),
491
498
  NamedSchemas: mapOf('Schema'),
492
499
  NamedResponses: mapOf('Response'),
493
500
  NamedParameters: mapOf('Parameter'),
@@ -1,7 +1,7 @@
1
1
  import { NodeType, listOf, mapOf } from '.';
2
2
  import { Oas3Types } from './oas3';
3
3
 
4
- const DefinitionRoot: NodeType = {
4
+ const Root: NodeType = {
5
5
  properties: {
6
6
  openapi: null,
7
7
  info: 'Info',
@@ -9,7 +9,7 @@ const DefinitionRoot: NodeType = {
9
9
  security: listOf('SecurityRequirement'),
10
10
  tags: listOf('Tag'),
11
11
  externalDocs: 'ExternalDocs',
12
- paths: 'PathMap',
12
+ paths: 'PathsMap',
13
13
  webhooks: 'WebhooksMap',
14
14
  components: 'Components',
15
15
  jsonSchemaDialect: { type: 'string' },
@@ -241,7 +241,7 @@ const SecurityScheme: NodeType = {
241
241
  export const Oas3_1Types: Record<string, NodeType> = {
242
242
  ...Oas3Types,
243
243
  Info,
244
- DefinitionRoot,
244
+ Root,
245
245
  Schema,
246
246
  License,
247
247
  Components,
@@ -1,5 +1,6 @@
1
1
  import { NodeType, listOf } from '.';
2
2
  import { omitObjectProps, pickObjectProps, isCustomRuleId } from '../utils';
3
+
3
4
  const builtInRulesList = [
4
5
  'spec',
5
6
  'info-description',
@@ -8,6 +9,7 @@ const builtInRulesList = [
8
9
  'info-license-url',
9
10
  'operation-2xx-response',
10
11
  'operation-4xx-response',
12
+ 'operation-4xx-problem-details-rfc7807',
11
13
  'assertions',
12
14
  'operation-operationId-unique',
13
15
  'operation-parameters-unique',
@@ -31,7 +33,7 @@ const builtInRulesList = [
31
33
  'path-params-defined',
32
34
  'parameter-description',
33
35
  'operation-singular-tag',
34
- 'operation-security-defined',
36
+ 'security-defined',
35
37
  'no-unresolved-refs',
36
38
  'paths-kebab-case',
37
39
  'boolean-parameter-prefixes',
@@ -40,7 +42,7 @@ const builtInRulesList = [
40
42
  'no-identical-paths',
41
43
  'no-ambiguous-paths',
42
44
  'no-undefined-server-variable',
43
- 'no-servers-empty-enum',
45
+ 'no-server-variables-empty-enum',
44
46
  'no-http-verbs-in-paths',
45
47
  'path-excludes-patterns',
46
48
  'request-mime-type',
@@ -51,31 +53,38 @@ const builtInRulesList = [
51
53
  'response-contains-header',
52
54
  'response-contains-property',
53
55
  'scalar-property-missing-example',
56
+ 'spec-components-invalid-map-name',
54
57
  ];
55
58
  const nodeTypesList = [
56
- 'DefinitionRoot',
59
+ 'Root',
57
60
  'Tag',
58
61
  'ExternalDocs',
59
62
  'Server',
60
63
  'ServerVariable',
64
+ 'ServerVariablesMap',
61
65
  'SecurityRequirement',
62
66
  'Info',
63
67
  'Contact',
64
68
  'License',
65
- 'PathMap',
69
+ 'PathsMap',
66
70
  'PathItem',
67
71
  'Parameter',
68
72
  'Operation',
69
73
  'Callback',
74
+ 'CallbacksMap',
70
75
  'RequestBody',
71
- 'MediaTypeMap',
76
+ 'MediaTypesMap',
72
77
  'MediaType',
73
78
  'Example',
79
+ 'ExamplesMap',
74
80
  'Encoding',
81
+ 'EncodingsMap',
75
82
  'Header',
83
+ 'HeadersMap',
76
84
  'ResponsesMap',
77
85
  'Response',
78
86
  'Link',
87
+ 'LinksMap',
79
88
  'Schema',
80
89
  'Xml',
81
90
  'SchemaProperties',
@@ -101,6 +110,39 @@ const nodeTypesList = [
101
110
  'WebhooksMap',
102
111
  ];
103
112
 
113
+ const ConfigStyleguide: NodeType = {
114
+ properties: {
115
+ extends: {
116
+ type: 'array',
117
+ items: {
118
+ type: 'string',
119
+ },
120
+ },
121
+ rules: 'Rules',
122
+ oas2Rules: 'Rules',
123
+ oas3_0Rules: 'Rules',
124
+ oas3_1Rules: 'Rules',
125
+ preprocessors: { type: 'object' },
126
+ oas2Preprocessors: { type: 'object' },
127
+ oas3_0Preprocessors: { type: 'object' },
128
+ oas3_1Preprocessors: { type: 'object' },
129
+ decorators: { type: 'object' },
130
+ oas2Decorators: { type: 'object' },
131
+ oas3_0Decorators: { type: 'object' },
132
+ oas3_1Decorators: { type: 'object' },
133
+ },
134
+ };
135
+
136
+ const RootConfigStyleguide: NodeType = {
137
+ properties: {
138
+ plugins: {
139
+ type: 'array',
140
+ items: { type: 'string' },
141
+ },
142
+ ...ConfigStyleguide.properties,
143
+ },
144
+ };
145
+
104
146
  const ConfigRoot: NodeType = {
105
147
  properties: {
106
148
  organization: { type: 'string' },
@@ -110,7 +152,8 @@ const ConfigRoot: NodeType = {
110
152
  properties: {},
111
153
  additionalProperties: { properties: { type: 'string' } },
112
154
  }, // deprecated
113
- styleguide: 'RootConfigStyleguide',
155
+ ...RootConfigStyleguide.properties,
156
+ styleguide: 'RootConfigStyleguide', // deprecated
114
157
  lint: 'RootConfigStyleguide', // deprecated
115
158
  'features.openapi': 'ConfigReferenceDocs',
116
159
  referenceDocs: 'ConfigReferenceDocs', // deprecated
@@ -119,6 +162,7 @@ const ConfigRoot: NodeType = {
119
162
  resolve: {
120
163
  properties: {
121
164
  http: 'ConfigHTTP',
165
+ doNotResolveExamples: { type: 'boolean' },
122
166
  },
123
167
  },
124
168
  },
@@ -138,7 +182,9 @@ const ConfigApisProperties: NodeType = {
138
182
  type: 'string',
139
183
  },
140
184
  },
141
- styleguide: 'ConfigStyleguide',
185
+ lint: 'ConfigStyleguide', // deprecated
186
+ styleguide: 'ConfigStyleguide', // deprecated
187
+ ...ConfigStyleguide.properties,
142
188
  'features.openapi': 'ConfigReferenceDocs',
143
189
  'features.mockServer': 'ConfigMockServer',
144
190
  },
@@ -156,40 +202,6 @@ const ConfigHTTP: NodeType = {
156
202
  },
157
203
  };
158
204
 
159
- const ConfigStyleguide: NodeType = {
160
- properties: {
161
- extends: {
162
- type: 'array',
163
- items: {
164
- type: 'string',
165
- },
166
- },
167
- doNotResolveExamples: { type: 'boolean' },
168
- rules: 'Rules',
169
- oas2Rules: 'Rules',
170
- oas3_0Rules: 'Rules',
171
- oas3_1Rules: 'Rules',
172
- preprocessors: { type: 'object' },
173
- oas2Preprocessors: { type: 'object' },
174
- oas3_0Preprocessors: { type: 'object' },
175
- oas3_1Preprocessors: { type: 'object' },
176
- decorators: { type: 'object' },
177
- oas2Decorators: { type: 'object' },
178
- oas3_0Decorators: { type: 'object' },
179
- oas3_1Decorators: { type: 'object' },
180
- },
181
- };
182
-
183
- const RootConfigStyleguide: NodeType = {
184
- properties: {
185
- plugins: {
186
- type: 'array',
187
- items: { type: 'string' },
188
- },
189
- ...ConfigStyleguide.properties,
190
- },
191
- };
192
-
193
205
  const Rules: NodeType = {
194
206
  properties: {},
195
207
  additionalProperties: (value: unknown, key: string) => {
package/src/utils.ts CHANGED
@@ -6,7 +6,8 @@ import * as pluralize from 'pluralize';
6
6
  import { parseYaml } from './js-yaml';
7
7
  import { UserContext } from './walk';
8
8
  import { HttpResolveConfig } from './config';
9
- import { env } from './config';
9
+ import { env } from './env';
10
+ import { logger, colorize } from './logger';
10
11
 
11
12
  export { parseYaml, stringifyYaml } from './js-yaml';
12
13
 
@@ -32,7 +33,7 @@ export async function loadYaml<T>(filename: string): Promise<T> {
32
33
  return parseYaml(contents) as T;
33
34
  }
34
35
 
35
- export function notUndefined<T>(x: T | undefined): x is T {
36
+ export function isDefined<T>(x: T | undefined): x is T {
36
37
  return x !== undefined;
37
38
  }
38
39
 
@@ -95,7 +96,7 @@ export function omitObjectProps<T extends Record<string, unknown>>(
95
96
  export function splitCamelCaseIntoWords(str: string) {
96
97
  const camel = str
97
98
  .split(/(?:[-._])|([A-Z][a-z]+)/)
98
- .filter(Boolean)
99
+ .filter(isTruthy)
99
100
  .map((item) => item.toLocaleLowerCase());
100
101
  const caps = str
101
102
  .split(/([A-Z]{2,})/)
@@ -182,7 +183,7 @@ export function isNotString<T>(value: string | T): value is T {
182
183
  }
183
184
 
184
185
  export function assignExisting<T>(target: Record<string, T>, obj: Record<string, T>) {
185
- for (let k of Object.keys(obj)) {
186
+ for (const k of Object.keys(obj)) {
186
187
  if (target.hasOwnProperty(k)) {
187
188
  target[k] = obj[k];
188
189
  }
@@ -204,3 +205,29 @@ export function doesYamlFileExist(filePath: string): boolean {
204
205
  fs.existsSync(filePath)
205
206
  );
206
207
  }
208
+
209
+ export function showWarningForDeprecatedField(deprecatedField: string, updatedField?: string) {
210
+ logger.warn(
211
+ `The '${colorize.red(deprecatedField)}' field is deprecated. ${
212
+ updatedField ? `Use ${colorize.green(updatedField)} instead. ` : ''
213
+ }Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`
214
+ );
215
+ }
216
+
217
+ export function showErrorForDeprecatedField(deprecatedField: string, updatedField?: string) {
218
+ throw new Error(
219
+ `Do not use '${deprecatedField}' field. ${
220
+ updatedField ? `Use '${updatedField}' instead. ` : ''
221
+ }\n`
222
+ );
223
+ }
224
+
225
+ export type Falsy = undefined | null | false | '' | 0;
226
+
227
+ export function isTruthy<Truthy>(value: Truthy | Falsy): value is Truthy {
228
+ return !!value;
229
+ }
230
+
231
+ export function identity<T>(value: T): T {
232
+ return value;
233
+ }
package/src/visitors.ts CHANGED
@@ -27,7 +27,7 @@ import type {
27
27
  Oas3Callback,
28
28
  } from './typings/openapi';
29
29
 
30
- import {
30
+ import type {
31
31
  Oas2Definition,
32
32
  Oas2Tag,
33
33
  Oas2ExternalDocs,
@@ -45,10 +45,11 @@ import {
45
45
  Oas2SecurityScheme,
46
46
  } from './typings/swagger';
47
47
 
48
- import { NormalizedNodeType } from './types';
49
- import { Stack } from './utils';
50
- import { UserContext, ResolveResult, ProblemSeverity } from './walk';
51
- import { Location } from './ref-utils';
48
+ import type { NormalizedNodeType } from './types';
49
+ import type { Stack } from './utils';
50
+ import type { UserContext, ResolveResult, ProblemSeverity } from './walk';
51
+ import type { Location } from './ref-utils';
52
+
52
53
  export type VisitFunction<T> = (
53
54
  node: T,
54
55
  ctx: UserContext & { ignoreNextVisitorsOnNode: () => void },
@@ -70,7 +71,7 @@ type NestedVisitObject<T, P> = VisitObject<T> & NestedVisitor<P>;
70
71
 
71
72
  type VisitFunctionOrObject<T> = VisitFunction<T> | VisitObject<T>;
72
73
 
73
- type VisitorNode<T extends any> = {
74
+ type VisitorNode<T> = {
74
75
  ruleId: string;
75
76
  severity: ProblemSeverity;
76
77
  context: VisitorLevelContext | VisitorSkippedLevelContext;
@@ -126,7 +127,7 @@ export type BaseVisitor = {
126
127
  };
127
128
 
128
129
  type Oas3FlatVisitor = {
129
- DefinitionRoot?: VisitFunctionOrObject<Oas3Definition>;
130
+ Root?: VisitFunctionOrObject<Oas3Definition>;
130
131
  Tag?: VisitFunctionOrObject<Oas3Tag>;
131
132
  ExternalDocs?: VisitFunctionOrObject<Oas3ExternalDocs>;
132
133
  Server?: VisitFunctionOrObject<Oas3Server>;
@@ -135,13 +136,13 @@ type Oas3FlatVisitor = {
135
136
  Info?: VisitFunctionOrObject<Oas3Info>;
136
137
  Contact?: VisitFunctionOrObject<Oas3Contact>;
137
138
  License?: VisitFunctionOrObject<Oas3License>;
138
- PathMap?: VisitFunctionOrObject<Record<string, Oas3PathItem>>;
139
+ PathsMap?: VisitFunctionOrObject<Record<string, Oas3PathItem>>;
139
140
  PathItem?: VisitFunctionOrObject<Oas3PathItem>;
140
141
  Callback?: VisitFunctionOrObject<Record<string, Oas3PathItem>>;
141
142
  Parameter?: VisitFunctionOrObject<Oas3Parameter>;
142
143
  Operation?: VisitFunctionOrObject<Oas3Operation>;
143
144
  RequestBody?: VisitFunctionOrObject<Oas3RequestBody>;
144
- MediaTypeMap?: VisitFunctionOrObject<Record<string, Oas3MediaType>>;
145
+ MediaTypesMap?: VisitFunctionOrObject<Record<string, Oas3MediaType>>;
145
146
  MediaType?: VisitFunctionOrObject<Oas3MediaType>;
146
147
  Example?: VisitFunctionOrObject<Oas3Example>;
147
148
  Encoding?: VisitFunctionOrObject<Oas3Encoding>;
@@ -173,14 +174,14 @@ type Oas3FlatVisitor = {
173
174
  };
174
175
 
175
176
  type Oas2FlatVisitor = {
176
- DefinitionRoot?: VisitFunctionOrObject<Oas2Definition>;
177
+ Root?: VisitFunctionOrObject<Oas2Definition>;
177
178
  Tag?: VisitFunctionOrObject<Oas2Tag>;
178
179
  ExternalDocs?: VisitFunctionOrObject<Oas2ExternalDocs>;
179
180
  SecurityRequirement?: VisitFunctionOrObject<Oas2SecurityRequirement>;
180
181
  Info?: VisitFunctionOrObject<Oas2Info>;
181
182
  Contact?: VisitFunctionOrObject<Oas2Contact>;
182
183
  License?: VisitFunctionOrObject<Oas2License>;
183
- PathMap?: VisitFunctionOrObject<Record<string, Oas2PathItem>>;
184
+ PathsMap?: VisitFunctionOrObject<Record<string, Oas2PathItem>>;
184
185
  PathItem?: VisitFunctionOrObject<Oas2PathItem>;
185
186
  Parameter?: VisitFunctionOrObject<any>;
186
187
  Operation?: VisitFunctionOrObject<Oas2Operation>;
@@ -197,6 +198,18 @@ type Oas2FlatVisitor = {
197
198
  SecurityScheme?: VisitFunctionOrObject<Oas2SecurityScheme>;
198
199
  };
199
200
 
201
+ const legacyTypesMap = {
202
+ Root: 'DefinitionRoot',
203
+ ServerVariablesMap: 'ServerVariableMap',
204
+ PathsMap: 'PathMap',
205
+ CallbacksMap: 'CallbackMap',
206
+ MediaTypesMap: 'MediaTypeMap',
207
+ ExamplesMap: 'ExampleMap',
208
+ EncodingsMap: 'EncodingMap',
209
+ HeadersMap: 'HeaderMap',
210
+ LinksMap: 'LinkMap',
211
+ };
212
+
200
213
  type Oas3NestedVisitor = {
201
214
  [T in keyof Oas3FlatVisitor]: Oas3FlatVisitor[T] extends Function
202
215
  ? Oas3FlatVisitor[T]
@@ -225,7 +238,7 @@ export type Oas2TransformVisitor = BaseVisitor &
225
238
  Oas2FlatVisitor &
226
239
  Record<string, VisitFunction<any> | VisitObject<any>>;
227
240
 
228
- export type NestedVisitor<T> = Exclude<T, 'any' | 'ref' | 'DefinitionRoot'>;
241
+ export type NestedVisitor<T> = Exclude<T, 'any' | 'ref' | 'Root'>;
229
242
 
230
243
  export type NormalizedOasVisitors<T extends BaseVisitor> = {
231
244
  [V in keyof T]-?: {
@@ -309,7 +322,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
309
322
 
310
323
  const possibleChildren = new Set<NormalizedNodeType>();
311
324
 
312
- for (let type of Object.values(from.properties)) {
325
+ for (const type of Object.values(from.properties)) {
313
326
  if (type === to) {
314
327
  addWeakFromStack(ruleConf, stack);
315
328
  continue;
@@ -333,7 +346,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
333
346
  }
334
347
  }
335
348
 
336
- for (let fromType of Array.from(possibleChildren.values())) {
349
+ for (const fromType of Array.from(possibleChildren.values())) {
337
350
  addWeakNodes(ruleConf, fromType, to, parentContext, stack);
338
351
  }
339
352
 
@@ -350,7 +363,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
350
363
  visit: () => undefined,
351
364
  depth: 0,
352
365
  context: {
353
- isSkippedLevel: true as true,
366
+ isSkippedLevel: true,
354
367
  seen: new Set(),
355
368
  parent: parentContext,
356
369
  },
@@ -380,8 +393,11 @@ export function normalizeVisitors<T extends BaseVisitor>(
380
393
  }
381
394
 
382
395
  for (const typeName of visitorKeys as Array<keyof T>) {
383
- const typeVisitor = visitor[typeName] as any as NestedVisitObject<any, T>;
384
- const normalizedTypeVisitor = normalizedVisitors[typeName]!;
396
+ const typeVisitor = (visitor[typeName] ||
397
+ visitor[
398
+ legacyTypesMap[typeName as keyof typeof legacyTypesMap] as keyof T
399
+ ]) as any as NestedVisitObject<any, T>;
400
+ const normalizedTypeVisitor = normalizedVisitors[typeName];
385
401
 
386
402
  if (!typeVisitor) continue;
387
403
 
@@ -407,7 +423,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
407
423
  activatedOn: null,
408
424
  type: types[typeName],
409
425
  parent: parentContext,
410
- isSkippedLevel: false as false,
426
+ isSkippedLevel: false,
411
427
  };
412
428
 
413
429
  if (typeof typeVisitor === 'object') {
package/src/walk.ts CHANGED
@@ -18,6 +18,8 @@ import {
18
18
  import { pushStack, popStack } from './utils';
19
19
  import { OasVersion } from './oas-types';
20
20
  import { NormalizedNodeType, isNamedType } from './types';
21
+ import type { RuleSeverity } from './config';
22
+
21
23
  type NonUndefined = string | number | boolean | symbol | bigint | object | Record<string, any>;
22
24
 
23
25
  export type ResolveResult<T extends NonUndefined> =
@@ -66,7 +68,7 @@ export type Problem = {
66
68
  suggest?: string[];
67
69
  location?: Partial<LocationObject> | Array<Partial<LocationObject>>;
68
70
  from?: LocationObject;
69
- forceSeverity?: ProblemSeverity;
71
+ forceSeverity?: RuleSeverity;
70
72
  ruleId?: string;
71
73
  };
72
74
 
@@ -409,17 +411,19 @@ export function walkDocument<T>(opts: {
409
411
  : [opts.location]
410
412
  : [{ ...currentLocation, reportOnKey: false }];
411
413
 
412
- ctx.problems.push({
413
- ruleId: opts.ruleId || ruleId,
414
- severity: opts.forceSeverity || severity,
415
- ...opts,
416
- suggest: opts.suggest || [],
417
- location: loc.map((loc: any) => {
418
- return { ...currentLocation, reportOnKey: false, ...loc };
419
- }),
420
- });
414
+ const ruleSeverity = opts.forceSeverity || severity;
415
+ if (ruleSeverity !== 'off') {
416
+ ctx.problems.push({
417
+ ruleId: opts.ruleId || ruleId,
418
+ severity: ruleSeverity,
419
+ ...opts,
420
+ suggest: opts.suggest || [],
421
+ location: loc.map((loc: any) => {
422
+ return { ...currentLocation, reportOnKey: false, ...loc };
423
+ }),
424
+ });
425
+ }
421
426
  }
422
-
423
427
  function getVisitorDataFn(ruleId: string) {
424
428
  ctx.visitorsData[ruleId] = ctx.visitorsData[ruleId] || {};
425
429
  return ctx.visitorsData[ruleId];