Skip to content

Commit 6743a89

Browse files
refactor: add missed methods to models (#553)
1 parent 06f273e commit 6743a89

17 files changed

+728
-48
lines changed

src/models/asyncapi.ts

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,37 @@
11
import { AsyncAPIDocumentV2 } from "./v2";
22

3-
import type { InfoInterface } from "./info";
43
import type { BaseModel } from "./base";
4+
import type { InfoInterface } from "./info";
5+
import type { ChannelsInterface } from "./channels";
6+
import type { ComponentsInterface } from "./components";
7+
import type { MessagesInterface } from "./messages";
58
import type { ExtensionsMixinInterface } from "./mixins";
9+
import type { OperationsInterface } from "./operations";
10+
import type { SchemasInterface } from "./schemas";
11+
import type { SecuritySchemesInterface } from "./security-schemes";
612
import type { ServersInterface } from "./servers";
713
import type { DetailedAsyncAPI } from "../types";
814

915
export interface AsyncAPIDocumentInterface extends BaseModel, ExtensionsMixinInterface {
1016
version(): string;
17+
defaultContentType(): string | undefined;
18+
hasDefaultContentType(): boolean;
1119
info(): InfoInterface;
1220
servers(): ServersInterface;
21+
channels(): ChannelsInterface;
22+
operations(): OperationsInterface;
23+
messages(): MessagesInterface;
24+
schemas(): SchemasInterface;
25+
securitySchemes(): SecuritySchemesInterface;
26+
components(): ComponentsInterface;
1327
}
1428

1529
export function newAsyncAPIDocument(asyncapi: DetailedAsyncAPI): AsyncAPIDocumentInterface {
1630
switch (asyncapi.semver.major) {
1731
case 2:
1832
return new AsyncAPIDocumentV2(asyncapi.parsed, { asyncapi, pointer: '/' });
1933
// case 3:
20-
// return new AsyncAPIDocumentV3(asyncapi.parsed, { asyncapi, pointer: '/' }) as any;
34+
// return new AsyncAPIDocumentV3(asyncapi.parsed, { asyncapi, pointer: '/' });
2135
default:
2236
throw new Error(`Unsupported AsyncAPI version: ${asyncapi.semver.version}`);
2337
}

src/models/channel.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { BaseModel } from "./base";
22
import type { ChannelParametersInterface } from "./channel-parameters";
3+
import type { MessagesInterface } from "./messages";
34
import type { BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface } from "./mixins";
45
import type { OperationsInterface } from "./operations";
56
import type { ServersInterface } from "./servers";
@@ -9,5 +10,6 @@ export interface ChannelInterface extends BaseModel, BindingsMixinInterface, Des
910
address(): string;
1011
servers(): ServersInterface;
1112
operations(): OperationsInterface;
13+
messages(): MessagesInterface;
1214
parameters(): ChannelParametersInterface;
1315
}

src/models/message.ts

+6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import type { BaseModel } from "./base";
2+
import type { ChannelsInterface } from "./channels";
23
import type { MessageTraitsInterface } from "./message-traits";
34
import type { MessageTraitInterface } from "./message-trait";
5+
import type { OperationsInterface } from "./operations";
46
import type { SchemaInterface } from "./schema";
7+
import type { ServersInterface } from "./servers";
58

69
export interface MessageInterface extends BaseModel, MessageTraitInterface {
710
hasPayload(): boolean;
811
payload(): SchemaInterface | undefined;
12+
servers(): ServersInterface;
13+
channels(): ChannelsInterface;
14+
operations(): OperationsInterface;
915
traits(): MessageTraitsInterface;
1016
}

src/models/operation.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import type { BaseModel } from "./base";
2+
import type { ChannelsInterface } from "./channels";
23
import type { MessagesInterface } from "./messages";
34
import type { OperationTraitsInterface } from "./operation-traits";
45
import type { OperationTraitInterface } from "./operation-trait";
6+
import type { ServersInterface } from "./servers";
57

68
export type OperationAction = 'send' | 'receive' | 'publish' | 'subscribe';
79

810
export interface OperationInterface extends BaseModel, OperationTraitInterface {
11+
servers(): ServersInterface;
12+
channels(): ChannelsInterface;
913
messages(): MessagesInterface;
1014
traits(): OperationTraitsInterface;
1115
}

src/models/server.ts

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import type { BaseModel } from "./base";
2+
import type { ChannelsInterface } from './channels'
3+
import type { MessagesInterface } from './messages'
24
import type { BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface } from './mixins';
5+
import type { OperationsInterface } from './operations'
36
import type { ServerVariablesInterface } from "./server-variables";
47
import type { SecuritySchemeInterface } from "./security-scheme";
58

@@ -9,6 +12,9 @@ export interface ServerInterface extends BaseModel, DescriptionMixinInterface, B
912
protocol(): string;
1013
protocolVersion(): string;
1114
hasProtocolVersion(): boolean;
15+
channels(): ChannelsInterface;
16+
operations(): OperationsInterface;
17+
messages(): MessagesInterface;
1218
variables(): ServerVariablesInterface;
1319
security(): Array<Record<string, { schema: SecuritySchemeInterface; scopes: string[]; }>>;
1420
}

src/models/v2/asyncapi.ts

+65-2
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,46 @@
11
import { BaseModel } from "../base";
22
import { Info } from "./info";
3+
import { Channels } from "./channels";
4+
import { Channel } from "./channel";
5+
import { Components } from "./components";
6+
import { Messages } from "./messages";
7+
import { Operations } from "./operations";
38
import { Servers } from "./servers";
49
import { Server } from "./server";
10+
import { SecuritySchemes } from "./security-schemes";
11+
import { SecurityScheme } from "./security-scheme";
12+
import { Schemas } from "./schemas";
513

614
import { Mixin } from '../utils';
715
import { ExtensionsMixin } from './mixins/extensions';
816

9-
import type { AsyncAPIDocumentInterface, InfoInterface } from "../../models";
10-
import type { ServersInterface } from "models/servers";
17+
import { tilde } from '../../utils';
18+
19+
import type { AsyncAPIDocumentInterface } from "../asyncapi";
20+
import type { InfoInterface } from "../info";
21+
import type { ServersInterface } from "../servers";
22+
import type { ChannelsInterface } from "../channels";
23+
import type { ComponentsInterface } from "../components";
24+
import type { OperationsInterface } from "../operations";
25+
import type { OperationInterface } from "../operation";
26+
import type { MessagesInterface } from "../messages";
27+
import type { MessageInterface } from "../message";
28+
import type { SchemasInterface } from "../schemas";
29+
import type { SecuritySchemesInterface } from "../security-schemes";
1130

1231
export class AsyncAPIDocument extends Mixin(BaseModel, ExtensionsMixin) implements AsyncAPIDocumentInterface {
1332
version(): string {
1433
return this._json.asyncapi;
1534
}
1635

36+
defaultContentType(): string | undefined {
37+
return this._json.defaultContentType;
38+
}
39+
40+
hasDefaultContentType(): boolean {
41+
return !!this._json.defaultContentType;
42+
}
43+
1744
info(): InfoInterface {
1845
return this.createModel(Info, this._json.info, { pointer: '/info' });
1946
}
@@ -25,4 +52,40 @@ export class AsyncAPIDocument extends Mixin(BaseModel, ExtensionsMixin) implemen
2552
)
2653
);
2754
}
55+
56+
channels(): ChannelsInterface {
57+
return new Channels(
58+
Object.entries(this._json.channels || {}).map(([channelAddress, channel]) =>
59+
this.createModel(Channel, channel, { id: channelAddress, address: channelAddress, pointer: `/channels/${tilde(channelAddress)}` })
60+
)
61+
);
62+
}
63+
64+
operations(): OperationsInterface {
65+
const operations: OperationInterface[] = [];
66+
this.channels().forEach(channel => operations.push(...channel.operations().all()));
67+
return new Operations(operations);
68+
}
69+
70+
messages(): MessagesInterface {
71+
const messages: MessageInterface[] = [];
72+
this.operations().forEach(operation => messages.push(...operation.messages().all()));
73+
return new Messages(messages);
74+
}
75+
76+
schemas(): SchemasInterface {
77+
return new Schemas([]);
78+
}
79+
80+
securitySchemes(): SecuritySchemesInterface {
81+
return new SecuritySchemes(
82+
Object.entries(this._json.components?.securitySchemes || {}).map(([securitySchemeName, securityScheme]) =>
83+
this.createModel(SecurityScheme, securityScheme, { id: securitySchemeName, pointer: `/components/securitySchemes/${securitySchemeName}` })
84+
)
85+
);
86+
}
87+
88+
components(): ComponentsInterface {
89+
return new Components(this._json.components || {});
90+
}
2891
}

src/models/v2/channel.ts

+13-10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import { ExtensionsMixin } from './mixins/extensions';
1515
import type { ModelMetadata } from "../base";
1616
import type { ChannelInterface } from "../channel";
1717
import type { ChannelParametersInterface } from "../channel-parameters";
18+
import type { MessagesInterface } from "../messages";
19+
import type { MessageInterface } from "../message";
1820
import type { OperationsInterface } from "../operations";
1921
import type { OperationInterface } from "../operation";
2022
import type { ServersInterface } from "../servers";
@@ -48,20 +50,21 @@ export class Channel extends Mixin(BaseModel, BindingsMixin, DescriptionMixin, E
4850
}
4951

5052
operations(): OperationsInterface {
51-
const operations: OperationInterface[] = []
52-
if (this._json.publish) {
53-
operations.push(
54-
this.createModel(Operation, this._json.publish, { id: 'publish', action: 'publish', pointer: `${this._meta.pointer}/publish` }),
53+
const operations: OperationInterface[] = [];
54+
['publish', 'subscribe'].forEach(operationAction => {
55+
this._json[operationAction] && operations.push(
56+
this.createModel(Operation, this._json[operationAction], { id: operationAction, action: operationAction, pointer: `${this._meta.pointer}/${operationAction}` }),
5557
);
56-
}
57-
if (this._json.subscribe) {
58-
operations.push(
59-
this.createModel(Operation, this._json.subscribe, { id: 'subscribe', action: 'subscribe', pointer: `${this._meta.pointer}/subscribe` }),
60-
);
61-
}
58+
});
6259
return new Operations(operations);
6360
}
6461

62+
messages(): MessagesInterface {
63+
const messages: MessageInterface[] = [];
64+
this.operations().forEach(operation => messages.push(...operation.messages().all()));
65+
return new Messages(messages);
66+
}
67+
6568
parameters(): ChannelParametersInterface {
6669
return new ChannelParameters(
6770
Object.entries(this._json.parameters || {}).map(([channelParameterName, channelParameter]) => {

src/models/v2/message.ts

+58
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1+
import { Channels } from './channels';
2+
import { Operations } from './operations';
3+
import { Operation } from './operation';
14
import { MessageTraits } from "./message-traits";
25
import { MessageTrait } from "./message-trait";
6+
import { Servers } from './servers';
37
import { Schema } from './schema';
48

9+
import { tilde } from '../../utils';
10+
11+
import type { ChannelsInterface } from "../channels";
12+
import type { ChannelInterface } from "../channel";
513
import type { MessageInterface } from "../message";
614
import type { MessageTraitsInterface } from "../message-traits";
15+
import type { OperationsInterface } from "../operations";
16+
import type { OperationInterface } from "../operation";
17+
import type { ServersInterface } from "../servers";
18+
import type { ServerInterface } from "../server";
719
import type { SchemaInterface } from "../schema";
820

921
export class Message extends MessageTrait implements MessageInterface {
@@ -16,6 +28,52 @@ export class Message extends MessageTrait implements MessageInterface {
1628
return this.createModel(Schema, this._json.payload, { pointer: `${this._meta.pointer}/payload` });
1729
}
1830

31+
servers(): ServersInterface {
32+
const servers: ServerInterface[] = [];
33+
const serversData: any[] = [];
34+
this.channels().forEach(channel => {
35+
channel.servers().forEach(server => {
36+
if (!serversData.includes(server.json())) {
37+
serversData.push(server.json());
38+
servers.push(server);
39+
}
40+
})
41+
});
42+
return new Servers(servers);
43+
}
44+
45+
channels(): ChannelsInterface {
46+
const channels: ChannelInterface[] = [];
47+
const channelsData: any[] = [];
48+
this.operations().all().forEach(operation => {
49+
operation.channels().forEach(channel => {
50+
if (!channelsData.includes(channel.json())) {
51+
channelsData.push(channel.json());
52+
channels.push(channel);
53+
}
54+
})
55+
});
56+
return new Channels(channels);
57+
}
58+
59+
operations(): OperationsInterface {
60+
const operations: OperationInterface[] = [];
61+
Object.entries(this._meta.asyncapi?.parsed.channels || {}).forEach(([channelAddress, channel]: [string, any]) => {
62+
['subscribe', 'publish'].forEach(operationAction => {
63+
const operation = channel[operationAction];
64+
if (operation && (
65+
operation.message === this._json ||
66+
(operation.message.oneOf || []).includes(this._json)
67+
)) {
68+
operations.push(
69+
this.createModel(Operation, operation, { pointer: `/channels/${tilde(channelAddress)}/${operationAction}`, action: operationAction })
70+
);
71+
}
72+
});
73+
});
74+
return new Operations(operations);
75+
}
76+
1977
traits(): MessageTraitsInterface {
2078
return new MessageTraits(
2179
(this._json.traits || []).map((trait: any, index: number) => {

src/models/v2/operation.ts

+36-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,48 @@
1-
import { Message } from "./message";
1+
import { Channels } from "./channels";
2+
import { Channel } from "./channel";
23
import { Messages } from "./messages";
4+
import { Message } from "./message";
35
import { OperationTraits } from "./operation-traits";
46
import { OperationTrait } from "./operation-trait";
7+
import { Servers } from "./servers";
58

9+
import { tilde } from "../../utils";
10+
11+
import type { ChannelsInterface } from "../channels";
12+
import type { ChannelInterface } from "../channel";
613
import type { MessagesInterface } from "../messages";
714
import type { OperationInterface } from "../operation";
815
import type { OperationTraitsInterface } from "../operation-traits";
16+
import type { ServersInterface } from "../servers";
17+
import type { ServerInterface } from "../server";
918

1019
export class Operation extends OperationTrait implements OperationInterface {
20+
servers(): ServersInterface {
21+
const servers: ServerInterface[] = [];
22+
const serversData: any[] = [];
23+
this.channels().forEach(channel => {
24+
channel.servers().forEach(server => {
25+
if (!serversData.includes(server.json())) {
26+
serversData.push(server.json());
27+
servers.push(server);
28+
}
29+
})
30+
});
31+
return new Servers(servers);
32+
}
33+
34+
channels(): ChannelsInterface {
35+
const channels: ChannelInterface[] = [];
36+
Object.entries(this._meta.asyncapi.parsed.channels || {}).forEach(([channelAddress, channel]: [string, any]) => {
37+
if (channel.subscribe === this._json || channel.publish === this._json) {
38+
channels.push(
39+
this.createModel(Channel, channel, { id: channelAddress, address: channelAddress, pointer: `/channels/${tilde(channelAddress)}` })
40+
);
41+
}
42+
});
43+
return new Channels(channels);
44+
}
45+
1146
messages(): MessagesInterface {
1247
let isOneOf = false;
1348
let messages = this._json.message || [];

0 commit comments

Comments
 (0)