Path: blob/1.0-develop/resources/scripts/plugins/Websocket.ts
7458 views
import Sockette from 'sockette';1import { EventEmitter } from 'events';23export class Websocket extends EventEmitter {4// Timer instance for this socket.5private timer: any = null;67// The backoff for the timer, in milliseconds.8private backoff = 5000;910// The socket instance being tracked.11private socket: Sockette | null = null;1213// The URL being connected to for the socket.14private url: string | null = null;1516// The authentication token passed along with every request to the Daemon.17// By default this token expires every 15 minutes and must therefore be18// refreshed at a pretty continuous interval. The socket server will respond19// with "token expiring" and "token expired" events when approaching 3 minutes20// and 0 minutes to expiry.21private token = '';2223// Connects to the websocket instance and sets the token for the initial request.24connect(url: string): this {25this.url = url;2627this.socket = new Sockette(`${this.url}`, {28onmessage: (e) => {29try {30const { event, args } = JSON.parse(e.data);31args ? this.emit(event, ...args) : this.emit(event);32} catch (ex) {33console.warn('Failed to parse incoming websocket message.', ex);34}35},36onopen: () => {37// Clear the timers, we managed to connect just fine.38this.timer && clearTimeout(this.timer);39this.backoff = 5000;4041this.emit('SOCKET_OPEN');42this.authenticate();43},44onreconnect: () => {45this.emit('SOCKET_RECONNECT');46this.authenticate();47},48onclose: () => this.emit('SOCKET_CLOSE'),49onerror: (error) => this.emit('SOCKET_ERROR', error),50});5152this.timer = setTimeout(() => {53this.backoff = this.backoff + 2500 >= 20000 ? 20000 : this.backoff + 2500;54this.socket && this.socket.close();55clearTimeout(this.timer);5657// Re-attempt connecting to the socket.58this.connect(url);59}, this.backoff);6061return this;62}6364// Sets the authentication token to use when sending commands back and forth65// between the websocket instance.66setToken(token: string, isUpdate = false): this {67this.token = token;6869if (isUpdate) {70this.authenticate();71}7273return this;74}7576authenticate() {77if (this.url && this.token) {78this.send('auth', this.token);79}80}8182close(code?: number, reason?: string) {83this.url = null;84this.token = '';85this.socket && this.socket.close(code, reason);86}8788open() {89this.socket && this.socket.open();90}9192reconnect() {93this.socket && this.socket.reconnect();94}9596send(event: string, payload?: string | string[]) {97this.socket &&98this.socket.send(99JSON.stringify({100event,101args: Array.isArray(payload) ? payload : [payload],102})103);104}105}106107108