Skip to content
This repository was archived by the owner on Jun 18, 2023. It is now read-only.

Commit cc03946

Browse files
timonbackstavshamir
authored andcommitted
feat: Separate server and angular models
Introduce mapper service to map from server to angular model
1 parent 125a9f2 commit cc03946

File tree

10 files changed

+181
-115
lines changed

10 files changed

+181
-115
lines changed

src/app/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { MockServer } from './shared/mock/mock-server';
2020
import { PublisherService } from './shared/publisher.service';
2121
import { FormsModule } from '@angular/forms';
2222
import { JsonComponent } from './shared/components/json/json.component';
23+
import {AsyncApiMapperService} from "./shared/asyncapi-mapper.service";
2324

2425
@NgModule({
2526
declarations: [
@@ -45,6 +46,7 @@ import { JsonComponent } from './shared/components/json/json.component';
4546
],
4647
providers: [
4748
AsyncApiService,
49+
AsyncApiMapperService,
4850
PublisherService,
4951
{
5052
provide: HIGHLIGHT_OPTIONS,

src/app/channels/channel-main/channel-main.component.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ export class ChannelMainComponent implements OnInit {
4040
asyncapi => {
4141
let schemas: Map<string, Schema> = asyncapi.components.schemas;
4242
this.schemaName = this.operation.message.payload.$ref.slice(this.operation.message.payload.$ref.lastIndexOf('/') + 1)
43-
this.schema = schemas[this.schemaName];
43+
this.schema = schemas.get(this.schemaName);
4444

45-
this.defaultExample = new Example(this.schema.example);
46-
this.exampleTextAreaLineCount = this.defaultExample.lineCount;
45+
this.defaultExample = this.schema.example;
46+
this.exampleTextAreaLineCount = this.defaultExample?.lineCount || 0;
4747

4848
this.headersSchemaName = this.operation.message.headers.$ref.slice(this.operation.message.headers.$ref.lastIndexOf('/') + 1)
49-
this.headers = schemas[this.headersSchemaName];
50-
this.headersExample = new Example(this.headers.example);
51-
this.headersTextAreaLineCount = this.headersExample.lineCount;
49+
this.headers = schemas.get(this.headersSchemaName);
50+
this.headersExample = this.headers.example;
51+
this.headersTextAreaLineCount = this.headersExample?.lineCount || 0;
5252
}
5353
);
5454

src/app/schemas/schema/schema.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</span>
1313
<span class="format" *ngIf="property.value.format">({{ property.value.format }})</span>
1414
<div class="description">{{ property.value.description }}</div>
15-
<span class="example" *ngIf="property.value.example">example: {{ property.value.example }}</span>
15+
<span class="example" *ngIf="property.value.example">example: {{ property.value.example.value }}</span>
1616
<mat-select *ngIf="property.value.enum" placeholder="Enum">
1717
<mat-option *ngFor="let enum of property.value.enum" [value]="enum">{{ enum }}</mat-option>
1818
</mat-select>

src/app/servers/servers.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Server } from '../shared/models/server.model';
99
})
1010
export class ServersComponent implements OnInit {
1111

12-
servers: Map<String, Server>;
12+
servers: Map<string, Server>;
1313

1414
constructor(private asyncApiService: AsyncApiService) { }
1515

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { AsyncApi } from './models/asyncapi.model';
2+
import { Server } from './models/server.model';
3+
import {Channel, Message, Operation, OperationType} from './models/channel.model';
4+
import { Schema } from './models/schema.model';
5+
import { Injectable } from '@angular/core';
6+
import {Example} from "./models/example.model";
7+
8+
interface ServerAsyncApiSchema {
9+
description?: string;
10+
type: string;
11+
format: string;
12+
enum: string[];
13+
properties?: Map<string, ServerAsyncApiSchema>;
14+
example?: {
15+
[key: string]: object;
16+
};
17+
required?: string[];
18+
}
19+
20+
interface ServerAsyncApiMessage {
21+
name: string;
22+
title: string;
23+
description?: string;
24+
payload: { $ref: string };
25+
headers: { $ref: string };
26+
}
27+
28+
interface ServerAsyncApiInfo {
29+
title: string;
30+
version: string;
31+
description?: string;
32+
}
33+
34+
export interface ServerAsyncApi {
35+
asyncapi: string;
36+
info: ServerAsyncApiInfo;
37+
servers: {
38+
[key: string]: {
39+
url: string;
40+
protocol: string;
41+
};
42+
};
43+
channels: {
44+
[key: string]: {
45+
description?: string;
46+
subscribe?: {
47+
message: ServerAsyncApiMessage | { oneOf: ServerAsyncApiMessage[] };
48+
bindings?: any;
49+
};
50+
publish?: {
51+
message: ServerAsyncApiMessage | { oneOf: ServerAsyncApiMessage[] };
52+
bindings?: any;
53+
};
54+
};
55+
};
56+
components: {
57+
schemas: Map<string, ServerAsyncApiSchema>;
58+
};
59+
}
60+
61+
@Injectable()
62+
export class AsyncApiMapperService {
63+
64+
constructor() {
65+
}
66+
67+
public toAsyncApiMap(serverAsyncApi: Map<string, ServerAsyncApi>): Map<string, AsyncApi> {
68+
const docs = new Map<string, AsyncApi>();
69+
Object.entries(serverAsyncApi).forEach(([docName, doc]) => docs.set(docName, this.toAsyncApi(doc)));
70+
return docs;
71+
}
72+
73+
toAsyncApi(item: ServerAsyncApi): AsyncApi {
74+
return {
75+
info: item.info,
76+
servers: this.mapServers(item.servers),
77+
channels: this.mapChannels(item.channels),
78+
components: {
79+
schemas: this.mapSchemas(item.components.schemas)
80+
}
81+
};
82+
}
83+
84+
private mapServers(servers: ServerAsyncApi["servers"]): Map<string, Server> {
85+
const s = new Map<string, Server>();
86+
Object.entries(servers).forEach(([k, v]) => s.set(k, v));
87+
return s;
88+
}
89+
90+
private mapChannels(channels: ServerAsyncApi["channels"]): Channel[] {
91+
const s = new Array<Channel>();
92+
Object.entries(channels).forEach(([k, v]) => {
93+
const subscriberChannels = this.mapChannel(k, v.description, v.subscribe, "subscribe")
94+
subscriberChannels.forEach(channel => s.push(channel))
95+
96+
const publisherChannels = this.mapChannel(k, v.description, v.publish, "publish")
97+
publisherChannels.forEach(channel => s.push(channel))
98+
});
99+
return s;
100+
}
101+
102+
private mapChannel(
103+
topicName: string,
104+
description: ServerAsyncApi["channels"][""]["description"],
105+
operation: ServerAsyncApi["channels"][""]["subscribe"] | ServerAsyncApi["channels"][""]["publish"],
106+
operationType: OperationType): Channel[]
107+
{
108+
if(operation !== undefined) {
109+
let messages: Message[] = 'oneOf' in operation.message ? operation.message.oneOf : [operation.message];
110+
111+
return messages.map(message => {
112+
return {
113+
name: topicName,
114+
description: description,
115+
operation: this.mapOperation(operationType, message, operation.bindings)
116+
}
117+
})
118+
}
119+
return [];
120+
}
121+
122+
private mapOperation(operationType: OperationType, message: Message, bindings?: any): Operation {
123+
return {
124+
protocol: this.getProtocol(bindings),
125+
operation: operationType,
126+
message: message,
127+
bindings: bindings
128+
}
129+
}
130+
131+
private getProtocol(bindings?: any): string {
132+
return Object.keys(bindings)[0];
133+
}
134+
135+
private mapSchemas(schemas: Map<string, ServerAsyncApiSchema>): Map<string, Schema> {
136+
const s = new Map<string, Schema>();
137+
Object.entries(schemas).forEach(([k, v]) => s.set(k, this.mapSchema(v)));
138+
return s;
139+
}
140+
141+
private mapSchema(schema: ServerAsyncApiSchema): Schema {
142+
const properties = schema.properties !== undefined ? this.mapSchemas(schema.properties) : undefined
143+
const example = schema.example !== undefined ? new Example(schema.example) : undefined
144+
return {
145+
description: schema.description,
146+
type: schema.type,
147+
format: schema.format,
148+
enum: schema.enum,
149+
properties: properties,
150+
required: schema.required,
151+
example: example,
152+
}
153+
}
154+
}

src/app/shared/asyncapi.service.ts

Lines changed: 3 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,17 @@
11
import { AsyncApi } from './models/asyncapi.model';
2-
import { Server } from './models/server.model';
3-
import { Channel, Message, Operation } from './models/channel.model';
4-
import { Schema } from './models/schema.model';
52
import { HttpClient } from '@angular/common/http';
63
import { Injectable } from '@angular/core';
74
import { Observable, of } from 'rxjs';
85
import { map } from 'rxjs/operators';
9-
import { Info } from './models/info.model';
106
import { Endpoints } from './endpoints';
11-
12-
interface ServerAsyncApi {
13-
asyncapi: string;
14-
info: Info;
15-
servers: {
16-
[key: string]: {
17-
url: string;
18-
protocol: string;
19-
};
20-
};
21-
channels: {
22-
[key: string]: {
23-
description?: string;
24-
subscribe?: {
25-
message: Message | { oneOf: Message[] };
26-
bindings?: any;
27-
};
28-
publish?: {
29-
message: Message | { oneOf: Message[] };
30-
bindings?: any;
31-
};
32-
};
33-
};
34-
components: {
35-
schemas: Map<string, Schema>;
36-
};
37-
}
7+
import {AsyncApiMapperService, ServerAsyncApi} from "./asyncapi-mapper.service";
388

399
@Injectable()
4010
export class AsyncApiService {
4111

4212
private docs: AsyncApi;
4313

44-
constructor(private http: HttpClient) {
14+
constructor(private http: HttpClient, private asyncApiMapperService: AsyncApiMapperService) {
4515
}
4616

4717
public getAsyncApis(): Observable<AsyncApi> {
@@ -50,70 +20,7 @@ export class AsyncApiService {
5020
}
5121

5222
return this.http.get<ServerAsyncApi>(Endpoints.docs).pipe(map(item => {
53-
this.docs = this.toAsyncApi(item);
54-
return this.docs;
23+
return this.asyncApiMapperService.toAsyncApi(item);
5524
}));
5625
}
57-
58-
private toAsyncApi(item: ServerAsyncApi): AsyncApi {
59-
return {
60-
info: item.info,
61-
servers: this.mapServers(item.servers),
62-
channels: this.mapChannels(item.channels),
63-
components: {
64-
schemas: item.components.schemas
65-
}
66-
};
67-
}
68-
69-
private mapServers(servers: ServerAsyncApi["servers"]): Map<string, Server> {
70-
const s = new Map<string, Server>();
71-
Object.entries(servers).forEach(([k, v]) => s.set(k, v));
72-
return s;
73-
}
74-
75-
private mapChannels(channels: ServerAsyncApi["channels"]): Channel[] {
76-
const s = new Array<Channel>();
77-
Object.entries(channels).forEach(([k, v]) => {
78-
const subscriberChannels = this.mapChannel(k, v.description, v.subscribe, "subscribe")
79-
subscriberChannels.forEach(channel => s.push(channel))
80-
81-
const publisherChannels = this.mapChannel(k, v.description, v.publish, "publish")
82-
publisherChannels.forEach(channel => s.push(channel))
83-
});
84-
return s;
85-
}
86-
87-
private mapChannel(
88-
topicName: string,
89-
description: ServerAsyncApi["channels"][""]["description"],
90-
operation: ServerAsyncApi["channels"][""]["subscribe"] | ServerAsyncApi["channels"][""]["publish"],
91-
operationName: string): Channel[] {
92-
if (operation !== undefined) {
93-
let messages: Message[] = 'oneOf' in operation.message ? operation.message.oneOf : [operation.message];
94-
95-
return messages.map(message => {
96-
return {
97-
name: topicName,
98-
description: description,
99-
operation: this.mapOperation(operationName, message, operation.bindings)
100-
}
101-
})
102-
}
103-
return [];
104-
}
105-
106-
private mapOperation(operationName: string, message: Message, bindings?: any): Operation {
107-
return {
108-
protocol: this.getProtocol(bindings),
109-
operation: operationName,
110-
message: message,
111-
bindings: bindings
112-
}
113-
}
114-
115-
private getProtocol(bindings?: any): string {
116-
return Object.keys(bindings)[0];
117-
}
118-
11926
}

src/app/shared/models/channel.model.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ export interface Channel {
44
operation: Operation;
55
}
66

7+
export type OperationType = "publish" | "subscribe";
78
export interface Operation {
89
message: Message;
910
bindings?: { [type: string]: any };
1011
protocol: string;
11-
operation: string;
12+
operation: OperationType;
1213
}
1314

1415
export interface Message {

src/app/shared/models/info.model.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export interface Info {
2-
title: String;
3-
version: String;
4-
description?: String;
5-
}
2+
title: string;
3+
version: string;
4+
description?: string;
5+
}

src/app/shared/models/schema.model.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { Example } from './example.model';
22

33
export interface Schema {
4-
description?: String;
5-
type: String;
4+
description?: string;
5+
type: string;
6+
format?: string;
7+
enum?: string[];
68
properties?: Map<string, Schema>;
7-
example: Example;
9+
example?: Example;
810
required?: string[];
911
}

src/app/shared/models/server.model.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export interface Server {
2-
url: String;
3-
protocol: String;
4-
}
2+
url: string;
3+
protocol: string;
4+
}

0 commit comments

Comments
 (0)