-
Notifications
You must be signed in to change notification settings - Fork 135
/
Copy pathAbstractMessaging.ts
96 lines (87 loc) · 2.71 KB
/
AbstractMessaging.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import { AppIdentifier } from '@finos/fdc3-standard';
import { Messaging } from '../Messaging';
import { RegisterableListener } from '../listeners/RegisterableListener';
import {
AgentResponseMessage,
AppRequestMessage,
WebConnectionProtocol6Goodbye,
} from '@finos/fdc3-schema/generated/api/BrowserTypes';
export abstract class AbstractMessaging implements Messaging {
private appIdentifier: AppIdentifier;
abstract createUUID(): string;
abstract post(message: AppRequestMessage | WebConnectionProtocol6Goodbye): Promise<void>;
abstract register(l: RegisterableListener): void;
abstract unregister(id: string): void;
abstract createMeta(): AppRequestMessage['meta'];
constructor(appIdentifier: AppIdentifier) {
this.appIdentifier = appIdentifier;
}
waitFor<X extends AgentResponseMessage>(
filter: (m: X) => boolean,
timeoutMs?: number,
timeoutErrorMessage?: string
): Promise<X> {
const id = this.createUUID();
return new Promise<X>((resolve, reject) => {
let done = false;
let timeout: NodeJS.Timeout | null = null;
const l: RegisterableListener = {
id,
filter: filter,
action: m => {
done = true;
this.unregister(id);
if (timeout) {
clearTimeout(timeout);
}
resolve(m as X);
},
register: async () => {
this.register(l);
},
unsubscribe: async () => {
this.unregister(id);
},
};
this.register(l);
if (timeoutMs) {
timeout = setTimeout(() => {
this.unregister(id);
if (!done) {
console.error(
`waitFor rejecting after ${timeoutMs}ms at ${new Date().toISOString()}${timeoutErrorMessage ? ' with message: ' + timeoutErrorMessage : ''}`
);
reject(new Error(timeoutErrorMessage));
}
}, timeoutMs);
}
});
}
async exchange<X extends AgentResponseMessage>(
message: AppRequestMessage,
expectedTypeName: AgentResponseMessage['type'],
timeoutMs: number,
timeoutErrorMessage?: string
): Promise<X> {
const errorMessage =
timeoutErrorMessage ?? `Timeout waiting for ${expectedTypeName} with requestUuid ${message.meta.requestUuid}`;
const prom = this.waitFor<X>(
m => {
return m.type == expectedTypeName && m.meta.requestUuid == message.meta.requestUuid;
},
timeoutMs,
errorMessage
);
this.post(message);
const out: X = await prom;
if (out?.payload?.error) {
throw new Error(out.payload.error);
} else {
return out;
}
}
getAppIdentifier(): AppIdentifier {
return this.appIdentifier;
}
abstract disconnect(): Promise<void>;
}