Skip to content

Commit

Permalink
refactor: interface and implementations for each major spec version (a…
Browse files Browse the repository at this point in the history
  • Loading branch information
smoya authored and magicmatatjahu committed Oct 3, 2022
1 parent e3809c0 commit edc8529
Show file tree
Hide file tree
Showing 28 changed files with 274 additions and 118 deletions.
4 changes: 2 additions & 2 deletions src/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { asyncapi as aasRuleset } from "@stoplight/spectral-rulesets";

import { toAsyncAPIDocument, normalizeInput, hasWarningDiagnostic, hasErrorDiagnostic } from "./utils";

import type { AsyncAPIDocument } from "./models/asyncapi";
import type { AsyncAPIDocumentInterface } from "./models/asyncapi";
import type { ParserInput, Diagnostic } from "./types";

export interface LintOptions extends IConstructorOpts, IRunOpts {
Expand All @@ -31,7 +31,7 @@ export async function lint(asyncapi: ParserInput, options?: LintOptions): Promis
if (toAsyncAPIDocument(asyncapi)) {
return;
}
const document = normalizeInput(asyncapi as Exclude<ParserInput, AsyncAPIDocument>);
const document = normalizeInput(asyncapi as Exclude<ParserInput, AsyncAPIDocumentInterface>);
return (await validate(document, options)).diagnostics;
}

Expand Down
28 changes: 21 additions & 7 deletions src/models/asyncapi.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import { InfoInterface } from "./info";
import { BaseModel } from "./base";
import { Info } from "./info";
import { AsyncAPIDocumentV2 } from "./v2";
import { AsyncAPIDocumentV3 } from "./v3";

export class AsyncAPIDocument extends BaseModel {
version(): string {
return this.json("asyncapi");
export interface AsyncAPIDocumentInterface extends BaseModel {
version(): string;
info(): InfoInterface
}

export function newAsyncAPIDocument(json: Record<string, any>): AsyncAPIDocumentInterface {
const version = json['asyncapi']; // Maybe this should be an arg.
if (version == undefined || version == null || version == '') {
throw new Error('Missing AsyncAPI version in document');
}

info(): Info {
return new Info(this.json("info"));
const major = version.split(".")[0];
switch (major) {
case '2':
return new AsyncAPIDocumentV2(json);
case '3':
return new AsyncAPIDocumentV3(json);
default:
throw new Error(`Unsupported version: ${version}`);
}
}
}
16 changes: 4 additions & 12 deletions src/models/contact.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { BaseModel } from "./base";

export class Contact extends BaseModel {
name(): string {
return this.json("name");
}

url(): string {
return this.json("url");
}

email(): string {
return this.json("email");
}
export interface ContactInterface extends BaseModel {
name(): string;
url(): string;
email(): string;
}
6 changes: 4 additions & 2 deletions src/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export * from './v2';
export * from './v3';
export * from './asyncapi';
export * from './base';
export * from './contact';
export * from './info';
export * from './license';
export * from './contact';
export * from './license';
37 changes: 9 additions & 28 deletions src/models/info.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,12 @@
import { ContactInterface } from "./contact";
import { LicenseInterface } from "./license";
import { BaseModel } from "./base";
import { Contact } from "./contact";
import { License } from "./license";

export class Info extends BaseModel {
title(): string {
return this.json("title");
}

version(): string {
return this.json("version");
}

description(): string {
return this.json("description");
}

termsOfService(): string {
return this.json("termsOfService");
}

contact(): Contact | undefined {
const doc = this.json("contact");
return doc && new Contact(doc);
}

license(): License | undefined {
const doc = this.json("license");
return doc && new License(doc);
}
export interface InfoInterface extends BaseModel {
title(): string;
version(): string;
description(): string;
termsOfService(): string;
contact(): ContactInterface | undefined;
license(): LicenseInterface | undefined;
}
11 changes: 3 additions & 8 deletions src/models/license.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { BaseModel } from "./base";

export class License extends BaseModel {
name(): string {
return this.json("name");
}

url(): string {
return this.json("url");
}
export interface LicenseInterface extends BaseModel {
name(): string;
url(): string;
}
13 changes: 13 additions & 0 deletions src/models/v2/asyncapi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AsyncAPIDocumentInterface } from "../../models";
import { BaseModel } from "../base";
import { Info } from "./info";

export class AsyncAPIDocument extends BaseModel implements AsyncAPIDocumentInterface {
version(): string {
return this.json("asyncapi");
}

info(): Info {
return new Info(this.json("info"));
}
}
16 changes: 16 additions & 0 deletions src/models/v2/contact.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ContactInterface } from "../../models/contact";
import { BaseModel } from "../base";

export class Contact extends BaseModel implements ContactInterface {
name(): string {
return this.json("name");
}

url(): string {
return this.json("url");
}

email(): string {
return this.json("email");
}
}
4 changes: 4 additions & 0 deletions src/models/v2/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { AsyncAPIDocument as AsyncAPIDocumentV2 } from './asyncapi';
export { Contact as ContactV2 } from './contact';
export { Info as InfoV2 } from './info';
export { License as LicenseV2 } from './license';
32 changes: 32 additions & 0 deletions src/models/v2/info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { InfoInterface } from "../../models/info";
import { BaseModel } from "../base";
import { Contact } from "./contact";
import { License } from "./license";

export class Info extends BaseModel implements InfoInterface {
title(): string {
return this.json("title");
}

version(): string {
return this.json("version");
}

description(): string {
return this.json("description");
}

termsOfService(): string {
return this.json("termsOfService");
}

contact(): Contact | undefined {
const doc = this.json("contact");
return doc && new Contact(doc);
}

license(): License | undefined {
const doc = this.json("license");
return doc && new License(doc);
}
}
12 changes: 12 additions & 0 deletions src/models/v2/license.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { LicenseInterface } from "../../models/license";
import { BaseModel } from "../base";

export class License extends BaseModel implements LicenseInterface {
name(): string {
return this.json("name");
}

url(): string {
return this.json("url");
}
}
13 changes: 13 additions & 0 deletions src/models/v3/asyncapi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AsyncAPIDocumentInterface } from "../../models/asyncapi";
import { BaseModel } from "../base";
import { Info } from "./info";

export class AsyncAPIDocument extends BaseModel implements AsyncAPIDocumentInterface {
version(): string {
return this.json("asyncapi");
}

info(): Info {
return new Info(this.json("info"));
}
}
16 changes: 16 additions & 0 deletions src/models/v3/contact.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ContactInterface } from "../../models/contact";
import { BaseModel } from "../base";

export class Contact extends BaseModel implements ContactInterface {
name(): string {
return this.json("name");
}

url(): string {
return this.json("url");
}

email(): string {
return this.json("email");
}
}
4 changes: 4 additions & 0 deletions src/models/v3/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { AsyncAPIDocument as AsyncAPIDocumentV3 } from './asyncapi';
export { Contact as ContactV3 } from './contact';
export { Info as InfoV3 } from './info';
export { License as LicenseV3 } from './license';
32 changes: 32 additions & 0 deletions src/models/v3/info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { InfoInterface } from "../../models/info";
import { BaseModel } from "../base";
import { Contact } from "./contact";
import { License } from "./license";

export class Info extends BaseModel implements InfoInterface {
title(): string {
return this.json("title");
}

version(): string {
return this.json("version");
}

description(): string {
return this.json("description");
}

termsOfService(): string {
return this.json("termsOfService");
}

contact(): Contact | undefined {
const doc = this.json("contact");
return doc && new Contact(doc);
}

license(): License | undefined {
const doc = this.json("license");
return doc && new License(doc);
}
}
12 changes: 12 additions & 0 deletions src/models/v3/license.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { LicenseInterface } from "../../models/license";
import { BaseModel } from "../base";

export class License extends BaseModel implements LicenseInterface {
name(): string {
return this.json("name");
}

url(): string {
return this.json("url");
}
}
6 changes: 3 additions & 3 deletions src/parse.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncAPIDocument } from "./models";
import { AsyncAPIDocumentInterface, newAsyncAPIDocument } from "./models";
import { normalizeInput, toAsyncAPIDocument } from "./utils";
import { validate } from "./lint";

Expand All @@ -21,7 +21,7 @@ export async function parse(asyncapi: ParserInput, options?: ParseOptions): Prom
}

try {
const document = normalizeInput(asyncapi as Exclude<ParserInput, AsyncAPIDocument>);
const document = normalizeInput(asyncapi as Exclude<ParserInput, AsyncAPIDocumentInterface>);
options = normalizeOptions(options);

const { validated, diagnostics } = await validate(document, options.validateOptions);
Expand All @@ -33,7 +33,7 @@ export async function parse(asyncapi: ParserInput, options?: ParseOptions): Prom
};
}

const parsed = new AsyncAPIDocument(validated as Record<string, unknown>);
const parsed = newAsyncAPIDocument(validated as Record<string, unknown>);
return {
source: asyncapi,
parsed,
Expand Down
6 changes: 3 additions & 3 deletions src/stringify.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncAPIDocument } from './models';
import { AsyncAPIDocumentInterface, newAsyncAPIDocument } from './models';

import { isAsyncAPIDocument, isParsedDocument, isStringifiedDocument } from './utils';
import { xParserSpecStringified } from './constants';
Expand All @@ -25,7 +25,7 @@ export function stringify(document: unknown, options: StringifyOptions = {}): st
}, refReplacer(), options.space || 2);
}

export function unstringify(document: unknown): AsyncAPIDocument | undefined {
export function unstringify(document: unknown): AsyncAPIDocumentInterface | undefined {
if (!isStringifiedDocument(document)) {
return;
}
Expand All @@ -36,7 +36,7 @@ export function unstringify(document: unknown): AsyncAPIDocument | undefined {
delete (<Record<string, any>>document)[String(xParserSpecStringified)];

traverseStringifiedDoc(document, undefined, document, new Map(), new Map());
return new AsyncAPIDocument(<Record<string, any>>document);
return newAsyncAPIDocument(<Record<string, any>>document);
}

function refReplacer() {
Expand Down
6 changes: 3 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { ISpectralDiagnostic } from '@stoplight/spectral-core';
import type { AsyncAPIDocument } from './models/asyncapi';
import type { AsyncAPIDocumentInterface } from './models/asyncapi';

export type MaybeAsyncAPI = { asyncapi: unknown } & Record<string, unknown>;
export type ParserInput = string | MaybeAsyncAPI | AsyncAPIDocument;
export type ParserInput = string | MaybeAsyncAPI | AsyncAPIDocumentInterface;

export type Diagnostic = ISpectralDiagnostic;

export interface ParserOutput {
source: ParserInput;
parsed: AsyncAPIDocument | undefined;
parsed: AsyncAPIDocumentInterface | undefined;
diagnostics: Diagnostic[];
}
Loading

0 comments on commit edc8529

Please sign in to comment.