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: port message, operation, correlation-id and security-requirements models #542

Merged
merged 4 commits into from
May 6, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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/models/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ export interface AsyncAPIDocumentInterface extends BaseModel, ExtensionsMixinInt
export function newAsyncAPIDocument(asyncapi: DetailedAsyncAPI): AsyncAPIDocumentInterface {
switch (asyncapi.semver.major) {
case 2:
return new AsyncAPIDocumentV2(asyncapi.parsed, { parent: null, asyncapi, pointer: '/' });
return new AsyncAPIDocumentV2(asyncapi.parsed, { asyncapi, pointer: '/' });
case 3:
return new AsyncAPIDocumentV3(asyncapi.parsed, { parent: null, asyncapi, pointer: '/' });
return new AsyncAPIDocumentV3(asyncapi.parsed, { asyncapi, pointer: '/' });
default:
throw new Error(`Unsupported AsyncAPI version: ${asyncapi.semver.version}`);
}
Expand Down
8 changes: 4 additions & 4 deletions src/models/base.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Constructor } from "./utils";
import type { DetailedAsyncAPI } from "../types";

export interface ModelMetadata<P = unknown> {
export interface ModelMetadata {
asyncapi: DetailedAsyncAPI;
pointer: string;
parent: P | null;
[key: string]: any;
}

export abstract class BaseModel {
Expand Down Expand Up @@ -32,8 +32,8 @@ export abstract class BaseModel {
return `${this._meta?.pointer}/${field}`;
}

protected createModel<T extends BaseModel>(Model: Constructor<T>, value: any, { id, parent, pointer }: { id?: string, parent?: any, pointer: string | number }): T {
const meta = { asyncapi: this._meta.asyncapi, parent: parent || this, pointer } as ModelMetadata;
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);
}
Expand Down
10 changes: 9 additions & 1 deletion src/models/channel-parameter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import type { BaseModel } from "./base";
import type { DescriptionMixinInterface, ExtensionsMixinInterface } from "./mixins";
import type { SchemaInterface } from "./schema";

export interface ChannelParameterInterface extends BaseModel {}
export interface ChannelParameterInterface extends BaseModel, DescriptionMixinInterface, ExtensionsMixinInterface {
id(): string;
hasSchema(): boolean;
Copy link
Member

Choose a reason for hiding this comment

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

schema(): SchemaInterface | undefined;
hasLocation(): boolean;
location(): string | undefined;
Copy link
Member

Choose a reason for hiding this comment

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

Same as before, If this should stay, should be added to https://github.com/asyncapi/parser-api/blob/master/docs/v1.md#channelparameter

Copy link
Member Author

Choose a reason for hiding this comment

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

The channel parameter has a location so it has to stay 😄

Copy link
Member

Choose a reason for hiding this comment

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

Would you mind then creating a PR on Parser-API repo?

}
12 changes: 11 additions & 1 deletion src/models/channel.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import type { BaseModel } from "./base";
import type { ChannelParametersInterface } from "./channel-parameters";
import type { BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface } from "./mixins";
import type { OperationsInterface } from "./operations";
import type { ServersInterface } from "./servers";

export interface ChannelInterface extends BaseModel {}
export interface ChannelInterface extends BaseModel, BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface {
id(): string;
address(): string;
servers(): ServersInterface;
operations(): OperationsInterface;
parameters(): ChannelParametersInterface;
}
6 changes: 5 additions & 1 deletion src/models/correlation-id.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import type { BaseModel } from "./base";
import type { DescriptionMixinInterface, ExtensionsMixinInterface } from "./mixins";

export interface CorrelationIdInterface extends BaseModel {}
export interface CorrelationIdInterface extends BaseModel, DescriptionMixinInterface, ExtensionsMixinInterface {
hasLocation(): boolean;
location(): string | undefined;
}
12 changes: 11 additions & 1 deletion src/models/message-example.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import type { BaseModel } from "./base";
import type { ExtensionsMixinInterface } from './mixins';

export interface MessageExample extends BaseModel {}
export interface MessageExampleInterface extends BaseModel, ExtensionsMixinInterface {
hasName(): boolean;
name(): string;
hasSummary(): boolean;
summary(): string;
hasHeaders(): boolean;
headers(): Record<string, any> | undefined;
hasPayload(): boolean;
payload(): Record<string, any> | undefined;
}
4 changes: 4 additions & 0 deletions src/models/message-examples.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Collection } from "./collection";
import type { MessageExampleInterface } from "./message-example";

export interface MessageExamplesInterface extends Collection<MessageExampleInterface> {}
23 changes: 22 additions & 1 deletion src/models/message-trait.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
import type { BaseModel } from "./base";
import type { CorrelationIdInterface } from "./correlation-id";
import type { MessageExamplesInterface } from "./message-examples";
import type { BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface, ExternalDocumentationMixinInterface, TagsMixinInterface } from './mixins';
import type { SchemaInterface } from "./schema";

export interface MessageTraitInterface extends BaseModel {}
export interface MessageTraitInterface extends BaseModel, BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface, ExternalDocumentationMixinInterface, TagsMixinInterface {
Copy link
Member

Choose a reason for hiding this comment

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

There are some missing methods from the Parser-API that I think should be implemented here (otherwise, discarded from the Parser-API).

  • hasKnownSchemaFormat() : boolean
  • schemaFormat() : string

See https://github.com/asyncapi/parser-api/blob/master/docs/v1.md#message

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 didn't add it on purpose for a simple reason. Defining schemaFormat at the messag level on a lot of problems from a schema reuse point of view, and I will try to move schemaFormat to the Schema object - then this will be removed. Here is my issue for 3.0.0 asyncapi/spec#622. If we want it I can add it, but I hope that in 99% we will remove it.

Copy link
Member

Choose a reason for hiding this comment

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

It makes sense indeed. How would you implement that? I think this should be then done in this PR

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 can add schemaFormat in this PR to Message model, but we can always remove it.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, makes sense.

I like the message.payload().schemaFormat() you suggested in asyncapi/spec#622. Maybe we can move forward with it later on, and now just adding an issue to work on it next?

Copy link
Member Author

Choose a reason for hiding this comment

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

Issue :) #544

id(): string;
hasMessageId(): boolean;
messageId(): string | undefined;
hasCorrelationId(): boolean;
correlationId(): CorrelationIdInterface | undefined;
hasContentType(): boolean;
contentType(): string | undefined;
hasHeaders(): boolean
headers(): SchemaInterface | undefined;
hasName(): boolean;
name(): string | undefined;
hasTitle(): boolean;
title(): string | undefined;
hasSummary(): boolean;
summary(): string | undefined;
examples(): MessageExamplesInterface;
}
2 changes: 1 addition & 1 deletion src/models/message-traits.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Collection } from "./collection";
import type { MessageTraitInterface } from "./message-trait";

export interface MessagesTraitsInterface extends Collection<MessageTraitInterface> {}
export interface MessageTraitsInterface extends Collection<MessageTraitInterface> {}
8 changes: 7 additions & 1 deletion src/models/message.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import type { BaseModel } from "./base";
import type { MessageTraitsInterface } from "./message-traits";
import type { MessageTraitInterface } from "./message-trait";
import type { SchemaInterface } from "./schema";

export interface MessageInterface extends BaseModel, MessageTraitInterface {}
export interface MessageInterface extends BaseModel, MessageTraitInterface {
hasPayload(): boolean;
payload(): SchemaInterface | undefined;
traits(): MessageTraitsInterface;
}
12 changes: 6 additions & 6 deletions src/models/oauth-flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { BaseModel } from './base';
import { ExtensionsMixinInterface } from './mixins';

export interface OAuthFlowInterface extends BaseModel, ExtensionsMixinInterface {
authorizationUrl(): string | undefined;
hasRefreshUrl(): boolean;
refreshUrl(): string | undefined;
scopes(): Record<string, string> | undefined;
tokenUrl(): string | undefined;
}
authorizationUrl(): string | undefined;
hasRefreshUrl(): boolean;
refreshUrl(): string | undefined;
scopes(): Record<string, string> | undefined;
tokenUrl(): string | undefined;
}
24 changes: 12 additions & 12 deletions src/models/oauth-flows.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { OAuthFlowInterface } from './oauth-flow';
import { BaseModel } from './base';
import {ExtensionsMixinInterface} from './mixins';
import type { BaseModel } from './base';
import type { OAuthFlowInterface } from './oauth-flow';
import type { ExtensionsMixinInterface } from './mixins';

export interface OAuthFlowsInterface extends BaseModel, ExtensionsMixinInterface {
hasAuthorizationCode(): boolean;
authorizationCode(): OAuthFlowInterface | undefined;
hasClientCredentials(): boolean
clientCredentials(): OAuthFlowInterface | undefined;
hasImplicit(): boolean;
implicit(): OAuthFlowInterface | undefined;
hasPassword(): boolean;
password(): OAuthFlowInterface | undefined;
}
hasAuthorizationCode(): boolean;
authorizationCode(): OAuthFlowInterface | undefined;
hasClientCredentials(): boolean
clientCredentials(): OAuthFlowInterface | undefined;
hasImplicit(): boolean;
implicit(): OAuthFlowInterface | undefined;
hasPassword(): boolean;
password(): OAuthFlowInterface | undefined;
}
13 changes: 12 additions & 1 deletion src/models/operation-trait.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
import type { BaseModel } from "./base";
import type { BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface, ExternalDocumentationMixinInterface, TagsMixinInterface } from './mixins';
import type { OperationKind } from "./operation";
import type { SecurityRequirementsInterface } from "./security-requirements";

export interface OperationTraitInterface extends BaseModel {}
export interface OperationTraitInterface extends BaseModel, BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface, ExternalDocumentationMixinInterface, TagsMixinInterface {
id(): string;
kind(): OperationKind;
Copy link
Member

Choose a reason for hiding this comment

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

This should be added into the Parser-API https://github.com/asyncapi/parser-api/blob/master/docs/v1.md#operation, as well as removing some of the methods related to Publish/Subscribe

Copy link
Member

@smoya smoya May 5, 2022

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right, we have inconsistencies. type in SecurityRequirements and here kind. In 3.0.0 we have for example called it as action (asyncapi/spec#618) so maybe we should call it action?

Copy link
Member

Choose a reason for hiding this comment

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

Indeed, action sounds like a better fit.

hasOperationId(): boolean;
operationId(): string | undefined;
hasSummary(): boolean;
summary(): string | undefined;
security(): SecurityRequirementsInterface;
}
2 changes: 1 addition & 1 deletion src/models/operation-traits.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Collection } from "./collection";
import type { OperationTraitInterface } from "./operation-trait";

export interface OperationsTraitsInterface extends Collection<OperationTraitInterface> {}
export interface OperationTraitsInterface extends Collection<OperationTraitInterface> {}
9 changes: 8 additions & 1 deletion src/models/operation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import type { BaseModel } from "./base";
import type { MessagesInterface } from "./messages";
import type { OperationTraitsInterface } from "./operation-traits";
import type { OperationTraitInterface } from "./operation-trait";

export interface OperationInterface extends BaseModel, OperationTraitInterface {}
export type OperationKind = 'send' | 'receive' | 'publish' | 'subscribe';

export interface OperationInterface extends BaseModel, OperationTraitInterface {
messages(): MessagesInterface;
traits(): OperationTraitsInterface;
}
3 changes: 2 additions & 1 deletion src/models/schema.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { BaseModel } from "./base";
import type { ExtensionsMixinInterface } from "./mixins";

export interface SchemaInterface extends BaseModel {}
export interface SchemaInterface extends BaseModel, ExtensionsMixinInterface {}
6 changes: 6 additions & 0 deletions src/models/security-requirement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { BaseModel } from "./base";
import type { SecuritySchemeInterface } from "./security-scheme";

export interface SecurityRequirementInterface extends BaseModel {
requirements(): Record<string, { schema: SecuritySchemeInterface, scopes: Array<string> }>;
}
4 changes: 4 additions & 0 deletions src/models/security-requirements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Collection } from "./collection";
import type { SecurityRequirementInterface } from "./security-requirement";

export interface SecurityRequirementsInterface extends Collection<SecurityRequirementInterface> {}
27 changes: 13 additions & 14 deletions src/models/security-scheme.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { BaseModel } from './base';
import { DescriptionMixinInterface, ExtensionsMixinInterface } from './mixins';
import { OAuthFlowsInterface } from './oauth-flows';
import type { BaseModel } from './base';
import type { OAuthFlowsInterface } from './oauth-flows';
import type { DescriptionMixinInterface, ExtensionsMixinInterface } from './mixins';

export type SecuritySchemaType = 'userPassword' | 'apiKey' | 'X509' | 'symmetricEncryption' | 'asymmetricEncryption' | 'httpApiKey' | 'http' | 'oauth2' | 'openIdConnect' | 'plain' | 'scramSha256' | 'scramSha512' | 'gssapi';


export interface SecuritySchemeInterface extends BaseModel, DescriptionMixinInterface, ExtensionsMixinInterface {
id(): string
hasBearerFormat(): boolean;
bearerFormat(): string | undefined;
openIdConnectUrl(): string;
scheme(): string | undefined;
flows(): OAuthFlowsInterface | undefined;
scopes(): string[];
type(): SecuritySchemaType;
in(): string | undefined;
}
id(): string
hasBearerFormat(): boolean;
bearerFormat(): string | undefined;
openIdConnectUrl(): string;
scheme(): string | undefined;
flows(): OAuthFlowsInterface | undefined;
scopes(): string[];
type(): SecuritySchemaType;
in(): string | undefined;
}
6 changes: 3 additions & 3 deletions src/models/security-schemes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Collection} from './collection';
import { SecuritySchemeInterface } from './security-scheme';
import type { Collection} from './collection';
import type { SecuritySchemeInterface } from './security-scheme';

export interface SecuritySchemesInterface extends Collection<SecuritySchemeInterface> {}
export interface SecuritySchemesInterface extends Collection<SecuritySchemeInterface> {}
4 changes: 2 additions & 2 deletions src/models/server-variable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface ServerVariableInterface extends BaseModel, DescriptionMixinInte
id(): string;
hasDefaultValue(): boolean;
defaultValue(): string | undefined;
hasAllowedValue(): boolean;
allowedValue(): Array<string>;
hasAllowedValues(): boolean;
allowedValues(): Array<string>;
examples(): Array<string>;
}
8 changes: 5 additions & 3 deletions src/models/server.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import type { BaseModel } from "./base";
import type { BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface } from './mixins';
import type { ServerVariablesInterface } from "./server-variables";
import type { SecurityRequirementsInterface } from "./security-requirements";

export interface ServerInterface extends BaseModel, DescriptionMixinInterface, BindingsMixinInterface, ExtensionsMixinInterface {
id(): string
url(): string;
protocol(): string | undefined;
protocol(): string;
protocolVersion(): string;
hasProtocolVersion(): boolean;
variables(): ServerVariablesInterface
}
variables(): ServerVariablesInterface;
security(): SecurityRequirementsInterface;
}
5 changes: 1 addition & 4 deletions src/models/v2/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ import { ExtensionsMixin } from './mixins/extensions';
import type { AsyncAPIDocumentInterface, InfoInterface } from "../../models";
import type { ServersInterface } from "models/servers";

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

export class AsyncAPIDocument extends Mixin(BaseModel, ExtensionsMixin) implements AsyncAPIDocumentInterface {
version(): string {
return this._json.asyncapi;
}
Expand Down
17 changes: 17 additions & 0 deletions src/models/v2/correlation-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { BaseModel } from "../base";

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

import type { CorrelationIdInterface } from "../correlation-id";

export class CorrelationId extends Mixin(BaseModel, DescriptionMixin, ExtensionsMixin) implements CorrelationIdInterface {
hasLocation(): boolean {
return !!this._json.location;
}

location(): string | undefined {
return this._json.location;
}
}
4 changes: 2 additions & 2 deletions src/models/v2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ export { SecurityScheme as SecuritySchemeV2 } from './security-scheme';
export { SecuritySchemes as SecuritySchemesV2 } from './security-schemes';
export { ServerVariable as ServerVariableV2 } from './server-variable';
export { ServerVariables as ServerVariablesV2 } from './server-variables';
export {OAuthFlow as OAuthFlowV2} from './oauth-flow';
export {OAuthFlows as OAuthFlowsV2} from './oauth-flows';
export { OAuthFlow as OAuthFlowV2 } from './oauth-flow';
export { OAuthFlows as OAuthFlowsV2 } from './oauth-flows';
Loading