@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
@@ -274,3 +274,145 @@ describe('bundleFromString', () => {
274
274
  expect(rest.source.body).toEqual(stringDocument);
275
275
  });
276
276
  });
277
+
278
+ describe('bundle async', () => {
279
+ it('should bundle async of version 2.x', async () => {
280
+ const testDocument = parseYamlToDocument(
281
+ outdent`
282
+ asyncapi: '2.6.0'
283
+ info:
284
+ title: Account Service
285
+ version: 1.0.0
286
+ description: This service is in charge of processing user signups
287
+ channels:
288
+ user/signedup:
289
+ subscribe:
290
+ message:
291
+ $ref: '#/components/messages/UserSignedUp'
292
+ components:
293
+ schemas:
294
+ UserSignedUp:
295
+ type: object
296
+ properties:
297
+ displayName:
298
+ type: string
299
+ description: Name of the user
300
+ messages:
301
+ UserSignedUp:
302
+ payload:
303
+ $ref: '#/components/schemas/UserSignedUp'
304
+ `,
305
+ ''
306
+ );
307
+
308
+ const config = await makeConfig({});
309
+
310
+ const {
311
+ bundle: { parsed },
312
+ problems,
313
+ } = await bundleDocument({
314
+ document: testDocument,
315
+ config: config,
316
+ externalRefResolver: new BaseResolver(),
317
+ dereference: true,
318
+ });
319
+
320
+ expect(problems).toHaveLength(0);
321
+ expect(parsed).toMatchInlineSnapshot(`
322
+ asyncapi: 2.6.0
323
+ info:
324
+ title: Account Service
325
+ version: 1.0.0
326
+ description: This service is in charge of processing user signups
327
+ channels:
328
+ user/signedup:
329
+ subscribe:
330
+ message:
331
+ payload: &ref_1
332
+ type: object
333
+ properties: &ref_0
334
+ displayName:
335
+ type: string
336
+ description: Name of the user
337
+ components:
338
+ schemas:
339
+ UserSignedUp:
340
+ type: object
341
+ properties: *ref_0
342
+ messages:
343
+ UserSignedUp:
344
+ payload: *ref_1
345
+
346
+ `);
347
+ });
348
+
349
+ it('should bundle async of version 3.0', async () => {
350
+ const testDocument = parseYamlToDocument(
351
+ outdent`
352
+ asyncapi: 3.0.0
353
+ info:
354
+ title: Account Service
355
+ version: 1.0.0
356
+ description: This service is in charge of processing user signups
357
+ operations:
358
+ sendUserSignedup:
359
+ action: send
360
+ messages:
361
+ - $ref: '#/components/messages/UserSignedUp'
362
+ components:
363
+ schemas:
364
+ UserSignedUp:
365
+ type: object
366
+ properties:
367
+ displayName:
368
+ type: string
369
+ description: Name of the user
370
+ messages:
371
+ UserSignedUp:
372
+ payload:
373
+ $ref: '#/components/schemas/UserSignedUp'
374
+ `,
375
+ ''
376
+ );
377
+
378
+ const config = await makeConfig({});
379
+
380
+ const {
381
+ bundle: { parsed },
382
+ problems,
383
+ } = await bundleDocument({
384
+ document: testDocument,
385
+ config: config,
386
+ externalRefResolver: new BaseResolver(),
387
+ dereference: true,
388
+ });
389
+
390
+ expect(problems).toHaveLength(0);
391
+ expect(parsed).toMatchInlineSnapshot(`
392
+ asyncapi: 3.0.0
393
+ info:
394
+ title: Account Service
395
+ version: 1.0.0
396
+ description: This service is in charge of processing user signups
397
+ operations:
398
+ sendUserSignedup:
399
+ action: send
400
+ messages:
401
+ - payload: &ref_1
402
+ type: object
403
+ properties: &ref_0
404
+ displayName:
405
+ type: string
406
+ description: Name of the user
407
+ components:
408
+ schemas:
409
+ UserSignedUp:
410
+ type: object
411
+ properties: *ref_0
412
+ messages:
413
+ UserSignedUp:
414
+ payload: *ref_1
415
+
416
+ `);
417
+ });
418
+ });
@@ -104,14 +104,6 @@ const testPortalConfig = parseYamlToDocument(
104
104
  # configurationUrl: Must be reported as a missing required prop
105
105
  clientSecret: '{{ process.env.secret }}'
106
106
 
107
- basic:
108
- type: BASIC
109
- credentials:
110
- - teams:
111
- - 789 # Must be a string
112
- - correct
113
- # username: Must be reported as a missing required prop
114
-
115
107
  sso:
116
108
  - WRONG # Does not match allowed options
117
109
 
@@ -393,20 +385,6 @@ describe('lint', () => {
393
385
  "severity": "error",
394
386
  "suggest": [],
395
387
  },
396
- {
397
- "from": undefined,
398
- "location": [
399
- {
400
- "pointer": "#/theme/openapi/showConsole",
401
- "reportOnKey": true,
402
- "source": "",
403
- },
404
- ],
405
- "message": "Property \`showConsole\` is not expected here.",
406
- "ruleId": "configuration spec",
407
- "severity": "error",
408
- "suggest": [],
409
- },
410
388
  {
411
389
  "from": undefined,
412
390
  "location": [
@@ -912,34 +890,6 @@ describe('lint', () => {
912
890
  "severity": "error",
913
891
  "suggest": [],
914
892
  },
915
- {
916
- "from": undefined,
917
- "location": [
918
- {
919
- "pointer": "#/ssoOnPrem/basic/credentials/0",
920
- "reportOnKey": true,
921
- "source": "",
922
- },
923
- ],
924
- "message": "The field \`username\` must be present on this level.",
925
- "ruleId": "configuration spec",
926
- "severity": "error",
927
- "suggest": [],
928
- },
929
- {
930
- "from": undefined,
931
- "location": [
932
- {
933
- "pointer": "#/ssoOnPrem/basic/credentials/0/teams/0",
934
- "reportOnKey": false,
935
- "source": "",
936
- },
937
- ],
938
- "message": "Expected type \`string\` but got \`integer\`.",
939
- "ruleId": "configuration spec",
940
- "severity": "error",
941
- "suggest": [],
942
- },
943
893
  {
944
894
  "from": undefined,
945
895
  "location": [
package/src/bundle.ts CHANGED
@@ -1,4 +1,3 @@
1
- import isEqual = require('lodash.isequal');
2
1
  import { BaseResolver, resolveDocument, makeRefId, makeDocumentFromString } from './resolve';
3
2
  import { normalizeVisitors } from './visitors';
4
3
  import { normalizeTypes } from './types';
@@ -13,20 +12,19 @@ import {
13
12
  import { isAbsoluteUrl, isRef, Location, refBaseName } from './ref-utils';
14
13
  import { initRules } from './config/rules';
15
14
  import { reportUnresolvedRef } from './rules/no-unresolved-refs';
16
- import { isPlainObject, isTruthy } from './utils';
15
+ import { dequal, isPlainObject, isTruthy } from './utils';
17
16
  import { isRedoclyRegistryURL } from './redocly/domains';
18
17
  import { RemoveUnusedComponents as RemoveUnusedComponentsOas2 } from './decorators/oas2/remove-unused-components';
19
18
  import { RemoveUnusedComponents as RemoveUnusedComponentsOas3 } from './decorators/oas3/remove-unused-components';
20
19
  import { ConfigTypes } from './types/redocly-yaml';
21
20
 
22
- import type { Oas3Rule, Oas3Visitor, Oas2Visitor } from './visitors';
21
+ import type { Oas3Visitor, Oas2Visitor } from './visitors';
23
22
  import type { NormalizedNodeType, NodeType } from './types';
24
23
  import type { WalkContext, UserContext, ResolveResult, NormalizedProblem } from './walk';
25
24
  import type { Config, StyleguideConfig } from './config';
26
25
  import type { OasRef } from './typings/openapi';
27
26
  import type { Document, ResolvedRefMap } from './resolve';
28
-
29
- export type Oas3RuleSet = Record<string, Oas3Rule>;
27
+ import type { CollectFn } from './utils';
30
28
 
31
29
  export enum OasVersion {
32
30
  Version2 = 'oas2',
@@ -85,6 +83,7 @@ export async function bundle(
85
83
  opts: {
86
84
  ref?: string;
87
85
  doc?: Document;
86
+ collectSpecData?: CollectFn;
88
87
  } & BundleOptions
89
88
  ) {
90
89
  const {
@@ -103,6 +102,7 @@ export async function bundle(
103
102
  if (document instanceof Error) {
104
103
  throw document;
105
104
  }
105
+ opts.collectSpecData?.(document.parsed);
106
106
 
107
107
  return bundleDocument({
108
108
  document,
@@ -293,6 +293,15 @@ export function mapTypeToComponent(typeName: string, version: SpecMajorVersion)
293
293
  default:
294
294
  return null;
295
295
  }
296
+ case SpecMajorVersion.Async3:
297
+ switch (typeName) {
298
+ case 'Schema':
299
+ return 'schemas';
300
+ case 'Parameter':
301
+ return 'parameters';
302
+ default:
303
+ return null;
304
+ }
296
305
  case SpecMajorVersion.Arazzo:
297
306
  switch (typeName) {
298
307
  case 'Root.x-parameters_items':
@@ -378,6 +387,8 @@ function makeBundleVisitor(
378
387
  components = root;
379
388
  } else if (version === SpecMajorVersion.Async2) {
380
389
  components = root.components = root.components || {};
390
+ } else if (version === SpecMajorVersion.Async3) {
391
+ components = root.components = root.components || {};
381
392
  } else if (version === SpecMajorVersion.Arazzo) {
382
393
  components = root.components = root.components || {};
383
394
  }
@@ -428,6 +439,8 @@ function makeBundleVisitor(
428
439
  components[componentType][name] = target.node;
429
440
  if (version === SpecMajorVersion.OAS3) {
430
441
  return `#/components/${componentType}/${name}`;
442
+ } else if (version === SpecMajorVersion.Async2 || version === SpecMajorVersion.Async3) {
443
+ return `#/components/${componentType}/${name}`;
431
444
  } else {
432
445
  return `#/${componentType}/${name}`;
433
446
  }
@@ -446,7 +459,7 @@ function makeBundleVisitor(
446
459
  return true;
447
460
  }
448
461
 
449
- return isEqual(node, target.node);
462
+ return dequal(node, target.node);
450
463
  }
451
464
 
452
465
  function getComponentName(
@@ -18,6 +18,17 @@ exports[`resolveConfig should ignore minimal from the root and read local file 1
18
18
  "tag-description": "warn",
19
19
  "tags-alphabetical": "off",
20
20
  },
21
+ "async3Decorators": {},
22
+ "async3Preprocessors": {},
23
+ "async3Rules": {
24
+ "channels-kebab-case": "off",
25
+ "info-contact": "off",
26
+ "no-channel-trailing-slash": "off",
27
+ "operation-operationId": "warn",
28
+ "spec": "error",
29
+ "tag-description": "warn",
30
+ "tags-alphabetical": "off",
31
+ },
21
32
  "decorators": {},
22
33
  "doNotResolveExamples": undefined,
23
34
  "oas2Decorators": {},
@@ -135,6 +146,17 @@ exports[`resolveStyleguideConfig should resolve extends with local file config w
135
146
  "tag-description": "warn",
136
147
  "tags-alphabetical": "off",
137
148
  },
149
+ "async3Decorators": {},
150
+ "async3Preprocessors": {},
151
+ "async3Rules": {
152
+ "channels-kebab-case": "off",
153
+ "info-contact": "off",
154
+ "no-channel-trailing-slash": "off",
155
+ "operation-operationId": "warn",
156
+ "spec": "error",
157
+ "tag-description": "warn",
158
+ "tags-alphabetical": "off",
159
+ },
138
160
  "decorators": {},
139
161
  "doNotResolveExamples": undefined,
140
162
  "oas2Decorators": {},
@@ -12,6 +12,11 @@ StyleguideConfig {
12
12
  "oas3_0": {},
13
13
  "oas3_1": {},
14
14
  },
15
+ "async3": {
16
+ "oas2": {},
17
+ "oas3_0": {},
18
+ "oas3_1": {},
19
+ },
15
20
  "oas2": {
16
21
  "oas2": {},
17
22
  "oas3_0": {},
@@ -51,6 +56,11 @@ StyleguideConfig {
51
56
  "oas3_0": {},
52
57
  "oas3_1": {},
53
58
  },
59
+ "async3": {
60
+ "oas2": {},
61
+ "oas3_0": {},
62
+ "oas3_1": {},
63
+ },
54
64
  "oas2": {
55
65
  "oas2": {},
56
66
  "oas3_0": {},
@@ -124,6 +134,20 @@ StyleguideConfig {
124
134
  "operation-summary": "error",
125
135
  },
126
136
  },
137
+ "async3": {
138
+ "oas2": {
139
+ "no-empty-servers": "error",
140
+ "operation-summary": "error",
141
+ },
142
+ "oas3_0": {
143
+ "no-empty-servers": "error",
144
+ "operation-summary": "error",
145
+ },
146
+ "oas3_1": {
147
+ "no-empty-servers": "error",
148
+ "operation-summary": "error",
149
+ },
150
+ },
127
151
  "oas2": {
128
152
  "oas2": {
129
153
  "no-empty-servers": "error",
@@ -119,6 +119,7 @@ describe('getMergedConfig', () => {
119
119
  "decorators": {
120
120
  "arazzo": {},
121
121
  "async2": {},
122
+ "async3": {},
122
123
  "oas2": {},
123
124
  "oas3_0": {},
124
125
  "oas3_1": {},
@@ -131,6 +132,7 @@ describe('getMergedConfig', () => {
131
132
  "preprocessors": {
132
133
  "arazzo": {},
133
134
  "async2": {},
135
+ "async3": {},
134
136
  "oas2": {},
135
137
  "oas3_0": {},
136
138
  "oas3_1": {},
@@ -148,6 +150,9 @@ describe('getMergedConfig', () => {
148
150
  "async2": {
149
151
  "operation-summary": "warn",
150
152
  },
153
+ "async3": {
154
+ "operation-summary": "warn",
155
+ },
151
156
  "oas2": {
152
157
  "operation-summary": "warn",
153
158
  },
@@ -227,6 +232,7 @@ describe('getMergedConfig', () => {
227
232
  "decorators": {
228
233
  "arazzo": {},
229
234
  "async2": {},
235
+ "async3": {},
230
236
  "oas2": {},
231
237
  "oas3_0": {},
232
238
  "oas3_1": {},
@@ -239,6 +245,7 @@ describe('getMergedConfig', () => {
239
245
  "preprocessors": {
240
246
  "arazzo": {},
241
247
  "async2": {},
248
+ "async3": {},
242
249
  "oas2": {},
243
250
  "oas3_0": {},
244
251
  "oas3_1": {},
@@ -259,6 +266,10 @@ describe('getMergedConfig', () => {
259
266
  "no-empty-servers": "error",
260
267
  "operation-summary": "error",
261
268
  },
269
+ "async3": {
270
+ "no-empty-servers": "error",
271
+ "operation-summary": "error",
272
+ },
262
273
  "oas2": {
263
274
  "no-empty-servers": "error",
264
275
  "operation-summary": "error",
package/src/config/all.ts CHANGED
@@ -114,6 +114,15 @@ const all: PluginStyleguideConfig<'built-in'> = {
114
114
  'channels-kebab-case': 'error',
115
115
  'no-channel-trailing-slash': 'error',
116
116
  },
117
+ async3Rules: {
118
+ spec: 'error',
119
+ 'info-contact': 'error',
120
+ 'operation-operationId': 'error',
121
+ 'tag-description': 'error',
122
+ 'tags-alphabetical': 'error',
123
+ 'channels-kebab-case': 'error',
124
+ 'no-channel-trailing-slash': 'error',
125
+ },
117
126
  arazzoRules: { spec: 'error' },
118
127
  };
119
128
 
@@ -5,14 +5,17 @@ import minimal from './minimal';
5
5
  import { rules as oas3Rules } from '../rules/oas3';
6
6
  import { rules as oas2Rules } from '../rules/oas2';
7
7
  import { rules as async2Rules } from '../rules/async2';
8
+ import { rules as async3Rules } from '../rules/async3';
8
9
  import { rules as arazzoRules } from '../rules/arazzo';
9
10
  import { preprocessors as oas3Preprocessors } from '../rules/oas3';
10
11
  import { preprocessors as oas2Preprocessors } from '../rules/oas2';
11
12
  import { preprocessors as async2Preprocessors } from '../rules/async2';
13
+ import { preprocessors as async3Preprocessors } from '../rules/async3';
12
14
  import { preprocessors as arazzoPreprocessors } from '../rules/arazzo';
13
15
  import { decorators as oas3Decorators } from '../decorators/oas3';
14
16
  import { decorators as oas2Decorators } from '../decorators/oas2';
15
17
  import { decorators as async2Decorators } from '../decorators/async2';
18
+ import { decorators as async3Decorators } from '../decorators/async3';
16
19
  import { decorators as arazzoDecorators } from '../decorators/arazzo';
17
20
 
18
21
  import type { CustomRulesConfig, StyleguideRawConfig, Plugin } from './types';
@@ -33,18 +36,21 @@ export const defaultPlugin: Plugin = {
33
36
  oas3: oas3Rules,
34
37
  oas2: oas2Rules,
35
38
  async2: async2Rules,
39
+ async3: async3Rules,
36
40
  arazzo: arazzoRules,
37
41
  } as CustomRulesConfig,
38
42
  preprocessors: {
39
43
  oas3: oas3Preprocessors,
40
44
  oas2: oas2Preprocessors,
41
45
  async2: async2Preprocessors,
46
+ async3: async3Preprocessors,
42
47
  arazzo: arazzoPreprocessors,
43
48
  },
44
49
  decorators: {
45
50
  oas3: oas3Decorators,
46
51
  oas2: oas2Decorators,
47
52
  async2: async2Decorators,
53
+ async3: async3Decorators,
48
54
  arazzo: arazzoDecorators,
49
55
  },
50
56
  configs: builtInConfigs,
@@ -181,7 +181,7 @@ export function resolvePlugins(
181
181
  if (pluginModule.rules) {
182
182
  if (!pluginModule.rules.oas3 && !pluginModule.rules.oas2 && !pluginModule.rules.async2) {
183
183
  throw new Error(
184
- `Plugin rules must have \`oas3\`, \`oas2\`, \`async2\`, or \`arazzo\` rules "${p}.`
184
+ `Plugin rules must have \`oas3\`, \`oas2\`, \`async2\`, \`async3\` or \`arazzo\` rules "${p}.`
185
185
  );
186
186
  }
187
187
  plugin.rules = {};
@@ -194,6 +194,9 @@ export function resolvePlugins(
194
194
  if (pluginModule.rules.async2) {
195
195
  plugin.rules.async2 = prefixRules(pluginModule.rules.async2, id);
196
196
  }
197
+ if (pluginModule.rules.async3) {
198
+ plugin.rules.async3 = prefixRules(pluginModule.rules.async3, id);
199
+ }
197
200
  if (pluginModule.rules.arazzo) {
198
201
  plugin.rules.arazzo = prefixRules(pluginModule.rules.arazzo, id);
199
202
  }
@@ -203,6 +206,7 @@ export function resolvePlugins(
203
206
  !pluginModule.preprocessors.oas3 &&
204
207
  !pluginModule.preprocessors.oas2 &&
205
208
  !pluginModule.preprocessors.async2 &&
209
+ !pluginModule.preprocessors.async3 &&
206
210
  !pluginModule.preprocessors.arazzo
207
211
  ) {
208
212
  throw new Error(
@@ -219,6 +223,9 @@ export function resolvePlugins(
219
223
  if (pluginModule.preprocessors.async2) {
220
224
  plugin.preprocessors.async2 = prefixRules(pluginModule.preprocessors.async2, id);
221
225
  }
226
+ if (pluginModule.preprocessors.async3) {
227
+ plugin.preprocessors.async3 = prefixRules(pluginModule.preprocessors.async3, id);
228
+ }
222
229
  if (pluginModule.preprocessors.arazzo) {
223
230
  plugin.preprocessors.arazzo = prefixRules(pluginModule.preprocessors.arazzo, id);
224
231
  }
@@ -229,10 +236,11 @@ export function resolvePlugins(
229
236
  !pluginModule.decorators.oas3 &&
230
237
  !pluginModule.decorators.oas2 &&
231
238
  !pluginModule.decorators.async2 &&
239
+ !pluginModule.decorators.async3 &&
232
240
  !pluginModule.decorators.arazzo
233
241
  ) {
234
242
  throw new Error(
235
- `Plugin \`decorators\` must have \`oas3\`, \`oas2\` or \`async2\` decorators "${p}.`
243
+ `Plugin \`decorators\` must have \`oas3\`, \`oas2\`, \`async2\` or \`async3\` decorators "${p}.`
236
244
  );
237
245
  }
238
246
  plugin.decorators = {};
@@ -245,6 +253,9 @@ export function resolvePlugins(
245
253
  if (pluginModule.decorators.async2) {
246
254
  plugin.decorators.async2 = prefixRules(pluginModule.decorators.async2, id);
247
255
  }
256
+ if (pluginModule.decorators.async3) {
257
+ plugin.decorators.async3 = prefixRules(pluginModule.decorators.async3, id);
258
+ }
248
259
  if (pluginModule.decorators.arazzo) {
249
260
  plugin.decorators.arazzo = prefixRules(pluginModule.decorators.arazzo, id);
250
261
  }
@@ -432,6 +443,8 @@ function getMergedRawStyleguideConfig(
432
443
  oas2Rules: { ...rootStyleguideConfig?.oas2Rules, ...apiStyleguideConfig?.oas2Rules },
433
444
  oas3_0Rules: { ...rootStyleguideConfig?.oas3_0Rules, ...apiStyleguideConfig?.oas3_0Rules },
434
445
  oas3_1Rules: { ...rootStyleguideConfig?.oas3_1Rules, ...apiStyleguideConfig?.oas3_1Rules },
446
+ async2Rules: { ...rootStyleguideConfig?.async2Rules, ...apiStyleguideConfig?.async2Rules },
447
+ async3Rules: { ...rootStyleguideConfig?.async3Rules, ...apiStyleguideConfig?.async3Rules },
435
448
  arazzoRules: { ...rootStyleguideConfig?.arazzoRules, ...apiStyleguideConfig?.arazzoRules },
436
449
  preprocessors: {
437
450
  ...rootStyleguideConfig?.preprocessors,
@@ -9,6 +9,7 @@ import {
9
9
  Oas2RuleSet,
10
10
  Oas3RuleSet,
11
11
  Async2RuleSet,
12
+ Async3RuleSet,
12
13
  ArazzoRuleSet,
13
14
  } from '../oas-types';
14
15
  import { isBrowser } from '../env';
@@ -72,6 +73,7 @@ export class StyleguideConfig {
72
73
  [SpecVersion.OAS3_0]: { ...rawConfig.rules, ...rawConfig.oas3_0Rules },
73
74
  [SpecVersion.OAS3_1]: { ...rawConfig.rules, ...rawConfig.oas3_1Rules },
74
75
  [SpecVersion.Async2]: { ...rawConfig.rules, ...rawConfig.async2Rules },
76
+ [SpecVersion.Async3]: { ...rawConfig.rules, ...rawConfig.async3Rules },
75
77
  [SpecVersion.Arazzo]: { ...rawConfig.arazzoRules },
76
78
  };
77
79
 
@@ -80,6 +82,7 @@ export class StyleguideConfig {
80
82
  [SpecVersion.OAS3_0]: { ...rawConfig.preprocessors, ...rawConfig.oas3_0Preprocessors },
81
83
  [SpecVersion.OAS3_1]: { ...rawConfig.preprocessors, ...rawConfig.oas3_1Preprocessors },
82
84
  [SpecVersion.Async2]: { ...rawConfig.preprocessors, ...rawConfig.async2Preprocessors },
85
+ [SpecVersion.Async3]: { ...rawConfig.preprocessors, ...rawConfig.async3Preprocessors },
83
86
  [SpecVersion.Arazzo]: { ...rawConfig.arazzoPreprocessors },
84
87
  };
85
88
 
@@ -88,6 +91,7 @@ export class StyleguideConfig {
88
91
  [SpecVersion.OAS3_0]: { ...rawConfig.decorators, ...rawConfig.oas3_0Decorators },
89
92
  [SpecVersion.OAS3_1]: { ...rawConfig.decorators, ...rawConfig.oas3_1Decorators },
90
93
  [SpecVersion.Async2]: { ...rawConfig.decorators, ...rawConfig.async2Decorators },
94
+ [SpecVersion.Async3]: { ...rawConfig.decorators, ...rawConfig.async3Decorators },
91
95
  [SpecVersion.Arazzo]: { ...rawConfig.arazzoDecorators },
92
96
  };
93
97
 
@@ -182,6 +186,10 @@ export class StyleguideConfig {
182
186
  if (!plugin.typeExtension.async2) continue;
183
187
  extendedTypes = plugin.typeExtension.async2(extendedTypes, version);
184
188
  break;
189
+ case SpecVersion.Async3:
190
+ if (!plugin.typeExtension.async3) continue;
191
+ extendedTypes = plugin.typeExtension.async3(extendedTypes, version);
192
+ break;
185
193
  case SpecVersion.Arazzo:
186
194
  if (!plugin.typeExtension.arazzo) continue;
187
195
  extendedTypes = plugin.typeExtension.arazzo(extendedTypes, version);
@@ -276,15 +284,26 @@ export class StyleguideConfig {
276
284
  return oas2Rules;
277
285
  case SpecMajorVersion.Async2:
278
286
  // eslint-disable-next-line no-case-declarations
279
- const asyncApiRules: Async2RuleSet[] = []; // default ruleset
287
+ const asyncApi2Rules: Async2RuleSet[] = []; // default ruleset
288
+ this.plugins.forEach(
289
+ (p) => p.preprocessors?.async2 && asyncApi2Rules.push(p.preprocessors.async2)
290
+ );
291
+ this.plugins.forEach((p) => p.rules?.async2 && asyncApi2Rules.push(p.rules.async2));
292
+ this.plugins.forEach(
293
+ (p) => p.decorators?.async2 && asyncApi2Rules.push(p.decorators.async2)
294
+ );
295
+ return asyncApi2Rules;
296
+ case SpecMajorVersion.Async3:
297
+ // eslint-disable-next-line no-case-declarations
298
+ const asyncApi3Rules: Async3RuleSet[] = []; // default ruleset
280
299
  this.plugins.forEach(
281
- (p) => p.preprocessors?.async2 && asyncApiRules.push(p.preprocessors.async2)
300
+ (p) => p.preprocessors?.async3 && asyncApi3Rules.push(p.preprocessors.async3)
282
301
  );
283
- this.plugins.forEach((p) => p.rules?.async2 && asyncApiRules.push(p.rules.async2));
302
+ this.plugins.forEach((p) => p.rules?.async3 && asyncApi3Rules.push(p.rules.async3));
284
303
  this.plugins.forEach(
285
- (p) => p.decorators?.async2 && asyncApiRules.push(p.decorators.async2)
304
+ (p) => p.decorators?.async3 && asyncApi3Rules.push(p.decorators.async3)
286
305
  );
287
- return asyncApiRules;
306
+ return asyncApi3Rules;
288
307
  case SpecMajorVersion.Arazzo:
289
308
  // eslint-disable-next-line no-case-declarations
290
309
  const arazzoRules: ArazzoRuleSet[] = []; // default ruleset
@@ -10,10 +10,9 @@ import { bundleConfig } from '../bundle';
10
10
  import { BaseResolver } from '../resolve';
11
11
  import { isBrowser } from '../env';
12
12
 
13
- import type { Document } from '../resolve';
13
+ import type { Document, ResolvedRefMap } from '../resolve';
14
14
  import type { RegionalToken, RegionalTokenWithValidity } from '../redocly/redocly-client-types';
15
15
  import type { RawConfig, RawUniversalConfig, Region } from './types';
16
- import type { ResolvedRefMap } from '../resolve';
17
16
  import { DOMAINS } from '../redocly/domains';
18
17
 
19
18
  async function addConfigMetadata({
@@ -96,6 +96,15 @@ const minimal: PluginStyleguideConfig<'built-in'> = {
96
96
  'channels-kebab-case': 'off',
97
97
  'no-channel-trailing-slash': 'off',
98
98
  },
99
+ async3Rules: {
100
+ spec: 'error',
101
+ 'info-contact': 'off',
102
+ 'operation-operationId': 'warn',
103
+ 'tag-description': 'warn',
104
+ 'tags-alphabetical': 'off',
105
+ 'channels-kebab-case': 'off',
106
+ 'no-channel-trailing-slash': 'off',
107
+ },
99
108
  arazzoRules: {
100
109
  spec: 'error',
101
110
  },
@@ -96,6 +96,15 @@ const recommendedStrict: PluginStyleguideConfig<'built-in'> = {
96
96
  'channels-kebab-case': 'off',
97
97
  'no-channel-trailing-slash': 'off',
98
98
  },
99
+ async3Rules: {
100
+ spec: 'error',
101
+ 'info-contact': 'off',
102
+ 'operation-operationId': 'error',
103
+ 'tag-description': 'error',
104
+ 'tags-alphabetical': 'off',
105
+ 'channels-kebab-case': 'off',
106
+ 'no-channel-trailing-slash': 'off',
107
+ },
99
108
  arazzoRules: {
100
109
  spec: 'error',
101
110
  },