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: add models for server object #497

Merged
merged 17 commits into from
Mar 25, 2022
Merged
Show file tree
Hide file tree
Changes from 12 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
2 changes: 2 additions & 0 deletions src/models/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { AsyncAPIDocumentV3 } from "./v3";
import type { InfoInterface } from "./info";
import type { BaseModel } from "./base";
import type { ExtensionsMixinInterface } from "./mixins";
import { ServersInterface } from "./servers";

export interface AsyncAPIDocumentInterface extends BaseModel, ExtensionsMixinInterface {
version(): string;
info(): InfoInterface;
servers(): ServersInterface
}

export function newAsyncAPIDocument(json: Record<string, any>): AsyncAPIDocumentInterface {
Expand Down
14 changes: 14 additions & 0 deletions src/models/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { BaseModel } from "./base";
import { BindingsMixinInterface, DescriptionMixinInterface } from './mixins';

export interface ServerInterface extends BaseModel, DescriptionMixinInterface, BindingsMixinInterface {
id(): string;
name(): string | undefined;
hasName(): boolean;
protocol(): string | undefined;
hasProtocol(): boolean;
protocolVersion(): string;
hasProtocolVersion(): boolean;
url(): string;
hasUrl(): boolean;
}
4 changes: 4 additions & 0 deletions src/models/servers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Collection } from "./collection";
import {ServerInterface} from "./server";

export interface ServersInterface extends Collection<ServerInterface> {}
10 changes: 10 additions & 0 deletions src/models/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,14 @@ function mixin(derivedCtor: any, constructors: any[]): typeof BaseModel {
});
});
return derivedCtor;
}

export function createArrayFromMap(json: Record<string,any>){
const ArrayObject = [];
for (const [key, value] of Object.entries(json)) {
value['id'] = key;
ArrayObject.push(value);
};

return ArrayObject;
}
8 changes: 7 additions & 1 deletion src/models/v2/asyncapi.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { BaseModel } from "../base";
import { Info } from "./info";

import { Mixin } from '../utils';
import { createArrayFromMap, Mixin } from '../utils';
import { ExtensionsMixin } from './mixins/extensions';

import { AsyncAPIDocumentInterface, InfoInterface } from "../../models";
import { ServersInterface } from "models/servers";
import { Servers } from "./servers";

export class AsyncAPIDocument
extends Mixin(BaseModel, ExtensionsMixin)
Expand All @@ -17,4 +19,8 @@ export class AsyncAPIDocument
info(): InfoInterface {
return new Info(this._json.info);
}

servers(): ServersInterface {
return new Servers(createArrayFromMap(this._json.servers));
}
Souvikns marked this conversation as resolved.
Show resolved Hide resolved
}
4 changes: 3 additions & 1 deletion src/models/v2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ export { License as LicenseV2 } from './license';
export { Bindings as BindingsV2, Binding as BindingV2 } from './mixins/bindings';
export { Extensions as ExtensionsV2, Extension as ExtensionV2 } from './mixins/extensions';
export { ExternalDocumentation as ExternalDocumentationV2 } from './mixins/external-docs';
export { Tags as TagsV2, Tag as TagV2 } from './mixins/tags';
export { Tags as TagsV2, Tag as TagV2 } from './mixins/tags';
export { Server as ServerV2 } from './server';
export { Servers as ServersV2 } from './servers';
43 changes: 43 additions & 0 deletions src/models/v2/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Mixin } from '../utils';
import { BaseModel } from '../base';
import { ServerInterface } from '../server';
import { DescriptionMixin } from './mixins/description';
import { BindingsMixin } from './mixins/bindings';

export class Server extends Mixin(BaseModel, DescriptionMixin, BindingsMixin) implements ServerInterface {
id(): string {
return this.json('id');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had discussion in Slack that id should not be a part of _json :) I also gave you example how it should work - https://github.com/asyncapi/parser-js/blob/next-major/src/models/v2/mixins/extensions.ts#L11

Suggested change
id(): string {
return this.json('id');
}
constructor(
private readonly _id: string,
_json: Record<string, any>,
) {
super(_json);
}
id(): string {
return this._id;
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this because I modeled the utils function to convert object to array something like this

export function createArrayFromMap(json: Record<string,any>){
  const ArrayObject = [];
  for (const [key, value] of Object.entries(json)) {
    value['id'] = key;
    ArrayObject.push(value);
  };

  return ArrayObject;
}

so I thought maybe I don't need the add a separate id variable can just get it to format it. Main reason was so that the v2 and v3 have minimal changes, because to add seperate _id parameter now we have to pass something like new Servers(id, this._json)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v3 changes may be much bigger than they are now (to be honest we don't have anything approved so v3=v2 now), so please don't look at this proposal from Fran as something final.

About id. Have in mind that if someone will run json() should get the value that is defined for the object in the specification (not including traits because we have to combine them) without any additional fields that are not defined in the object, so what you want to get with adding the id field is nothing more than changing the original json. I know that adding an id as an argument to a constructor can be weird, but in this case the id is outside the object, and in v3 it can be part of the object and it will be easier to handle.


hasName(): boolean {
return !!this.json('name');
}

name(): string | undefined {
return this.json('name');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@smoya smoya Mar 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name is the key in the map of servers. But I think we can change it to ID to be consistent?

Copy link
Member

@magicmatatjahu magicmatatjahu Mar 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is id then?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the key in the map of servers

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, so name and hasName is out @Souvikns

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So then what is id? I was thinking that id is the key

Copy link
Member

@smoya smoya Mar 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to use id() for all objects like Channel, Server, Operation, etc, instead of path() for Channels, name for Servers, etc
If we add a ID method for all of those models, no matter if we later change the source of them between versions.
I know the parser-api doesn’t reflect that but we learnt a lot during the last few months :)


hasProtocol(): boolean {
return !!this.json('protocol');
}

protocol(): string | undefined {
return this.json('protocol');
}

hasProtocolVersion(): boolean {
return !!this.json('protocolVersion');
}

protocolVersion(): string {
return this.json('protocolVersion');
}

hasUrl(): boolean {
return !!this.json('url');
}

url(): string {
return this.json('url');
}
Souvikns marked this conversation as resolved.
Show resolved Hide resolved
Souvikns marked this conversation as resolved.
Show resolved Hide resolved
}
13 changes: 13 additions & 0 deletions src/models/v2/servers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Collection } from '../collection';
import { ServerInterface } from '../server';
import { ServersInterface } from '../servers';

export class Servers extends Collection<ServerInterface> implements ServersInterface {
override get(id: string): ServerInterface | undefined {
return this.collections.find(server => server.id() === id);
}

override has(id: string): boolean {
return this.collections.some(server => server.id() === id);
}
}
8 changes: 7 additions & 1 deletion src/models/v3/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@ import { Info } from "./info";

import { Mixin } from '../utils';
import { ExtensionsMixin } from './mixins/extensions';
import { ServersInterface } from "models/servers";
import { Servers } from "./servers";

export class AsyncAPIDocument
extends Mixin(BaseModel, ExtensionsMixin)
implements AsyncAPIDocumentInterface {

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

info(): Info {
return new Info(this.json("info"));
}

servers(): ServersInterface {
return new Servers(this._json.servers);
}
Souvikns marked this conversation as resolved.
Show resolved Hide resolved
}
4 changes: 3 additions & 1 deletion src/models/v3/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ export { License as LicenseV3 } from './license';
export { Bindings as BindingsV3, Binding as BindingV3 } from './mixins/bindings';
export { Extensions as ExtensionsV3, Extension as ExtensionV3 } from './mixins/extensions';
export { ExternalDocumentation as ExternalDocumentationV3 } from './mixins/external-docs';
export { Tags as TagsV3, Tag as TagV3 } from './mixins/tags';
export { Tags as TagsV3, Tag as TagV3 } from './mixins/tags';
export { Server as ServerV3 } from './server';
export { Servers as ServersV3 } from './servers';
43 changes: 43 additions & 0 deletions src/models/v3/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Mixin } from '../utils';
import { BaseModel } from '../base';
import { ServerInterface } from '../server';
import { DescriptionMixin } from './mixins/description';
import { BindingsMixin } from './mixins/bindings';

export class Server extends Mixin(BaseModel, DescriptionMixin, BindingsMixin) implements ServerInterface {
Souvikns marked this conversation as resolved.
Show resolved Hide resolved
id(): string {
return this.json('id');
}

hasName(): boolean {
return !!this.json('name');
}

name(): string | undefined {
return this.json('name');
}

hasProtocol(): boolean {
return !!this.json('protocol');
}

protocol(): string | undefined {
return this.json('protocol');
}

hasProtocolVersion(): boolean {
return !!this.json('protocolVersion');
}

protocolVersion(): string {
return this.json('protocolVersion');
}

hasUrl(): boolean {
return !!this.json('url');
}

url(): string {
return this.json('url');
}
}
13 changes: 13 additions & 0 deletions src/models/v3/servers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Collection } from '../collection';
import { ServerInterface } from '../server';
import { ServersInterface } from '../servers';

export class Servers extends Collection<ServerInterface> implements ServersInterface {
override get(id: string): ServerInterface | undefined {
return this.collections.find(server => server.id() === id);
}

override has(id: string): boolean {
return this.collections.some(server => server.id() === id);
}
}
14 changes: 13 additions & 1 deletion test/models/v2/asyncapi.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { newAsyncAPIDocument, AsyncAPIDocumentV2, InfoV2, AsyncAPIDocumentV3 } from '../../../src/models';
import { newAsyncAPIDocument, AsyncAPIDocumentV2, InfoV2, AsyncAPIDocumentV3, ServersV2 } from '../../../src/models';

import {
assertExtensionsMixinInheritance,
Expand Down Expand Up @@ -27,6 +27,18 @@ describe('AsyncAPIDocument model', function() {
});
});

describe('.servers()', function(){
it('should return an servers object', function(){
const doc = {servers: {
development: {

}
}};
const d = new AsyncAPIDocumentV2(doc);
expect(d.servers() instanceof ServersV2).toBeTruthy();
})
})

describe('mixins inheritance', function() {
assertExtensionsMixinInheritance(AsyncAPIDocumentV2);
});
Expand Down
Loading