diff options
Diffstat (limited to 'extension/src/util')
-rw-r--r-- | extension/src/util/messenger.ts | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/extension/src/util/messenger.ts b/extension/src/util/messenger.ts new file mode 100644 index 00000000..6f8bb29d --- /dev/null +++ b/extension/src/util/messenger.ts @@ -0,0 +1,108 @@ +console.log("Websocket import"); +const WebSocket = require("ws"); + +export abstract class Messenger { + abstract send(messageType: string, data: object): void; + + abstract onMessageType( + messageType: string, + callback: (data: object) => void + ): void; + + abstract onMessage(callback: (messageType: string, data: any) => void): void; + + abstract onOpen(callback: () => void): void; + + abstract onClose(callback: () => void): void; + + abstract sendAndReceive(messageType: string, data: any): Promise<any>; +} + +export class WebsocketMessenger extends Messenger { + websocket: WebSocket; + private onMessageListeners: { + [messageType: string]: ((data: object) => void)[]; + } = {}; + private onOpenListeners: (() => void)[] = []; + private onCloseListeners: (() => void)[] = []; + private serverUrl: string; + + _newWebsocket(): WebSocket { + // // Dynamic import, because WebSocket is builtin with browser, but not with node. And can't use require in browser. + // if (typeof process === "object") { + // console.log("Using node"); + // // process is only available in Node + // var WebSocket = require("ws"); + // } + + const newWebsocket = new WebSocket(this.serverUrl); + for (const listener of this.onOpenListeners) { + this.onOpen(listener); + } + for (const listener of this.onCloseListeners) { + this.onClose(listener); + } + for (const messageType in this.onMessageListeners) { + for (const listener of this.onMessageListeners[messageType]) { + this.onMessageType(messageType, listener); + } + } + return newWebsocket; + } + + constructor(serverUrl: string) { + super(); + this.serverUrl = serverUrl; + this.websocket = this._newWebsocket(); + } + + send(messageType: string, data: object) { + const payload = JSON.stringify({ messageType, data }); + if (this.websocket.readyState === this.websocket.OPEN) { + this.websocket.send(payload); + } else { + if (this.websocket.readyState !== this.websocket.CONNECTING) { + this.websocket = this._newWebsocket(); + } + this.websocket.addEventListener("open", () => { + this.websocket.send(payload); + }); + } + } + + sendAndReceive(messageType: string, data: any): Promise<any> { + return new Promise((resolve, reject) => { + const eventListener = (data: any) => { + // THIS ISN"T GETTING CALLED + resolve(data); + this.websocket.removeEventListener("message", eventListener); + }; + this.onMessageType(messageType, eventListener); + this.send(messageType, data); + }); + } + + onMessageType(messageType: string, callback: (data: any) => void): void { + this.websocket.addEventListener("message", (event: any) => { + const msg = JSON.parse(event.data); + if (msg.messageType === messageType) { + callback(msg.data); + } + }); + } + + onMessage(callback: (messageType: string, data: any) => void): void { + this.websocket.addEventListener("message", (event) => { + const msg = JSON.parse(event.data); + callback(msg.messageType, msg.data); + }); + } + + onOpen(callback: () => void): void { + this.websocket.addEventListener("open", callback); + } + + onClose(callback: () => void): void { + this.websocket.addEventListener("close", callback); + } +} |