Skip to content

Commit b0b008d

Browse files
magicmatatjahuP0lip
authored andcommitted
feat(formats): support 2.1.0, 2.2.0, 2.3.0 AsyncAPI versions (#2067)
1 parent 7fdf0e1 commit b0b008d

File tree

2 files changed

+80
-21
lines changed

2 files changed

+80
-21
lines changed
Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { asyncApi2 } from '../asyncapi';
1+
import { aas2, aas2_0, aas2_1, aas2_2, aas2_3 } from '../asyncapi';
22

3-
describe('AsyncApi format', () => {
4-
describe('AsyncApi 2.{minor}.{patch}', () => {
5-
it.each([['2.0.17'], ['2.9.0'], ['2.9.3']])('recognizes %s version correctly', (version: string) => {
6-
expect(asyncApi2({ asyncapi: version }, null)).toBe(true);
7-
});
3+
describe('AsyncAPI format', () => {
4+
describe('AsyncAPI 2.x', () => {
5+
it.each(['2.0.0', '2.1.0', '2.2.0', '2.3.0', '2.0.17', '2.1.37', '2.9.0', '2.9.3'])(
6+
'recognizes %s version correctly',
7+
version => {
8+
expect(aas2({ asyncapi: version }, null)).toBe(true);
9+
},
10+
);
811

912
const testCases = [
1013
{ asyncapi: '3.0' },
@@ -15,6 +18,7 @@ describe('AsyncApi format', () => {
1518
{ asyncapi: '2.0.01' },
1619
{ asyncapi: '1.0' },
1720
{ asyncapi: 2 },
21+
{ asyncapi: null },
1822
{ openapi: '4.0' },
1923
{ openapi: '2.0' },
2024
{ openapi: null },
@@ -25,7 +29,50 @@ describe('AsyncApi format', () => {
2529
];
2630

2731
it.each(testCases)('does not recognize invalid document %o', document => {
28-
expect(asyncApi2(document, null)).toBe(false);
32+
expect(aas2(document, null)).toBe(false);
33+
});
34+
});
35+
36+
describe('AsyncAPI 2.0', () => {
37+
it.each(['2.0.0', '2.0.3'])('recognizes %s version correctly', version => {
38+
expect(aas2_0({ asyncapi: version }, null)).toBe(true);
39+
});
40+
41+
it.each(['2', '2.0', '2.1.0', '2.1.3'])('does not recognize %s version', version => {
42+
expect(aas2_0({ asyncapi: version }, null)).toBe(false);
43+
});
44+
});
45+
46+
describe('AsyncAPI 2.1', () => {
47+
it.each(['2.1.0', '2.1.37'])('recognizes %s version correctly', version => {
48+
expect(aas2_1({ asyncapi: version }, null)).toBe(true);
49+
});
50+
51+
it.each(['2', '2.1', '2.0.0', '2.2.0', '2.2.3'])('does not recognize %s version', version => {
52+
expect(aas2_1({ asyncapi: version }, null)).toBe(false);
53+
});
54+
});
55+
56+
describe('AsyncAPI 2.2', () => {
57+
it.each(['2.2.0', '2.2.3'])('recognizes %s version correctly', version => {
58+
expect(aas2_2({ asyncapi: version }, null)).toBe(true);
59+
});
60+
61+
it.each(['2', '2.2', '2.0.0', '2.1.0', '2.1.37', '2.3.0', '2.3.3'])('does not recognize %s version', version => {
62+
expect(aas2_2({ asyncapi: version }, null)).toBe(false);
2963
});
3064
});
65+
66+
describe('AsyncAPI 2.3', () => {
67+
it.each(['2.3.0', '2.3.3'])('recognizes %s version correctly', version => {
68+
expect(aas2_3({ asyncapi: version }, null)).toBe(true);
69+
});
70+
71+
it.each(['2', '2.3', '2.0.0', '2.1.0', '2.1.37', '2.2.0', '2.4.0', '2.4.3'])(
72+
'does not recognize %s version',
73+
version => {
74+
expect(aas2_3({ asyncapi: version }, null)).toBe(false);
75+
},
76+
);
77+
});
3178
});

packages/formats/src/asyncapi.ts

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,36 @@
11
import type { Format } from '@stoplight/spectral-core';
22
import { isPlainObject } from '@stoplight/json';
33

4-
type MaybeAsyncApi2 = Partial<{ asyncapi: unknown }>;
4+
type MaybeAAS2 = { asyncapi: unknown } & Record<string, unknown>;
55

6-
const bearsAStringPropertyNamed = (document: unknown, propertyName: string): boolean => {
7-
return isPlainObject(document) && propertyName in document && typeof document[propertyName] === 'string';
8-
};
6+
const aas2Regex = /^2\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/;
7+
const aas2_0Regex = /^2\.0(?:\.[0-9]*)?$/;
8+
const aas2_1Regex = /^2\.1(?:\.[0-9]*)?$/;
9+
const aas2_2Regex = /^2\.2(?:\.[0-9]*)?$/;
10+
const aas2_3Regex = /^2\.3(?:\.[0-9]*)?$/;
911

10-
const version2Regex = /^2\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/;
12+
const isAas2 = (document: unknown): document is { asyncapi: string } & Record<string, unknown> =>
13+
isPlainObject(document) && 'asyncapi' in document && aas2Regex.test(String((document as MaybeAAS2).asyncapi));
1114

12-
export const asyncApi2: Format = document => {
13-
if (!bearsAStringPropertyNamed(document, 'asyncapi')) {
14-
return false;
15-
}
15+
export const aas2: Format = isAas2;
16+
aas2.displayName = 'AsyncAPI 2.x';
1617

17-
const version = String((document as MaybeAsyncApi2).asyncapi);
18+
// for backward compatibility
19+
export const asyncApi2 = aas2;
20+
export const asyncapi2 = aas2;
1821

19-
return version2Regex.test(version);
20-
};
22+
export const aas2_0: Format = (document: unknown): boolean =>
23+
isAas2(document) && aas2_0Regex.test(String((document as MaybeAAS2).asyncapi));
24+
aas2_0.displayName = 'AsyncAPI 2.0.x';
2125

22-
asyncApi2.displayName = 'AsyncAPI 2.x';
26+
export const aas2_1: Format = (document: unknown): boolean =>
27+
isAas2(document) && aas2_1Regex.test(String((document as MaybeAAS2).asyncapi));
28+
aas2_1.displayName = 'AsyncAPI 2.1.x';
2329

24-
export { asyncApi2 as asyncapi2 };
30+
export const aas2_2: Format = (document: unknown): boolean =>
31+
isAas2(document) && aas2_2Regex.test(String((document as MaybeAAS2).asyncapi));
32+
aas2_2.displayName = 'AsyncAPI 2.2.x';
33+
34+
export const aas2_3: Format = (document: unknown): boolean =>
35+
isAas2(document) && aas2_3Regex.test(String((document as MaybeAAS2).asyncapi));
36+
aas2_3.displayName = 'AsyncAPI 2.3.x';

0 commit comments

Comments
 (0)