Path: blob/1.0-develop/resources/scripts/plugins/Websocket.ts
10258 views
import Sockette from 'sockette';1import { EventEmitter } from 'events';23export class Websocket extends EventEmitter {4// The socket instance being tracked.5private socket: Sockette | null = null;67// The URL being connected to for the socket.8private url: string | null = null;910// The authentication token passed along with every request to the Daemon.11// By default this token expires every 15 minutes and must therefore be12// refreshed at a pretty continuous interval. The socket server will respond13// with "token expiring" and "token expired" events when approaching 3 minutes14// and 0 minutes to expiry.15private token = '';1617// Connects to the websocket instance and sets the token for the initial request.18connect(url: string): this {19this.url = url;2021this.socket = new Sockette(`${this.url}`, {22timeout: 1000,23maxAttempts: 20,24onmessage: (e) => {25try {26const { event, args } = JSON.parse(e.data);27args ? this.emit(event, ...args) : this.emit(event);28} catch (ex) {29console.warn('Failed to parse incoming websocket message.', ex);30}31},32onopen: () => {33this.emit('SOCKET_OPEN');34this.authenticate();35},36onreconnect: (evt) => {37// We return code 4409 from Wings when a server is suspended. We've38// gone ahead and reserved 4400 as well here for future expansion without39// having to loop back around.40//41// If either of those codes is returned go ahead and abort here. Unfortunately42// the underlying sockette logic always calls reconnect for any code that isn't43// 1000/1001/1003, which is painful but we can just stop the flow here.44// @ts-expect-error code is actually present here.45if (evt.code === 4409 || evt.code === 4400) {46this.close(1000);47} else {48this.emit('SOCKET_RECONNECT');49}50},51onclose: () => this.emit('SOCKET_CLOSE'),52onerror: (error) => this.emit('SOCKET_ERROR', error),53onmaximum: () => this.emit('SOCKET_CONNECT_ERROR'),54});5556return this;57}5859// Sets the authentication token to use when sending commands back and forth60// between the websocket instance.61setToken(token: string, isUpdate = false): this {62this.token = token;6364if (isUpdate) {65this.authenticate();66}6768return this;69}7071authenticate() {72if (this.url && this.token) {73this.send('auth', this.token);74}75}7677close(code?: number, reason?: string) {78this.url = null;79this.token = '';80this.socket?.close(code, reason);81}8283open() {84this.socket?.open();85}8687reconnect() {88this.socket?.reconnect();89}9091send(event: string, payload?: string | string[]) {92this.socket?.json({ event, args: Array.isArray(payload) ? payload : [payload] });93}94}959697