helene
Version:
Real-time Web Apps for Node.js
137 lines • 4.58 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientSocket = void 0;
const utils_1 = require("../utils");
const eventemitter2_1 = require("eventemitter2");
const defer_1 = __importDefault(require("lodash/defer"));
const socket_io_client_1 = require("socket.io-client");
const client_1 = require("./client");
class ClientSocket extends eventemitter2_1.EventEmitter2 {
client;
socket;
protocol;
uri;
stopped = false;
connecting = false;
options = {
path: utils_1.HELENE_WS_PATH,
};
baseAttemptDelay = 1000;
get ready() {
return this.socket?.connected ?? false;
}
constructor(client, options = {}) {
super();
this.client = client;
Object.assign(this.options, options ?? {});
this.protocol = this.client.options.secure ? 'https://' : 'http://';
if (this.client.options.port) {
this.uri = `${this.protocol}${this.client.options.host}:${this.client.options.port}`;
}
else {
this.uri = `${this.protocol}${this.client.options.host}`;
}
}
connect() {
if (this.ready) {
console.warn('Helene: Already Connected');
return;
}
this.stopped = false;
this.connecting = true;
this.client.emit(utils_1.ClientEvents.CONNECTING);
this.socket = (0, socket_io_client_1.io)(this.uri, {
path: this.options.path,
query: {
uuid: this.client.uuid,
},
reconnection: true,
reconnectionAttempts: 10,
reconnectionDelay: 500,
reconnectionDelayMax: 10000,
randomizationFactor: 0.5,
});
this.socket.on('connect', () => {
this.handleOpen();
});
this.socket.on('reconnect', () => {
this.handleOpen();
});
this.socket.on('disconnect', reason => {
this.client.initialized = false;
this.client.initializing = false;
this.client.emit(utils_1.ClientEvents.WEBSOCKET_CLOSED);
if (this.stopped) {
this.socket = undefined;
return;
}
});
this.socket.on('error', this.handleError.bind(this));
this.socket.on('message', this.handleMessage.bind(this));
}
async close() {
this.stopped = true;
this.connecting = false;
(0, defer_1.default)(() => {
if (!this.socket) {
this.client.emit(utils_1.ClientEvents.WEBSOCKET_CLOSED);
return;
}
this.socket.close();
this.socket = undefined;
});
await this.client.waitFor(utils_1.ClientEvents.WEBSOCKET_CLOSED);
}
send(payload) {
if (!this.ready) {
console.warn('Helene: Not Ready');
console.log({
ready: this.ready,
connecting: this.connecting,
payload,
uuid: this.client.uuid,
options: this.client.options,
});
console.trace();
return;
}
this.socket.send(payload);
}
sendSetup() {
const setup = {
type: utils_1.PayloadType.SETUP,
uuid: this.client.uuid,
};
this.send(utils_1.Presentation.encode(setup));
this.client.emit(utils_1.ClientEvents.OUTBOUND_MESSAGE, setup);
}
handleOpen() {
if (!this.socket)
return;
this.sendSetup();
this.client.emit(utils_1.ClientEvents.WEBSOCKET_CONNECTED);
this.connecting = false;
this.client.initialize();
}
async handleMessage(data) {
const payload = utils_1.Presentation.decode(data);
if (!payload)
return;
if (payload.type === utils_1.PayloadType.HEARTBEAT && client_1.Client.ENABLE_HEARTBEAT) {
this.send(utils_1.Presentation.encode({ type: utils_1.PayloadType.HEARTBEAT }));
this.client.emit(utils_1.HeleneEvents.HEARTBEAT);
return;
}
this.client.payloadRouter(payload);
}
handleError = error => {
this.connecting = false;
console.error(error);
this.client.emit(utils_1.ClientEvents.ERROR, error);
};
}
exports.ClientSocket = ClientSocket;
//# sourceMappingURL=client-socket.js.map