@redocly/openapi-core 1.18.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/lib/benchmark/benches/lint-with-many-rules.bench.js +2 -2
  3. package/lib/benchmark/benches/lint-with-nested-rule.bench.js +2 -2
  4. package/lib/benchmark/benches/lint-with-no-rules.bench.js +2 -2
  5. package/lib/benchmark/benches/lint-with-top-level-rule-report.bench.js +2 -2
  6. package/lib/benchmark/benches/lint-with-top-level-rule.bench.js +2 -2
  7. package/lib/benchmark/benches/recommended-oas3.bench.js +2 -2
  8. package/lib/benchmark/benches/resolve-with-no-external.bench.js +2 -2
  9. package/lib/benchmark/utils.js +7 -4
  10. package/lib/bundle.d.ts +3 -3
  11. package/lib/bundle.js +128 -122
  12. package/lib/config/all.js +9 -0
  13. package/lib/config/builtIn.js +7 -1
  14. package/lib/config/config-resolvers.js +179 -138
  15. package/lib/config/config.d.ts +2 -2
  16. package/lib/config/config.js +53 -34
  17. package/lib/config/load.d.ts +1 -2
  18. package/lib/config/load.js +105 -117
  19. package/lib/config/minimal.js +9 -0
  20. package/lib/config/recommended-strict.js +9 -0
  21. package/lib/config/recommended.js +9 -0
  22. package/lib/config/rules.d.ts +3 -3
  23. package/lib/config/rules.js +1 -2
  24. package/lib/config/types.d.ts +9 -3
  25. package/lib/config/utils.js +70 -49
  26. package/lib/decorators/async3/index.d.ts +1 -0
  27. package/lib/decorators/async3/index.js +4 -0
  28. package/lib/decorators/common/filters/filter-helper.js +2 -3
  29. package/lib/decorators/common/filters/filter-in.js +1 -1
  30. package/lib/decorators/common/filters/filter-out.js +1 -1
  31. package/lib/decorators/common/info-override.js +1 -12
  32. package/lib/decorators/common/media-type-examples-override.js +8 -2
  33. package/lib/decorators/common/remove-x-internal.js +4 -5
  34. package/lib/decorators/oas2/remove-unused-components.js +1 -2
  35. package/lib/decorators/oas3/remove-unused-components.js +1 -2
  36. package/lib/env.d.ts +0 -1
  37. package/lib/env.js +1 -1
  38. package/lib/format/codeframes.js +10 -8
  39. package/lib/format/format.js +23 -15
  40. package/lib/index.d.ts +2 -1
  41. package/lib/index.js +6 -4
  42. package/lib/js-yaml/index.js +1 -1
  43. package/lib/lint.d.ts +2 -0
  44. package/lib/lint.js +92 -99
  45. package/lib/oas-types.d.ts +9 -5
  46. package/lib/oas-types.js +22 -12
  47. package/lib/redocly/domains.js +6 -6
  48. package/lib/redocly/index.js +60 -73
  49. package/lib/redocly/registry-api.js +64 -82
  50. package/lib/ref-utils.js +13 -13
  51. package/lib/resolve.js +186 -205
  52. package/lib/rules/ajv.js +10 -8
  53. package/lib/rules/async3/channels-kebab-case.d.ts +2 -0
  54. package/lib/rules/async3/channels-kebab-case.js +19 -0
  55. package/lib/rules/async3/index.d.ts +3 -0
  56. package/lib/rules/async3/index.js +22 -0
  57. package/lib/rules/async3/no-channel-trailing-slash.d.ts +2 -0
  58. package/lib/rules/async3/no-channel-trailing-slash.js +16 -0
  59. package/lib/rules/common/assertions/asserts.js +5 -5
  60. package/lib/rules/common/assertions/index.d.ts +5 -4
  61. package/lib/rules/common/assertions/utils.js +43 -28
  62. package/lib/rules/common/no-invalid-parameter-examples.js +1 -2
  63. package/lib/rules/common/no-invalid-schema-examples.js +1 -2
  64. package/lib/rules/common/no-required-schema-properties-undefined.js +1 -2
  65. package/lib/rules/common/operation-tag-defined.js +1 -2
  66. package/lib/rules/common/path-http-verbs-order.js +1 -1
  67. package/lib/rules/common/path-segment-plural.js +2 -1
  68. package/lib/rules/common/required-string-property-missing-min-length.js +2 -2
  69. package/lib/rules/common/response-contains-header.js +2 -2
  70. package/lib/rules/common/security-defined.js +3 -7
  71. package/lib/rules/common/spec.d.ts +2 -2
  72. package/lib/rules/common/spec.js +6 -7
  73. package/lib/rules/no-unresolved-refs.js +3 -4
  74. package/lib/rules/oas2/response-contains-property.js +1 -2
  75. package/lib/rules/oas3/array-parameter-serialization.js +1 -2
  76. package/lib/rules/oas3/component-name-unique.js +2 -4
  77. package/lib/rules/oas3/no-invalid-media-type-examples.js +1 -2
  78. package/lib/rules/oas3/no-server-variables-empty-enum.js +1 -2
  79. package/lib/rules/oas3/no-undefined-server-variable.js +2 -3
  80. package/lib/rules/oas3/no-unused-components.js +1 -2
  81. package/lib/rules/oas3/response-contains-property.js +1 -2
  82. package/lib/rules/utils.js +14 -12
  83. package/lib/types/arazzo.d.ts +1299 -73
  84. package/lib/types/arazzo.js +41 -36
  85. package/lib/types/asyncapi2.d.ts +17 -0
  86. package/lib/types/{asyncapi.js → asyncapi2.js} +71 -93
  87. package/lib/types/asyncapi3.d.ts +2 -0
  88. package/lib/types/asyncapi3.js +347 -0
  89. package/lib/types/index.js +19 -10
  90. package/lib/types/json-schema-adapter.js +4 -18
  91. package/lib/types/oas2.js +6 -6
  92. package/lib/types/oas3.js +10 -10
  93. package/lib/types/oas3_1.js +15 -9
  94. package/lib/types/redocly-yaml.d.ts +3 -1
  95. package/lib/types/redocly-yaml.js +131 -35
  96. package/lib/typings/arazzo.d.ts +28 -1
  97. package/lib/typings/asyncapi3.d.ts +53 -0
  98. package/lib/typings/asyncapi3.js +2 -0
  99. package/lib/utils.d.ts +12 -7
  100. package/lib/utils.js +91 -77
  101. package/lib/visitors.d.ts +11 -0
  102. package/lib/visitors.js +21 -8
  103. package/lib/walk.js +30 -23
  104. package/package.json +3 -3
  105. package/src/__tests__/bundle.test.ts +142 -0
  106. package/src/__tests__/lint.test.ts +0 -50
  107. package/src/bundle.ts +19 -6
  108. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +22 -0
  109. package/src/config/__tests__/__snapshots__/config.test.ts.snap +24 -0
  110. package/src/config/__tests__/config.test.ts +11 -0
  111. package/src/config/all.ts +9 -0
  112. package/src/config/builtIn.ts +6 -0
  113. package/src/config/config-resolvers.ts +15 -2
  114. package/src/config/config.ts +24 -5
  115. package/src/config/load.ts +1 -2
  116. package/src/config/minimal.ts +9 -0
  117. package/src/config/recommended-strict.ts +9 -0
  118. package/src/config/recommended.ts +9 -0
  119. package/src/config/rules.ts +12 -4
  120. package/src/config/types.ts +15 -2
  121. package/src/config/utils.ts +15 -0
  122. package/src/decorators/async3/index.ts +1 -0
  123. package/src/decorators/common/remove-x-internal.ts +2 -2
  124. package/src/index.ts +2 -1
  125. package/src/lint.ts +26 -3
  126. package/src/oas-types.ts +31 -13
  127. package/src/rules/arazzo/index.ts +1 -1
  128. package/src/rules/async2/index.ts +5 -5
  129. package/src/rules/async3/__tests__/channels-kebab-case.test.ts +141 -0
  130. package/src/rules/async3/__tests__/no-channel-trailing-slash.test.ts +96 -0
  131. package/src/rules/async3/channels-kebab-case.ts +19 -0
  132. package/src/rules/async3/index.ts +23 -0
  133. package/src/rules/async3/no-channel-trailing-slash.ts +16 -0
  134. package/src/rules/common/__tests__/spec.test.ts +47 -0
  135. package/src/rules/common/assertions/index.ts +13 -4
  136. package/src/rules/common/no-invalid-schema-examples.ts +3 -2
  137. package/src/rules/common/path-segment-plural.ts +3 -2
  138. package/src/rules/common/spec.ts +2 -2
  139. package/src/rules/oas2/index.ts +4 -4
  140. package/src/rules/oas3/index.ts +39 -37
  141. package/src/types/arazzo.ts +28 -23
  142. package/src/types/{asyncapi.ts → asyncapi2.ts} +58 -76
  143. package/src/types/asyncapi3.ts +381 -0
  144. package/src/types/oas3_1.ts +3 -2
  145. package/src/types/redocly-yaml.ts +14 -0
  146. package/src/typings/arazzo.ts +41 -1
  147. package/src/typings/asyncapi3.ts +61 -0
  148. package/src/utils.ts +46 -11
  149. package/src/visitors.ts +18 -0
  150. package/tsconfig.tsbuildinfo +1 -1
  151. package/lib/types/asyncapi.d.ts +0 -2
@@ -92,8 +92,20 @@ const builtInAsync2Rules = [
92
92
  'no-channel-trailing-slash',
93
93
  ] as const;
94
94
 
95
+ const builtInAsync3Rules = [
96
+ 'spec',
97
+ 'info-contact',
98
+ 'operation-operationId',
99
+ 'tag-description',
100
+ 'tags-alphabetical',
101
+ 'channels-kebab-case',
102
+ 'no-channel-trailing-slash',
103
+ ] as const;
104
+
95
105
  export type BuiltInAsync2RuleId = typeof builtInAsync2Rules[number];
96
106
 
107
+ export type BuiltInAsync3RuleId = typeof builtInAsync3Rules[number];
108
+
97
109
  const builtInArazzoRules = ['spec'] as const;
98
110
 
99
111
  export type BuiltInArazzoRuleId = typeof builtInArazzoRules[number];
@@ -103,6 +115,7 @@ const builtInRules = [
103
115
  ...builtInOAS2Rules,
104
116
  ...builtInOAS3Rules,
105
117
  ...builtInAsync2Rules,
118
+ ...builtInAsync3Rules,
106
119
  ...builtInArazzoRules,
107
120
  ] as const;
108
121
 
@@ -221,6 +234,7 @@ const oas3_1NodeTypesList = [
221
234
  'Root',
222
235
  'Schema',
223
236
  'SchemaProperties',
237
+ 'PatternProperties',
224
238
  'Info',
225
239
  'License',
226
240
  'Components',
@@ -1,4 +1,44 @@
1
1
  import type { FromSchema } from 'json-schema-to-ts';
2
- import type { arazzoSchema } from '../types/arazzo';
2
+ import type {
3
+ arazzoSchema,
4
+ parameter,
5
+ operationMethod,
6
+ expectSchema,
7
+ sourceDescriptionSchema,
8
+ infoObject,
9
+ requestBody,
10
+ replacement,
11
+ inherit,
12
+ criteriaObject,
13
+ step,
14
+ workflow,
15
+ } from '../types/arazzo';
3
16
 
4
17
  export type ArazzoDefinition = FromSchema<typeof arazzoSchema>;
18
+ export type OperationMethod = FromSchema<typeof operationMethod>;
19
+ export type ResponseContext = {
20
+ statusCode: number;
21
+ body: any;
22
+ headers: Headers;
23
+ mimeType: string;
24
+ } & Record<string, any>;
25
+ export type Expect = FromSchema<typeof expectSchema>;
26
+ export type SourceDescription = FromSchema<typeof sourceDescriptionSchema>;
27
+ export type Parameter = FromSchema<typeof parameter>;
28
+ export type InfoObject = FromSchema<typeof infoObject>;
29
+ export type RequestBody = FromSchema<typeof requestBody>;
30
+ export type Replacement = FromSchema<typeof replacement>;
31
+ export type Inherit = FromSchema<typeof inherit>;
32
+ export type CriteriaObject = FromSchema<typeof criteriaObject>;
33
+ export type VerboseLog = {
34
+ method: OperationMethod;
35
+ path: string;
36
+ host: string;
37
+ body?: any;
38
+ headerParams?: Record<string, string>;
39
+ statusCode?: number;
40
+ };
41
+ export type Step = FromSchema<typeof step>;
42
+ export type Workflow = FromSchema<typeof workflow> & {
43
+ steps: Step[];
44
+ };
@@ -0,0 +1,61 @@
1
+ export interface Async3Definition {
2
+ asyncapi: string;
3
+ servers?: Record<string, any>;
4
+ info: Async3Info;
5
+ channels?: Record<string, Channel>;
6
+ components?: Record<string, any>;
7
+ operations?: Record<string, any>;
8
+ defaultContentType?: string;
9
+ }
10
+
11
+ export interface Async3Info {
12
+ title: string;
13
+ version: string;
14
+
15
+ description?: string;
16
+ termsOfService?: string;
17
+ contact?: Async3Contact;
18
+ license?: Async3License;
19
+ tags?: Tag[];
20
+ externalDocs?: ExternalDoc;
21
+ }
22
+
23
+ export interface Async3Contact {
24
+ name?: string;
25
+ url?: string;
26
+ email?: string;
27
+ }
28
+
29
+ export interface Async3License {
30
+ name: string;
31
+ url?: string;
32
+ }
33
+
34
+ export interface Tag {
35
+ name: string;
36
+ description?: string;
37
+ externalDocs?: ExternalDoc;
38
+ }
39
+
40
+ export interface ExternalDoc {
41
+ url: string;
42
+ description?: string;
43
+ }
44
+
45
+ export interface Channel {
46
+ address?: string | null;
47
+ messages?: Record<string, any>;
48
+ title?: string;
49
+ summary?: string;
50
+ description?: string;
51
+ servers?: Record<string, any>[];
52
+ parameters?: Record<string, any>;
53
+ tags?: Record<string, any>;
54
+ externalDocs?: ExternalDocumentation;
55
+ bindings?: Record<string, any>;
56
+ }
57
+
58
+ export interface ExternalDocumentation {
59
+ url: string;
60
+ description?: string;
61
+ }
package/src/utils.ts CHANGED
@@ -2,14 +2,14 @@ import * as fs from 'fs';
2
2
  import { extname } from 'path';
3
3
  import * as minimatch from 'minimatch';
4
4
  import fetch from 'node-fetch';
5
- import * as pluralize from 'pluralize';
6
5
  import { parseYaml } from './js-yaml';
7
- import { UserContext } from './walk';
8
6
  import { env } from './env';
9
7
  import { logger, colorize } from './logger';
10
- import { HttpResolveConfig } from './config';
11
8
  import { HttpsProxyAgent } from 'https-proxy-agent';
12
9
 
10
+ import type { HttpResolveConfig } from './config';
11
+ import type { UserContext } from './walk';
12
+
13
13
  export { parseYaml, stringifyYaml } from './js-yaml';
14
14
 
15
15
  export type StackFrame<T> = {
@@ -38,15 +38,15 @@ export function isDefined<T>(x: T | undefined): x is T {
38
38
  return x !== undefined;
39
39
  }
40
40
 
41
- export function isPlainObject(value: any): value is Record<string, unknown> {
41
+ export function isPlainObject(value: unknown): value is Record<string, unknown> {
42
42
  return value !== null && typeof value === 'object' && !Array.isArray(value);
43
43
  }
44
44
 
45
- export function isEmptyObject(value: any): value is Record<string, unknown> {
45
+ export function isEmptyObject(value: unknown): value is Record<string, unknown> {
46
46
  return isPlainObject(value) && Object.keys(value).length === 0;
47
47
  }
48
48
 
49
- export function isEmptyArray(value: any) {
49
+ export function isEmptyArray(value: unknown) {
50
50
  return Array.isArray(value) && value.length === 0;
51
51
  }
52
52
 
@@ -146,10 +146,6 @@ export function validateMimeTypeOAS3(
146
146
  }
147
147
  }
148
148
 
149
- export function isSingular(path: string) {
150
- return pluralize.isSingular(path);
151
- }
152
-
153
149
  export function readFileAsStringSync(filePath: string) {
154
150
  return fs.readFileSync(filePath, 'utf-8');
155
151
  }
@@ -267,7 +263,7 @@ export function pickDefined<T extends Record<string, unknown>>(
267
263
  }
268
264
 
269
265
  export function nextTick() {
270
- new Promise((resolve) => {
266
+ return new Promise((resolve) => {
271
267
  setTimeout(resolve);
272
268
  });
273
269
  }
@@ -284,3 +280,42 @@ export function getProxyAgent() {
284
280
  const proxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
285
281
  return proxy ? new HttpsProxyAgent(proxy) : undefined;
286
282
  }
283
+
284
+ /**
285
+ * Checks if two objects are deeply equal.
286
+ * Borrowed the source code from https://github.com/lukeed/dequal.
287
+ */
288
+ export function dequal(foo: any, bar: any): boolean {
289
+ let ctor, len;
290
+ if (foo === bar) return true;
291
+
292
+ if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
293
+ if (ctor === Date) return foo.getTime() === bar.getTime();
294
+ if (ctor === RegExp) return foo.toString() === bar.toString();
295
+
296
+ if (ctor === Array) {
297
+ if ((len = foo.length) === bar.length) {
298
+ while (len-- && dequal(foo[len], bar[len]));
299
+ }
300
+ return len === -1;
301
+ }
302
+
303
+ if (!ctor || typeof foo === 'object') {
304
+ len = 0;
305
+ for (ctor in foo) {
306
+ if (
307
+ Object.prototype.hasOwnProperty.call(foo, ctor) &&
308
+ ++len &&
309
+ !Object.prototype.hasOwnProperty.call(bar, ctor)
310
+ )
311
+ return false;
312
+ if (!(ctor in bar) || !dequal(foo[ctor], bar[ctor])) return false;
313
+ }
314
+ return Object.keys(bar).length === len;
315
+ }
316
+ }
317
+
318
+ return foo !== foo && bar !== bar;
319
+ }
320
+
321
+ export type CollectFn = (value: unknown) => void;
package/src/visitors.ts CHANGED
@@ -50,6 +50,7 @@ import type {
50
50
  Oas2SecurityScheme,
51
51
  } from './typings/swagger';
52
52
  import type { Async2Definition } from './typings/asyncapi';
53
+ import type { Async3Definition } from './typings/asyncapi3';
53
54
  import type { ArazzoDefinition } from './typings/arazzo';
54
55
 
55
56
  export type SkipFunctionContext = Pick<
@@ -213,6 +214,10 @@ type Async2FlatVisitor = {
213
214
  Root?: VisitFunctionOrObject<Async2Definition>;
214
215
  };
215
216
 
217
+ type Async3FlatVisitor = {
218
+ Root?: VisitFunctionOrObject<Async3Definition>;
219
+ };
220
+
216
221
  type ArazzoFlatVisitor = {
217
222
  Root?: VisitFunctionOrObject<ArazzoDefinition>;
218
223
  };
@@ -249,6 +254,12 @@ type Async2NestedVisitor = {
249
254
  : Async2FlatVisitor[T] & NestedVisitor<Async2NestedVisitor>;
250
255
  };
251
256
 
257
+ type Async3NestedVisitor = {
258
+ [T in keyof Async3FlatVisitor]: Async3FlatVisitor[T] extends Function
259
+ ? Async3FlatVisitor[T]
260
+ : Async3FlatVisitor[T] & NestedVisitor<Async3NestedVisitor>;
261
+ };
262
+
252
263
  type ArazzoNestedVisitor = {
253
264
  [T in keyof ArazzoFlatVisitor]: ArazzoFlatVisitor[T] extends Function
254
265
  ? ArazzoFlatVisitor[T]
@@ -267,6 +278,10 @@ export type Async2Visitor = BaseVisitor &
267
278
  Async2NestedVisitor &
268
279
  Record<string, VisitFunction<any> | NestedVisitObject<any, Async2NestedVisitor>>;
269
280
 
281
+ export type Async3Visitor = BaseVisitor &
282
+ Async3NestedVisitor &
283
+ Record<string, VisitFunction<any> | NestedVisitObject<any, Async3NestedVisitor>>;
284
+
270
285
  export type ArazzoVisitor = BaseVisitor &
271
286
  ArazzoNestedVisitor &
272
287
  Record<string, VisitFunction<any> | NestedVisitObject<any, ArazzoNestedVisitor>>;
@@ -293,14 +308,17 @@ export type NormalizedOasVisitors<T extends BaseVisitor> = {
293
308
  export type Oas3Rule = (options: Record<string, any>) => Oas3Visitor | Oas3Visitor[];
294
309
  export type Oas2Rule = (options: Record<string, any>) => Oas2Visitor | Oas2Visitor[];
295
310
  export type Async2Rule = (options: Record<string, any>) => Async2Visitor | Async2Visitor[];
311
+ export type Async3Rule = (options: Record<string, any>) => Async3Visitor | Async3Visitor[];
296
312
  export type ArazzoRule = (options: Record<string, any>) => ArazzoVisitor | ArazzoVisitor[];
297
313
  export type Oas3Preprocessor = (options: Record<string, any>) => Oas3Visitor;
298
314
  export type Oas2Preprocessor = (options: Record<string, any>) => Oas2Visitor;
299
315
  export type Async2Preprocessor = (options: Record<string, any>) => Async2Visitor;
316
+ export type Async3Preprocessor = (options: Record<string, any>) => Async3Visitor;
300
317
  export type ArazzoPreprocessor = (options: Record<string, any>) => ArazzoVisitor;
301
318
  export type Oas3Decorator = (options: Record<string, any>) => Oas3Visitor;
302
319
  export type Oas2Decorator = (options: Record<string, any>) => Oas2Visitor;
303
320
  export type Async2Decorator = (options: Record<string, any>) => Async2Visitor;
321
+ export type Async3Decorator = (options: Record<string, any>) => Async3Visitor;
304
322
  export type ArazzoDecorator = (options: Record<string, any>) => ArazzoVisitor;
305
323
 
306
324
  // alias for the latest version supported