Skip to content

Commit 9f319c9

Browse files
committed
add factory
1 parent 9ee1f8b commit 9f319c9

27 files changed

+131
-112
lines changed

src/models/asyncapi.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
import { InfoInterface } from "./info";
2+
import { BaseModel } from "./base";
3+
import { V2AsyncAPIDocument } from "./v2";
4+
import { V3AsyncAPIDocument } from "./v3";
25

3-
export interface AsyncAPIDocumentInterface {
6+
export interface AsyncAPIDocumentInterface extends BaseModel {
47
version(): string;
58
info(): InfoInterface
9+
}
10+
11+
export function newAsyncAPIDocument(json: Record<string, any>): AsyncAPIDocumentInterface {
12+
const version = json['asyncapi']; // Maybe this should be an arg.
13+
if (version == undefined || version == null || version == '') {
14+
throw new Error('Missing AsyncAPI version in document');
15+
}
16+
17+
const major = version.split(".")[0];
18+
switch (major) {
19+
case '2':
20+
return new V2AsyncAPIDocument(json);
21+
case '3':
22+
return new V3AsyncAPIDocument(json);
23+
default:
24+
throw new Error(`Unsupported version: ${version}`);
25+
}
626
}

src/models/v2/base.ts renamed to src/models/base.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
export class V2BaseModel {
1+
export class BaseModel {
22
constructor(
33
private readonly _json: Record<string, any>,
44
) {}
55

6-
json<T = Record<string, unknown>>(): T;
7-
json<T = unknown>(key: string | number): T;
6+
json<T = Record<string, any>>(): T;
7+
json<T = any>(key: string | number): T;
88
json(key?: string | number) {
99
if (key === undefined) return this._json;
1010
if (!this._json) return;

src/models/contact.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
export interface ContactInterface {
1+
import { BaseModel } from "./base";
2+
3+
export interface ContactInterface extends BaseModel {
24
name(): string;
35
url(): string;
46
email(): string;

src/models/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './v2';
22
export * from './v3';
33
export * from './asyncapi';
4+
export * from './base';
45
export * from './info';
56
export * from './contact';
67
export * from './license';

src/models/info.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { ContactInterface } from "./contact";
22
import { LicenseInterface } from "./license";
3+
import { BaseModel } from "./base";
34

4-
export interface InfoInterface {
5+
export interface InfoInterface extends BaseModel {
56
title(): string;
67
version(): string;
78
description(): string;

src/models/license.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
export interface LicenseInterface {
1+
import { BaseModel } from "./base";
2+
3+
export interface LicenseInterface extends BaseModel {
24
name(): string;
35
url(): string;
46
}

src/models/v2/asyncapi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { AsyncAPIDocumentInterface } from "models/asyncapi";
2-
import { V2BaseModel } from "./base";
2+
import { BaseModel } from "../base";
33
import { V2Info } from "./info";
44

5-
export class V2AsyncAPIDocument extends V2BaseModel implements AsyncAPIDocumentInterface {
5+
export class V2AsyncAPIDocument extends BaseModel implements AsyncAPIDocumentInterface {
66
version(): string {
77
return this.json("asyncapi");
88
}

src/models/v2/contact.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ContactInterface } from "models/contact";
2-
import { V2BaseModel } from "./base";
2+
import { BaseModel } from "../base";
33

4-
export class V2Contact extends V2BaseModel implements ContactInterface {
4+
export class V2Contact extends BaseModel implements ContactInterface {
55
name(): string {
66
return this.json("name");
77
}

src/models/v2/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export * from './asyncapi';
2-
export * from './base';
32
export * from './contact';
43
export * from './info';
54
export * from './license';

src/models/v2/info.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { InfoInterface } from "models/info";
2-
import { V2BaseModel } from "./base";
2+
import { BaseModel } from "../base";
33
import { V2Contact } from "./contact";
44
import { V2License } from "./license";
55

6-
export class V2Info extends V2BaseModel implements InfoInterface {
6+
export class V2Info extends BaseModel implements InfoInterface {
77
title(): string {
88
return this.json("title");
99
}

src/models/v2/license.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { LicenseInterface } from "models/license";
2-
import { V2BaseModel } from "./base";
2+
import { BaseModel } from "../base";
33

4-
export class V2License extends V2BaseModel implements LicenseInterface {
4+
export class V2License extends BaseModel implements LicenseInterface {
55
name(): string {
66
return this.json("name");
77
}

src/models/v3/asyncapi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { AsyncAPIDocumentInterface } from "models/asyncapi";
2-
import { V3BaseModel } from "./base";
2+
import { BaseModel } from "../base";
33
import { V3Info } from "./info";
44

5-
export class V3AsyncAPIDocument extends V3BaseModel implements AsyncAPIDocumentInterface {
5+
export class V3AsyncAPIDocument extends BaseModel implements AsyncAPIDocumentInterface {
66
version(): string {
77
return this.json("asyncapi");
88
}

src/models/v3/base.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/models/v3/contact.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ContactInterface } from "models/contact";
2-
import { V3BaseModel } from "./base";
2+
import { BaseModel } from "../base";
33

4-
export class V3Contact extends V3BaseModel implements ContactInterface {
4+
export class V3Contact extends BaseModel implements ContactInterface {
55
name(): string {
66
return this.json("name");
77
}

src/models/v3/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export * from './asyncapi';
2-
export * from './base';
32
export * from './contact';
43
export * from './info';
54
export * from './license';

src/models/v3/info.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { InfoInterface } from "models/info";
2-
import { V3BaseModel } from "./base";
2+
import { BaseModel } from "../base";
33
import { V3Contact } from "./contact";
44
import { V3License } from "./license";
55

6-
export class V3Info extends V3BaseModel implements InfoInterface {
6+
export class V3Info extends BaseModel implements InfoInterface {
77
title(): string {
88
return this.json("title");
99
}

src/models/v3/license.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { LicenseInterface } from "models/license";
2-
import { V3BaseModel } from "./base";
2+
import { BaseModel } from "../base";
33

4-
export class V3License extends V3BaseModel implements LicenseInterface {
4+
export class V3License extends BaseModel implements LicenseInterface {
55
name(): string {
66
return this.json("name");
77
}

src/stringify.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AsyncAPIDocument } from './models';
1+
import { AsyncAPIDocumentInterface, newAsyncAPIDocument } from './models';
22

33
import { isAsyncAPIDocument, isParsedDocument, isStringifiedDocument } from './utils';
44
import { xParserSpecStringified } from './constants';
@@ -21,7 +21,7 @@ export function stringify(document: unknown, space?: string | number): string |
2121
}, refReplacer(), space);
2222
}
2323

24-
export function unstringify(document: unknown): AsyncAPIDocument | undefined {
24+
export function unstringify(document: unknown): AsyncAPIDocumentInterface | undefined {
2525
if (!isStringifiedDocument(document)) {
2626
return;
2727
}
@@ -32,7 +32,7 @@ export function unstringify(document: unknown): AsyncAPIDocument | undefined {
3232
delete (<Record<string, any>>document)[String(xParserSpecStringified)];
3333

3434
traverseStringifiedDoc(document, undefined, document, new Map(), new Map());
35-
return new AsyncAPIDocument(<Record<string, any>>document);
35+
return newAsyncAPIDocument(<Record<string, any>>document);
3636
}
3737

3838
function refReplacer() {

src/utils.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
import { AsyncAPIDocument } from './models';
1+
import { AsyncAPIDocumentInterface, newAsyncAPIDocument, V2AsyncAPIDocument, V3AsyncAPIDocument } from './models';
22
import { unstringify } from './stringify';
33

44
import {
55
xParserSpecParsed,
66
xParserSpecStringified,
77
} from './constants';
88

9-
export function toAsyncAPIDocument(maybeDoc: unknown): AsyncAPIDocument | undefined {
9+
export function toAsyncAPIDocument(maybeDoc: unknown): AsyncAPIDocumentInterface | undefined {
1010
if (isAsyncAPIDocument(maybeDoc)) {
1111
return maybeDoc;
1212
}
1313
if (!isParsedDocument(maybeDoc)) {
1414
return;
1515
}
16-
return unstringify(maybeDoc) || new AsyncAPIDocument(maybeDoc);
16+
return unstringify(maybeDoc) || newAsyncAPIDocument(maybeDoc);
1717
}
1818

19-
export function isAsyncAPIDocument(maybeDoc: unknown): maybeDoc is AsyncAPIDocument {
20-
return maybeDoc instanceof AsyncAPIDocument;
19+
export function isAsyncAPIDocument(maybeDoc: unknown): maybeDoc is AsyncAPIDocumentInterface {
20+
return maybeDoc instanceof V2AsyncAPIDocument || maybeDoc instanceof V3AsyncAPIDocument;
2121
}
2222

2323
export function isParsedDocument(maybeDoc: unknown): maybeDoc is Record<string, unknown> {

test/models/asyncapi.spec.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.

test/models/base.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { BaseModel } from '../../src/models/v2/base';
1+
import { BaseModel } from '../../src/models/base';
22

33
describe('Base model', function() {
44
describe('.json()', function() {

test/models/v2/asyncapi.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { newAsyncAPIDocument } from '../../../src/models';
2+
import { V2AsyncAPIDocument } from '../../../src/models/v2/asyncapi';
3+
import { V2Info } from '../../../src/models/v2/info';
4+
5+
describe('AsyncAPIDocument model', function() {
6+
it('should create a valid document', function() {
7+
const doc = { asyncapi: "2.0.0" };
8+
const d = newAsyncAPIDocument(doc)
9+
expect(d.version()).toEqual(doc.asyncapi);
10+
});
11+
describe('.version()', function() {
12+
it('should return the value', function() {
13+
const doc = { asyncapi: "3.0.0" };
14+
const d = new V2AsyncAPIDocument(doc);
15+
expect(d.version()).toEqual(doc.asyncapi);
16+
});
17+
18+
it('should return undefined when there is no value', function() {
19+
const doc = { };
20+
const d = new V2AsyncAPIDocument(doc);
21+
expect(d.version()).toBeUndefined();
22+
});
23+
});
24+
25+
describe('.info()', function() {
26+
it('should return an Info object', function() {
27+
const doc = { info: { name: "LeChuck" } };
28+
const d = new V2AsyncAPIDocument(doc);
29+
expect(d.info() instanceof V2Info).toBeTruthy();
30+
});
31+
});
32+
});

test/models/contact.spec.ts renamed to test/models/v2/contact.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,44 @@
1-
import { Contact } from '../../src/models/v2/contact';
1+
import { V2Contact } from '../../../src/models/v2/contact';
22

33
describe('Contact model', function() {
44
describe('.name()', function() {
55
it('should return the value', function() {
66
const doc = { name: "LeChuck" };
7-
const d = new Contact(doc);
7+
const d = new V2Contact(doc);
88
expect(d.name()).toEqual(doc.name);
99
});
1010

1111
it('should return undefined when there is no value', function() {
1212
const doc = { };
13-
const d = new Contact(doc);
13+
const d = new V2Contact(doc);
1414
expect(d.name()).toBeUndefined();
1515
});
1616
});
1717

1818
describe('.url()', function() {
1919
it('should return the value', function() {
2020
const doc = { url: "https://example.com" };
21-
const d = new Contact(doc);
21+
const d = new V2Contact(doc);
2222
expect(d.url()).toEqual(doc.url);
2323
});
2424

2525
it('should return undefined when there is no value', function() {
2626
const doc = { };
27-
const d = new Contact(doc);
27+
const d = new V2Contact(doc);
2828
expect(d.url()).toBeUndefined();
2929
});
3030
});
3131

3232
describe('.email()', function() {
3333
it('should return the value', function() {
3434
const doc = { email: "[email protected]" };
35-
const d = new Contact(doc);
35+
const d = new V2Contact(doc);
3636
expect(d.email()).toEqual(doc.email);
3737
});
3838

3939
it('should return undefined when there is no value', function() {
4040
const doc = { };
41-
const d = new Contact(doc);
41+
const d = new V2Contact(doc);
4242
expect(d.email()).toBeUndefined();
4343
});
4444
});

0 commit comments

Comments
 (0)