Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: interface and implementations for each major spec version #488

Merged
merged 5 commits into from
Mar 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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