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

feat: add all{components} functions #969

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
18 changes: 18 additions & 0 deletions src/models/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ import type { OperationsInterface } from './operations';
import type { SchemasInterface } from './schemas';
import type { SecuritySchemesInterface } from './security-schemes';
import type { ServersInterface } from './servers';
import type { ServerVariablesInterface } from './server-variables';
import type { ChannelParametersInterface } from './channel-parameters';
import type { CorrelationIdsInterface } from './correlation-ids';
import type { TagsInterface } from './tags';
import type { OperationTraitsInterface } from './operation-traits';
import type { MessageTraitsInterface } from './message-traits';
import type { BindingsInterface } from './bindings';

import type { v2, v3 } from '../spec-types';

Expand All @@ -31,4 +38,15 @@ export interface AsyncAPIDocumentInterface extends BaseModel<v2.AsyncAPIObject |
allOperations(): OperationsInterface;
allMessages(): MessagesInterface;
allSchemas(): SchemasInterface;
allSecuritySchemes(): SecuritySchemesInterface;
allServerVariables(): ServerVariablesInterface;
allParameters(): ChannelParametersInterface;
allCorrelationIds(): CorrelationIdsInterface;
allTags(): TagsInterface;
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 Author

Choose a reason for hiding this comment

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

@smoya I'm a little confused about where to add the allReplies function. If I add it here, then v2 also needs to implement it. But v2 doesn't have replies. I see three possible approaches:

  1. Remove allReplies from parser-api since it can't be implemented for v2.
  2. Add it here and return an empty array for the v2 implementation.
  3. Add allReplies to v3 only.

I would appreciate some insight on this.

allOperationTraits(): OperationTraitsInterface;
allMessageTraits(): MessageTraitsInterface;
allServerBindings(): BindingsInterface;
allChannelBindings(): BindingsInterface;
allOperationBindings(): BindingsInterface;
allMessageBindings(): BindingsInterface;
}
99 changes: 98 additions & 1 deletion src/models/v2/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import { Server } from './server';
import { SecuritySchemes } from './security-schemes';
import { SecurityScheme } from './security-scheme';
import { Schemas } from './schemas';
import { Bindings } from './bindings';

import { extensions } from './mixins';
import { extensions, tags } from './mixins';
import { tilde } from '../../utils';
import { schemasFromDocument } from '../utils';

Expand All @@ -29,10 +30,106 @@ import type { MessageInterface } from '../message';
import type { SchemasInterface } from '../schemas';
import type { SecuritySchemesInterface } from '../security-schemes';
import type { ExtensionsInterface } from '../extensions';
import type { BindingsInterface } from 'models/bindings';
import type { ChannelParametersInterface } from 'models/channel-parameters';
import type { CorrelationIdsInterface } from 'models/correlation-ids';
import type { MessageTraitsInterface } from 'models/message-traits';
import type { OperationTraitsInterface } from 'models/operation-traits';
import type { ServerVariablesInterface } from 'models/server-variables';
import type { TagsInterface } from 'models/tags';

import type { v2 } from '../../spec-types';

export class AsyncAPIDocument extends BaseModel<v2.AsyncAPIObject> implements AsyncAPIDocumentInterface {
allSecuritySchemes(): SecuritySchemesInterface {
return this.securitySchemes();
}
allServerVariables(): ServerVariablesInterface {
const serverVariables: ServerVariablesInterface = this.components().serverVariables();
this.allServers().forEach(server => serverVariables.push(...server.variables()));
return serverVariables;
}
allParameters(): ChannelParametersInterface {
const channelParameters: ChannelParametersInterface = this.components().channelParameters();
this.allChannels().forEach(channel => channelParameters.push(...channel.parameters()));
return channelParameters;
}
allCorrelationIds(): CorrelationIdsInterface {
const correlationIds: CorrelationIdsInterface = this.components().correlationIds();
this.allMessages().forEach(message => {
message.traits().forEach(trait => {
const correlationId = trait.correlationId();
if (!correlationId) {
return;
}
if (!correlationIds.includes(correlationId)) {
correlationIds.push(correlationId);
}
});

const correlationId = message.correlationId();
if (!correlationId) {
return;
}
if (!correlationIds.includes(correlationId)) {
correlationIds.push(correlationId);
}
});
return correlationIds;
}
allTags(): TagsInterface {
const rootTags: TagsInterface = tags(this);
this.allServers().forEach(server => rootTags.push(...server.tags()));
this.allOperations().forEach(channel => rootTags.push(...channel.tags()));
this.allOperationTraits().forEach(trait => rootTags.push(...trait.tags()));
this.allMessages().forEach(message => rootTags.push(...message.tags()));
this.allMessageTraits().forEach(trait => rootTags.push(...trait.tags()));
return rootTags;
}
allOperationTraits(): OperationTraitsInterface {
const operationTraits: OperationTraitsInterface = this.components().operationTraits();
this.allOperations().forEach(operation => operation.traits().forEach(trait => (
!operationTraits.some(t => t.json() === trait.json()) && operationTraits.push(trait)
)));

return operationTraits;
}
allMessageTraits(): MessageTraitsInterface {
const messageTraits: MessageTraitsInterface = this.components().messageTraits();
this.allMessages().forEach(message => message.traits().forEach(trait => (
!messageTraits.some(t => t.json() === trait.json()) && messageTraits.push(trait)
)));

return messageTraits;
}
allServerBindings(): BindingsInterface {
const serverBindings = Object.values(this.components().serverBindings()).flat();
this.allServers().forEach(server => server.bindings().forEach(binding => (
!serverBindings.some(b => b.json() === binding.json()) && serverBindings.push(binding)
)));
return new Bindings(serverBindings);
}
allChannelBindings(): BindingsInterface {
const channelBindings = Object.values(this.components().channelBindings()).flat();
this.allChannels().forEach(channel => channel.bindings().forEach(binding => (
!channelBindings.some(b => b.json() === binding.json()) && channelBindings.push(binding)
)));
return new Bindings(channelBindings);
}
allOperationBindings(): BindingsInterface {
const operationBindings = Object.values(this.components().operationBindings()).flat();
this.allOperations().forEach(operation => operation.bindings().forEach(binding => (
!operationBindings.some(b => b.json() === binding.json()) && operationBindings.push(binding)
)));
return new Bindings(operationBindings);
}
allMessageBindings(): BindingsInterface {
const messageBindings = Object.values(this.components().messageBindings()).flat();
this.allMessages().forEach(message => message.bindings().forEach(binding => (
!messageBindings.some(b => b.json() === binding.json()) && messageBindings.push(binding)
)));
return new Bindings(messageBindings);
}
version(): string {
return this._json.asyncapi;
}
Expand Down
164 changes: 164 additions & 0 deletions src/models/v3/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { SecuritySchemes } from './security-schemes';
import { SecurityScheme } from './security-scheme';
import { Components } from './components';
import { Schemas } from './schemas';
import { Bindings } from './bindings';
import { Tags } from './tags';

import { extensions } from './mixins';
import { tilde } from '../../utils';
Expand All @@ -30,10 +32,172 @@ import type { SchemasInterface } from '../schemas';
import type { OperationInterface } from '../operation';
import type { ChannelInterface } from '../channel';
import type { ServerInterface } from '../server';
import type { BindingsInterface } from 'models/bindings';
import type { ChannelParametersInterface } from 'models/channel-parameters';
import type { CorrelationIdsInterface } from 'models/correlation-ids';
import type { MessageTraitsInterface } from 'models/message-traits';
import type { OperationTraitsInterface } from 'models/operation-traits';
import type { ServerVariablesInterface } from 'models/server-variables';
import type { TagsInterface } from 'models/tags';
import type { Tag } from './tag';
import type { TagInterface } from 'models/tag';

import type { v3 } from '../../spec-types';

export class AsyncAPIDocument extends BaseModel<v3.AsyncAPIObject> implements AsyncAPIDocumentInterface {
allSecuritySchemes(): SecuritySchemesInterface {
return this.securitySchemes();
Copy link
Member

@smoya smoya Apr 8, 2024

Choose a reason for hiding this comment

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

I see two issues here:

  1. If allSecuritySchemes does the same as securitySchemes, then this is redundant.
  2. I believe securitySchemes method implementation is wrong ATM because it is only returning Security Schemes from components but instead would need to return from, for example, Operations in the root document.

cc @jonaslagoni please double 👀 just in case I'm delirious.

Copy link
Member Author

Choose a reason for hiding this comment

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

  1. If allSecuritySchemes does the same as securitySchemes, then this is redundant.

I agree. it has only been added for the sake of completeness.

  1. I believe securitySchemes method implementation is wrong ATM because it is only returning Security Schemes from components but instead would need to return from, for example, Operations in the root document.

the problem is that when I try to access the security scheme of an specific operation or operationTrait it returns SecurityRequirements[] instead of SecuritySchemes.

not sure if this is a bug or I am missing something.

Copy link
Member Author

Choose a reason for hiding this comment

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

@smoya pingy pongy.

}
allServerVariables(): ServerVariablesInterface {
const serverVariables: ServerVariablesInterface = this.components().serverVariables();
this.servers().forEach(server => {
server.variables().forEach(variable => {
if (!serverVariables.has(variable.id())) {
serverVariables.push(variable);
}
});
});

return serverVariables;
}
allParameters(): ChannelParametersInterface {
const parameters: ChannelParametersInterface = this.components().channelParameters();
this.channels().forEach(channel => {
channel.parameters().forEach(parameter => {
if (!parameters.includes(parameter)) {
parameters.push(parameter);
}
});
});
return parameters;
}

allCorrelationIds(): CorrelationIdsInterface {
const correlationIds: CorrelationIdsInterface = this.components().correlationIds();
this.allMessages().forEach(message => {
const correlationId = message.correlationId();
if (correlationId) {
correlationIds.push(correlationId);
}
});

this.allMessageTraits().forEach(trait => {
const correlationId = trait.correlationId();
if (correlationId) {
correlationIds.push(correlationId);
}
});

return correlationIds;
}
allTags(): TagsInterface {
const tags: TagInterface[] = Object.values(this.components().json().tags || {}) || [];
this.info().tags().forEach(tag => {
if (!tags.includes(tag)) {
tags.push(tag);
}
});

this.servers().forEach(server => {
server.tags().forEach(tag => {
if (!tags.includes(tag)) {
tags.push(tag);
}
});
});

this.channels().forEach(channel => {
(channel.json().tags || []).forEach((tag: Tag) => {
if (!tags.includes(tag)) {
tags.push(tag);
}
});
});

this.operations().forEach(operation => {
operation.tags().forEach(tag => {
if (!tags.includes(tag)) {
tags.push(tag);
}
});
});

this.allOperationTraits().forEach(trait => {
trait.tags().forEach(tag => {
if (!tags.includes(tag)) {
tags.push(tag);
}
});
});

this.allMessages().forEach(message => {
message.tags().forEach(tag => {
if (!tags.includes(tag)) {
tags.push(tag);
}
});
});

this.allMessageTraits().forEach(trait => {
trait.tags().forEach(tag => {
if (!tags.includes(tag)) {
tags.push(tag);
}
});
});

return new Tags(tags);
}
allOperationTraits(): OperationTraitsInterface {
const traits: OperationTraitsInterface = this.components().operationTraits();
this.operations().forEach(operation => {
operation.traits().forEach(trait => {
if (!traits.includes(trait)) {
traits.push(trait);
}
});
});
return traits;
}
allMessageTraits(): MessageTraitsInterface {
const messageTraits: MessageTraitsInterface = this.components().messageTraits();
this.allMessages().forEach(message => {
message.traits().forEach(trait => {
if (!messageTraits.includes(trait)) {
messageTraits.push(trait);
}
});
});
return messageTraits;
}
allServerBindings(): BindingsInterface {
const serverBindings = Object.values(this.components().serverBindings()).flat();
this.allServers().forEach(server => server.bindings().forEach(binding => (
!serverBindings.some(b => b.json() === binding.json()) && serverBindings.push(binding)
)));
return new Bindings(serverBindings);
}
allChannelBindings(): BindingsInterface {
const channelBindings = Object.values(this.components().channelBindings()).flat();
this.allChannels().forEach(channel => channel.bindings().forEach(binding => (
!channelBindings.some(b => b.json() === binding.json()) && channelBindings.push(binding)
)));
return new Bindings(channelBindings);
}
allOperationBindings(): BindingsInterface {
const operationBindings = Object.values(this.components().operationBindings()).flat();
this.allOperations().forEach(operation => operation.bindings().forEach(binding => (
!operationBindings.some(b => b.json() === binding.json()) && operationBindings.push(binding)
)));
return new Bindings(operationBindings);
}
allMessageBindings(): BindingsInterface {
const messageBindings = Object.values(this.components().messageBindings()).flat();
this.allMessages().forEach(message => message.bindings().forEach(binding => (
!messageBindings.some(b => b.json() === binding.json()) && messageBindings.push(binding)
)));
return new Bindings(messageBindings);
}
version(): string {
return this._json.asyncapi;
}
Expand Down
Loading
Loading