Skip to content

Commit

Permalink
refactor: port channel, channel-parameter and schema models (#547)
Browse files Browse the repository at this point in the history
magicmatatjahu authored and derberg committed Oct 4, 2022
1 parent 3627d02 commit ae4b0ff
Showing 35 changed files with 1,635 additions and 120 deletions.
8 changes: 2 additions & 6 deletions src/models/base.ts
Original file line number Diff line number Diff line change
@@ -32,11 +32,7 @@ export abstract class BaseModel {
return `${this._meta?.pointer}/${field}`;
}

protected createModel<T extends BaseModel>(Model: Constructor<T>, value: any, { id, parent, pointer, ...rest }: { id?: string, pointer: string | number, [key: string]: any }): T {
const meta = { ...rest, asyncapi: this._meta.asyncapi, pointer } as ModelMetadata;
if (id) {
return new Model(id, value, meta);
}
return new Model(value, meta);
protected createModel<T extends BaseModel>(Model: Constructor<T>, value: any, { pointer, ...rest }: { pointer: string | number, [key: string]: any }): T {
return new Model(value, { ...rest, asyncapi: this._meta.asyncapi, pointer });
}
}
2 changes: 1 addition & 1 deletion src/models/extension.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { BaseModel } from "./base";

export interface ExtensionInterface extends BaseModel {
id(): string;
name(): string;
version(): string;
value(): any;
}
56 changes: 54 additions & 2 deletions src/models/schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,56 @@
import type { BaseModel } from "./base";
import type { ExtensionsMixinInterface } from "./mixins";
import type { ExtensionsMixinInterface, ExternalDocumentationMixinInterface } from "./mixins";

export interface SchemaInterface extends BaseModel, ExtensionsMixinInterface {}
export interface SchemaInterface extends BaseModel, ExtensionsMixinInterface, ExternalDocumentationMixinInterface {
uid(): string;
$comment(): string | undefined;
$id(): string | undefined;
$schema(): string;
additionalItems(): boolean | SchemaInterface;
additionalProperties(): boolean | SchemaInterface;
allOf(): Array<SchemaInterface> | undefined;
anyOf(): Array<SchemaInterface> | undefined;
const(): any;
contains(): SchemaInterface | undefined;
contentEncoding(): string | undefined;
contentMediaType(): string | undefined;
default(): any;
definitions(): Record<string, SchemaInterface> | undefined;
description(): string | undefined;
dependencies(): Record<string, SchemaInterface | Array<string>> | undefined;
deprecated(): boolean;
discriminator(): string | undefined;
else(): SchemaInterface | undefined;
enum(): Array<any> | undefined;
examples(): Array<any> | undefined;
exclusiveMaximum(): number | undefined;
exclusiveMinimum(): number | undefined;
format(): string | undefined;
isBooleanSchema(): boolean;
if(): SchemaInterface | undefined;
isCircular(): boolean;
items(): SchemaInterface | Array<SchemaInterface> | undefined;
maximum(): number | undefined;
maxItems(): number | undefined;
maxLength(): number | undefined;
maxProperties(): number | undefined;
minimum(): number | undefined;
minItems(): number | undefined;
minLength(): number | undefined;
minProperties(): number | undefined;
multipleOf(): number | undefined;
not(): SchemaInterface | undefined;
oneOf(): Array<SchemaInterface> | undefined;
pattern(): string | undefined;
patternProperties(): Record<string, SchemaInterface> | undefined;
properties(): Record<string, SchemaInterface> | undefined;
property(key: string): SchemaInterface | undefined;
propertyNames(): SchemaInterface | undefined;
readOnly(): boolean | undefined;
required(): Array<string> | undefined;
then(): SchemaInterface | undefined;
title(): string | undefined;
type(): string | Array<string> | undefined;
uniqueItems(): boolean | undefined;
writeOnly(): boolean | undefined;
}
40 changes: 40 additions & 0 deletions src/models/v2/channel-parameter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { BaseModel } from "../base";
import { Schema } from "./schema";

import { Mixin } from '../utils';
import { DescriptionMixin } from './mixins/description';
import { ExtensionsMixin } from './mixins/extensions';

import type { ModelMetadata } from "../base";
import type { ChannelParameterInterface } from "../channel-parameter";
import type { SchemaInterface } from "../schema";

export class ChannelParameter extends Mixin(BaseModel, DescriptionMixin, ExtensionsMixin) implements ChannelParameterInterface {
constructor(
_json: Record<string,any>,
protected readonly _meta: ModelMetadata & { id: string } = {} as any
) {
super(_json, _meta);
}

id(): string {
return this._meta.id;
}

hasSchema(): boolean {
return !!this._json.schema;
}

schema(): SchemaInterface | undefined {
if (!this._json.schema) return undefined;
return this.createModel(Schema, this._json.schema, { pointer: `${this._meta.pointer}/schema` });
}

hasLocation(): boolean {
return !!this._json.location;
}

location(): string | undefined {
return this._json.location;
}
}
14 changes: 14 additions & 0 deletions src/models/v2/channel-parameters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Collection } from '../collection';

import type { ChannelParametersInterface } from '../channel-parameters';
import type { ChannelParameterInterface } from '../channel-parameter';

export class ChannelParameters extends Collection<ChannelParameterInterface> implements ChannelParametersInterface {
override get(id: string): ChannelParameterInterface | undefined {
return this.collections.find(parameter => parameter.id() === id);
}

override has(id: string): boolean {
return this.collections.some(parameter => parameter.id() === id);
}
}
75 changes: 75 additions & 0 deletions src/models/v2/channel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { BaseModel } from "../base";
import { ChannelParameters } from './channel-parameters';
import { ChannelParameter } from './channel-parameter';
import { Messages } from './messages';
import { Operations } from './operations';
import { Operation } from './operation';
import { Servers } from './servers';
import { Server } from './server';

import { Mixin } from '../utils';
import { BindingsMixin } from './mixins/bindings';
import { DescriptionMixin } from './mixins/description';
import { ExtensionsMixin } from './mixins/extensions';

import type { ModelMetadata } from "../base";
import type { ChannelInterface } from "../channel";
import type { ChannelParametersInterface } from "../channel-parameters";
import type { OperationsInterface } from "../operations";
import type { OperationInterface } from "../operation";
import type { ServersInterface } from "../servers";
import type { ServerInterface } from "../server";

export class Channel extends Mixin(BaseModel, BindingsMixin, DescriptionMixin, ExtensionsMixin) implements ChannelInterface {
constructor(
_json: Record<string,any>,
protected readonly _meta: ModelMetadata & { id: string, address: string } = {} as any
) {
super(_json, _meta);
}

id(): string {
return this._meta.id;
}

address(): string {
return this._meta.address;
}

servers(): ServersInterface {
const servers: ServerInterface[] = [];
const allowedServers: string[] = this._json.servers || [];
Object.entries(this._meta.asyncapi?.parsed.servers || {}).map(([serverName, server]) => {
if (allowedServers.length === 0 || allowedServers.includes(serverName)) {
servers.push(this.createModel(Server, server, { id: serverName, pointer: `/servers/${serverName}` }));
}
});
return new Servers(servers);
}

operations(): OperationsInterface {
const operations: OperationInterface[] = []
if (this._json.publish) {
operations.push(
this.createModel(Operation, this._json.publish, { id: 'publish', action: 'publish', pointer: `${this._meta.pointer}/publish` }),
);
}
if (this._json.subscribe) {
operations.push(
this.createModel(Operation, this._json.subscribe, { id: 'subscribe', action: 'subscribe', pointer: `${this._meta.pointer}/subscribe` }),
);
}
return new Operations(operations);
}

parameters(): ChannelParametersInterface {
return new ChannelParameters(
Object.entries(this._json.parameters || {}).map(([channelParameterName, channelParameter]) => {
return this.createModel(ChannelParameter, channelParameter, {
id: channelParameterName,
pointer: `${this._meta.pointer}/parameters/${channelParameterName}`
})
})
);
}
}
14 changes: 14 additions & 0 deletions src/models/v2/channels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Collection } from '../collection';

import type { ChannelsInterface } from '../channels';
import type { ChannelInterface } from '../channel';

export class Channels extends Collection<ChannelInterface> implements ChannelsInterface {
override get(id: string): ChannelInterface | undefined {
return this.collections.find(channel => channel.id() === id);
}

override has(id: string): boolean {
return this.collections.some(channel => channel.id() === id);
}
}
5 changes: 2 additions & 3 deletions src/models/v2/message-trait.ts
Original file line number Diff line number Diff line change
@@ -19,15 +19,14 @@ import type { SchemaInterface } from "../schema";

export class MessageTrait extends Mixin(BaseModel, BindingsMixin, DescriptionMixin, ExtensionsMixin, ExternalDocumentationMixin, TagsMixin) implements MessageTraitInterface {
constructor(
private readonly _id: string,
_json: Record<string,any>,
_meta: ModelMetadata = {} as any
protected readonly _meta: ModelMetadata & { id: string } = {} as any
) {
super(_json, _meta);
}

id(): string {
return this.messageId() || this._id;
return this.messageId() || this._meta.id;
}

hasMessageId(): boolean {
5 changes: 2 additions & 3 deletions src/models/v2/mixins/bindings.ts
Original file line number Diff line number Diff line change
@@ -11,15 +11,14 @@ import type { BindingInterface } from "../../binding";

export class Binding extends Mixin(BaseModel, ExtensionsMixin) implements BindingInterface {
constructor(
private readonly _protocol: string,
_json: Record<string, any>,
_meta: ModelMetadata = {} as any,
protected readonly _meta: ModelMetadata & { protocol: string } = {} as any,
) {
super(_json, _meta);
}

protocol(): string {
return this._protocol;
return this._meta.protocol;
}

version(): string {
11 changes: 5 additions & 6 deletions src/models/v2/mixins/extensions.ts
Original file line number Diff line number Diff line change
@@ -10,15 +10,14 @@ import { EXTENSION_REGEX } from '../../../constants';

export class Extension extends BaseModel implements ExtensionInterface {
constructor(
private readonly _id: string,
_json: Record<string, any>,
_meta: ModelMetadata = {} as any,
protected readonly _meta: ModelMetadata & { name: string } = {} as any,
) {
super(_json, _meta);
}

id(): string {
return this._id;
name(): string {
return this._meta.name;
}

version(): string {
@@ -33,12 +32,12 @@ export class Extension extends BaseModel implements ExtensionInterface {
export class Extensions extends Collection<ExtensionInterface> implements ExtensionsInterface {
override get(name: string): ExtensionInterface | undefined {
name = name.startsWith('x-') ? name : `x-${name}`;
return this.collections.find(ext => ext.id() === name);
return this.collections.find(ext => ext.name() === name);
};

override has(name: string): boolean {
name = name.startsWith('x-') ? name : `x-${name}`;
return this.collections.some(ext => ext.id() === name);
return this.collections.some(ext => ext.name() === name);
};
}

5 changes: 1 addition & 4 deletions src/models/v2/mixins/external-docs.ts
Original file line number Diff line number Diff line change
@@ -7,10 +7,7 @@ import { ExtensionsMixin } from './extensions';
import type { ExternalDocumentationInterface } from '../../external-docs';
import type { ExternalDocumentationMixinInterface } from "../../mixins";

export class ExternalDocumentation
extends Mixin(BaseModel, DescriptionMixin, ExtensionsMixin)
implements ExternalDocumentationInterface {

export class ExternalDocumentation extends Mixin(BaseModel, DescriptionMixin, ExtensionsMixin) implements ExternalDocumentationInterface {
url(): string {
return this._json.url;
}
5 changes: 1 addition & 4 deletions src/models/v2/mixins/tags.ts
Original file line number Diff line number Diff line change
@@ -10,10 +10,7 @@ import type { TagsMixinInterface } from "../../mixins";
import type { TagsInterface } from "../../tags";
import type { TagInterface } from "../../tag";

export class Tag
extends Mixin(BaseModel, DescriptionMixin, ExtensionsMixin, ExternalDocumentationMixin)
implements TagInterface {

export class Tag extends Mixin(BaseModel, DescriptionMixin, ExtensionsMixin, ExternalDocumentationMixin) implements TagInterface {
name(): string {
return this._json.name;
}
5 changes: 2 additions & 3 deletions src/models/v2/operation-trait.ts
Original file line number Diff line number Diff line change
@@ -15,15 +15,14 @@ import type { SecuritySchemeInterface } from "../security-scheme";

export class OperationTrait extends Mixin(BaseModel, BindingsMixin, DescriptionMixin, ExtensionsMixin, ExternalDocumentationMixin, TagsMixin) implements OperationTraitInterface {
constructor(
private readonly _id: string,
_json: Record<string,any>,
public readonly _meta: ModelMetadata & { action: OperationAction } = {} as any,
protected readonly _meta: ModelMetadata & { id: string, action: OperationAction } = {} as any,
) {
super(_json, _meta);
}

id(): string {
return this.operationId() || this._id;
return this.operationId() || this._meta.id;
}

action(): OperationAction {
Loading

0 comments on commit ae4b0ff

Please sign in to comment.