Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@aurox/persistent-websocket-connection

Package Overview
Dependencies
Maintainers
5
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@aurox/persistent-websocket-connection - npm Package Compare versions

Comparing version 0.5.0 to 0.6.0

13

dist/constants.js

@@ -1,9 +0,6 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_KEEP_ALIVE_INTERVAL = exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_TOLERANCE_TIMEOUT = exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_INTERVAL = exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_CONNECTION_CHECK_INTERVAL = exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT = void 0;
exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT = 2000;
exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_CONNECTION_CHECK_INTERVAL = 500;
exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_INTERVAL = 5000;
exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_TOLERANCE_TIMEOUT = 2000;
exports.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_KEEP_ALIVE_INTERVAL = 5000;
export const DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT = 2000;
export const DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_CONNECTION_CHECK_INTERVAL = 500;
export const DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_INTERVAL = 5000;
export const DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_TOLERANCE_TIMEOUT = 2000;
export const DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_KEEP_ALIVE_INTERVAL = 5000;
//# sourceMappingURL=constants.js.map

@@ -1,2 +0,2 @@

import { PersistentWebsocketConnectionOptions } from './types';
import { PersistentWebsocketConnectionOptions } from './types.js';
type DeepRequired<T> = T extends (...args: any[]) => any ? T : T extends object ? {

@@ -3,0 +3,0 @@ [P in keyof T]-?: DeepRequired<T[P]>;

@@ -1,5 +0,2 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOptionsWithDefaults = void 0;
const constants_1 = require("./constants");
import { DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT, DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_CONNECTION_CHECK_INTERVAL, DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_INTERVAL, DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_TOLERANCE_TIMEOUT, DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_KEEP_ALIVE_INTERVAL, } from './constants.js';
function defaultDoPing(send) {

@@ -20,6 +17,6 @@ send('ping');

}
function getOptionsWithDefaults(options) {
export function getOptionsWithDefaults(options) {
return {
url: options.url,
reconnectTimeout: options.reconnectTimeout || constants_1.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT,
reconnectTimeout: options.reconnectTimeout || DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT,
reconnectBackoff: {

@@ -29,9 +26,9 @@ enabled: (options.reconnectBackoff && options.reconnectBackoff.enabled) || false,

backoffIncrement: (options.reconnectBackoff && options.reconnectBackoff.backoffIncrement) ||
constants_1.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT,
DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT,
maxBackedOffTimeout: (options.reconnectBackoff && options.reconnectBackoff.maxBackedOffTimeout) ||
constants_1.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT * 10,
DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT * 10,
backoffIncrementResetTimeout: (options.reconnectBackoff && options.reconnectBackoff.backoffIncrementResetTimeout) ||
constants_1.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT * 10,
DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT * 10,
},
connectionCheckInterval: options.connectionCheckInterval || constants_1.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_CONNECTION_CHECK_INTERVAL,
connectionCheckInterval: options.connectionCheckInterval || DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_CONNECTION_CHECK_INTERVAL,
pingPong: {

@@ -43,4 +40,4 @@ enabled: (options.pingPong && options.pingPong.enabled) || false,

forwardHeartbeatMessage: (options.pingPong && options.pingPong.forwardHeartbeatMessage) || false,
interval: (options.pingPong && options.pingPong.interval) || constants_1.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_INTERVAL,
toleranceTimeout: (options.pingPong && options.pingPong.toleranceTimeout) || constants_1.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_TOLERANCE_TIMEOUT,
interval: (options.pingPong && options.pingPong.interval) || DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_INTERVAL,
toleranceTimeout: (options.pingPong && options.pingPong.toleranceTimeout) || DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_PING_PONG_TOLERANCE_TIMEOUT,
heartbeatDebounce: (options.pingPong && options.pingPong.heartbeatDebounce) || null,

@@ -53,3 +50,3 @@ doPing: (options.pingPong && options.pingPong.doPing) || defaultDoPing,

enabled: (options.keepAlive && options.keepAlive.enabled) || false,
interval: (options.keepAlive && options.keepAlive.interval) || constants_1.DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_KEEP_ALIVE_INTERVAL,
interval: (options.keepAlive && options.keepAlive.interval) || DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_KEEP_ALIVE_INTERVAL,
doKeepAlive: (options.keepAlive && options.keepAlive.doKeepAlive) || defaultDoKeepAlive,

@@ -70,3 +67,2 @@ },

}
exports.getOptionsWithDefaults = getOptionsWithDefaults;
//# sourceMappingURL=defaults.js.map

@@ -1,5 +0,5 @@

export * from './constants';
export * from './types';
import { PersistentWebsocketConnection, PersistentWebsocketConnectionEvents } from './PersistentWebsocketConnection';
export * from './constants.js';
export * from './types.js';
import { PersistentWebsocketConnection, PersistentWebsocketConnectionEvents } from './PersistentWebsocketConnection.js';
export { PersistentWebsocketConnectionEvents };
export default PersistentWebsocketConnection;

@@ -1,8 +0,5 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./constants"), exports);
tslib_1.__exportStar(require("./types"), exports);
const PersistentWebsocketConnection_1 = require("./PersistentWebsocketConnection");
exports.default = PersistentWebsocketConnection_1.PersistentWebsocketConnection;
export * from './constants.js';
export * from './types.js';
import { PersistentWebsocketConnection } from './PersistentWebsocketConnection.js';
export default PersistentWebsocketConnection;
//# sourceMappingURL=index.js.map
import { TypedEmitter } from 'tiny-typed-emitter';
import { PersistentWebsocketConnectionOptions, ConnectionLostReason } from './types';
import { PersistentWebsocketConnectionOptions, ConnectionLostReason } from './types.js';
export interface PersistentWebsocketConnectionEvents {

@@ -4,0 +4,0 @@ 'connecting': () => void;

@@ -1,84 +0,126 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PersistentWebsocketConnection = void 0;
const tslib_1 = require("tslib");
const isomorphic_ws_1 = tslib_1.__importDefault(require("isomorphic-ws"));
const tiny_typed_emitter_1 = require("tiny-typed-emitter");
const defaults_1 = require("./defaults");
class PersistentWebsocketConnection extends tiny_typed_emitter_1.TypedEmitter {
import WebSocket from 'isomorphic-ws';
import { TypedEmitter } from 'tiny-typed-emitter';
import { getOptionsWithDefaults } from './defaults.js';
export class PersistentWebsocketConnection extends TypedEmitter {
connection = null;
logger;
url;
reconnectTimeout;
connectionCheckInterval;
agent;
pingPongOptions;
keepAliveOptions;
backoffOptions;
attemptingToEstablishConnection = false;
closedExternally = false;
closedDuoToPongOrHeartbeatTimeout = false;
initialConnectionEstablished = false;
reconnecting = false;
reconnectingForcefully = false;
reconnectingTries = 0;
reconnectBackoffIncrement = 0;
onInitialConnectionEstablished;
onReconnect;
onData;
onReconnecting;
onConnecting;
onConnectionLost;
queuedDataToSendOnReconnect = [];
reconnectTimer = null;
reconnectDelayTimer = null;
reconnectBackoffIncrementResetTimer = null;
checkConnectionTimer = null;
pingPongTimer = null;
pingPongToleranceTimer = null;
keepAliveTimer = null;
get isConnected() {
var _a, _b;
return ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.readyState) === ((_b = this.connection) === null || _b === void 0 ? void 0 : _b.OPEN);
return this.connection?.readyState === this.connection?.OPEN;
}
get isConnecting() {
var _a, _b;
return ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.readyState) === ((_b = this.connection) === null || _b === void 0 ? void 0 : _b.CONNECTING);
return this.connection?.readyState === this.connection?.CONNECTING;
}
constructor(options) {
super();
this.connection = null;
this.attemptingToEstablishConnection = false;
this.closedExternally = false;
this.closedDuoToPongOrHeartbeatTimeout = false;
this.initialConnectionEstablished = false;
this.reconnecting = false;
this.reconnectingForcefully = false;
this.reconnectingTries = 0;
const optionsWithDefaults = getOptionsWithDefaults(options);
this.logger = optionsWithDefaults.logger;
this.url = optionsWithDefaults.url;
this.reconnectTimeout = optionsWithDefaults.reconnectTimeout;
this.connectionCheckInterval = optionsWithDefaults.connectionCheckInterval;
this.agent = optionsWithDefaults.agent;
this.pingPongOptions = optionsWithDefaults.pingPong;
this.keepAliveOptions = optionsWithDefaults.keepAlive;
this.backoffOptions = optionsWithDefaults.reconnectBackoff;
this.onInitialConnectionEstablished = optionsWithDefaults.onInitialConnectionEstablished;
this.onReconnect = optionsWithDefaults.onReconnect;
this.onData = optionsWithDefaults.onData;
this.onReconnecting = optionsWithDefaults.onReconnecting;
this.onConnecting = optionsWithDefaults.onConnecting;
this.onConnectionLost = optionsWithDefaults.onConnectionLost;
this.connect();
this.checkConnection();
}
send = (data) => {
if (this.isConnected) {
this.connection?.send(data);
}
};
sendOrQueue = (data) => {
if (this.isConnected) {
this.connection?.send(data);
}
else {
this.queuedDataToSendOnReconnect.push(data);
}
};
stop = () => {
if (this.closedExternally) {
return;
}
clearTimeout(this.reconnectTimer);
clearTimeout(this.reconnectDelayTimer);
clearTimeout(this.reconnectBackoffIncrementResetTimer);
clearTimeout(this.checkConnectionTimer);
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
clearTimeout(this.keepAliveTimer);
this.closedExternally = true;
this.closeConnection();
this.logger.debug(`Connection to ${this.url} closed gracefully.`);
this.emit('stopped');
};
forceReconnect = () => {
if (this.closedExternally) {
return;
}
this.logger.debug(`Attempting to forcefully reconnect to ${this.url}.`);
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
clearTimeout(this.keepAliveTimer);
// When forcefully reconnecting, we must reset the backoff state since it implies an urgent requirement
this.resetBackoffIncrement();
this.reconnectingForcefully = true;
this.closeConnection();
};
resetBackoffIncrement = () => {
this.reconnectBackoffIncrement = 0;
this.queuedDataToSendOnReconnect = [];
this.reconnectTimer = null;
this.reconnectDelayTimer = null;
this.reconnectBackoffIncrementResetTimer = null;
this.checkConnectionTimer = null;
this.pingPongTimer = null;
this.pingPongToleranceTimer = null;
this.keepAliveTimer = null;
this.send = (data) => {
var _a;
if (this.isConnected) {
(_a = this.connection) === null || _a === void 0 ? void 0 : _a.send(data);
}
};
this.sendOrQueue = (data) => {
var _a;
if (this.isConnected) {
(_a = this.connection) === null || _a === void 0 ? void 0 : _a.send(data);
}
else {
this.queuedDataToSendOnReconnect.push(data);
}
};
this.stop = () => {
if (this.closedExternally) {
return;
}
clearTimeout(this.reconnectTimer);
clearTimeout(this.reconnectDelayTimer);
clearTimeout(this.reconnectBackoffIncrementResetTimer);
clearTimeout(this.checkConnectionTimer);
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
clearTimeout(this.keepAliveTimer);
this.closedExternally = true;
this.closeConnection();
this.logger.debug(`Connection to ${this.url} closed gracefully.`);
this.emit('stopped');
};
this.forceReconnect = () => {
if (this.closedExternally) {
return;
}
this.logger.debug(`Attempting to forcefully reconnect to ${this.url}.`);
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
clearTimeout(this.keepAliveTimer);
// When forcefully reconnecting, we must reset the backoff state since it implies an urgent requirement
this.resetBackoffIncrement();
this.reconnectingForcefully = true;
this.closeConnection();
};
this.resetBackoffIncrement = () => {
this.reconnectBackoffIncrement = 0;
};
this.reconnect = () => {
};
reconnect = () => {
if (this.closedExternally || this.isConnected) {
this.reconnectingTries = 0;
this.reconnecting = false;
return;
}
this.reconnecting = true;
this.reconnectingTries += 1;
this.onReconnecting(this.reconnectingTries);
this.emit('reconnecting', this.reconnectingTries);
if (!this.attemptingToEstablishConnection) {
this.logger.debug(`Attempting to reconnect to ${this.url}.`);
this.connect();
}
else {
this.logger.debug(`Attempted to reconnect to ${this.url}, but the previous attempt is still unresolved.`);
}
clearTimeout(this.reconnectTimer);
this.reconnectTimer = setTimeout(() => {
if (this.closedExternally || this.isConnected) {

@@ -89,256 +131,217 @@ this.reconnectingTries = 0;

}
this.reconnecting = true;
this.reconnectingTries += 1;
this.onReconnecting(this.reconnectingTries);
this.emit('reconnecting', this.reconnectingTries);
if (!this.attemptingToEstablishConnection) {
this.logger.debug(`Attempting to reconnect to ${this.url}.`);
this.connect();
this.logger.debug(`Reconnection to ${this.url} timed out after ${this.reconnectTimeout}ms, retrying...`);
this.reconnectWithDelay();
}, this.reconnectTimeout);
};
reconnectWithDelay = () => {
clearTimeout(this.reconnectTimer);
clearTimeout(this.reconnectDelayTimer);
clearTimeout(this.reconnectBackoffIncrementResetTimer);
if (this.closedExternally || this.isConnected) {
this.reconnectingTries = 0;
this.reconnecting = false;
return;
}
this.reconnecting = true;
let delay = 0;
if (this.backoffOptions.enabled) {
this.reconnectBackoffIncrement += 1;
const incrementDiff = this.reconnectBackoffIncrement - this.backoffOptions.backoffOffset;
const increment = incrementDiff <= 0 ? 0 : Math.round(incrementDiff);
delay = this.backoffOptions.backoffIncrement * increment;
if (delay > this.backoffOptions.maxBackedOffTimeout) {
delay = this.backoffOptions.maxBackedOffTimeout;
}
else {
this.logger.debug(`Attempted to reconnect to ${this.url}, but the previous attempt is still unresolved.`);
}
clearTimeout(this.reconnectTimer);
this.reconnectTimer = setTimeout(() => {
if (this.closedExternally || this.isConnected) {
this.reconnectingTries = 0;
this.reconnecting = false;
return;
}
this.logger.debug(`Reconnection to ${this.url} timed out after ${this.reconnectTimeout}ms, retrying...`);
this.reconnectWithDelay();
}, this.reconnectTimeout);
};
this.reconnectWithDelay = () => {
clearTimeout(this.reconnectTimer);
clearTimeout(this.reconnectDelayTimer);
clearTimeout(this.reconnectBackoffIncrementResetTimer);
if (this.closedExternally || this.isConnected) {
this.reconnectingTries = 0;
this.reconnecting = false;
if (delay > 0) {
this.logger.debug(`Will try to reconnect to ${this.url} after ${delay}ms.`);
clearTimeout(this.reconnectDelayTimer);
this.reconnectDelayTimer = setTimeout(this.reconnect, delay);
return;
}
this.reconnecting = true;
let delay = 0;
if (this.backoffOptions.enabled) {
this.reconnectBackoffIncrement += 1;
const incrementDiff = this.reconnectBackoffIncrement - this.backoffOptions.backoffOffset;
const increment = incrementDiff <= 0 ? 0 : Math.round(incrementDiff);
delay = this.backoffOptions.backoffIncrement * increment;
if (delay > this.backoffOptions.maxBackedOffTimeout) {
delay = this.backoffOptions.maxBackedOffTimeout;
}
this.reconnect();
};
closeConnection = () => {
try {
this.connection?.close();
}
catch {
// Ignore errors here, failure to close is not very problematic
}
};
handleConnectionLost = (reason, error) => {
let preventDefault = false;
this.onConnectionLost({
reason,
error,
preventDefault: () => {
preventDefault = true;
},
});
if (!preventDefault) {
this.emit('connection-lost', reason, error);
this.reconnectWithDelay();
}
};
handleNoPong = () => {
if (this.pingPongOptions.heartbeatOnly) {
const debounce = this.pingPongOptions.heartbeatDebounce ? this.pingPongOptions.heartbeatDebounce : 0;
const tolerance = this.pingPongOptions.toleranceTimeout + debounce;
this.logger.error(`Connection to ${this.url}: Heartbeat was not received for ${tolerance}ms, it will be reset.`);
}
else {
const tolerance = this.pingPongOptions.toleranceTimeout;
this.logger.error(`Connection to ${this.url}: Ping was not answered by a pong for ${tolerance}ms, it will be reset.`);
}
clearTimeout(this.pingPongTimer);
this.closedDuoToPongOrHeartbeatTimeout = true;
this.closeConnection();
};
ping = (intervalOverride) => {
this.pingPongTimer = setTimeout(() => {
if (this.isConnected) {
this.pingPongToleranceTimer = setTimeout(this.handleNoPong, this.pingPongOptions.toleranceTimeout);
if (!this.pingPongOptions.heartbeatOnly) {
this.pingPongOptions.doPing(this.send);
}
if (delay > 0) {
this.logger.debug(`Will try to reconnect to ${this.url} after ${delay}ms.`);
clearTimeout(this.reconnectDelayTimer);
this.reconnectDelayTimer = setTimeout(this.reconnect, delay);
return;
}
}
this.reconnect();
};
this.closeConnection = () => {
var _a;
try {
(_a = this.connection) === null || _a === void 0 ? void 0 : _a.close();
}, intervalOverride || this.pingPongOptions.interval);
};
keepAlive = () => {
this.keepAliveTimer = setTimeout(() => {
if (this.isConnected) {
this.keepAliveOptions.doKeepAlive(this.send);
this.keepAlive();
}
catch (_b) {
// Ignore errors here, failure to close is not very problematic
}, this.keepAliveOptions.interval);
};
handleOpen = () => {
this.attemptingToEstablishConnection = false;
this.reconnectingForcefully = false;
this.closedDuoToPongOrHeartbeatTimeout = false;
this.emit('connected');
if (!this.initialConnectionEstablished) {
this.logger.debug(`Connection to ${this.url} was successfully established.`);
this.onInitialConnectionEstablished(this.send);
this.initialConnectionEstablished = true;
}
else {
clearTimeout(this.reconnectBackoffIncrementResetTimer);
this.reconnectBackoffIncrementResetTimer = setTimeout(this.resetBackoffIncrement, this.backoffOptions.backoffIncrementResetTimeout);
this.logger.debug(`Successfully reconnected to ${this.url}.`);
this.onReconnect(this.send);
this.emit('reconnected');
}
if (this.queuedDataToSendOnReconnect.length > 0) {
const queue = this.queuedDataToSendOnReconnect;
this.queuedDataToSendOnReconnect = [];
this.logger.debug(`Attempting to send ${queue.length} queued item(s) to ${this.url}.`);
for (const data of queue) {
this.connection?.send(data);
}
};
this.handleConnectionLost = (reason, error) => {
let preventDefault = false;
this.onConnectionLost({
reason,
error,
preventDefault: () => {
preventDefault = true;
},
});
if (!preventDefault) {
this.emit('connection-lost', reason, error);
this.reconnectWithDelay();
}
if (this.pingPongOptions.enabled) {
this.ping();
}
if (this.keepAliveOptions.enabled) {
this.keepAlive();
}
};
handleClose = () => {
this.attemptingToEstablishConnection = false;
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
clearTimeout(this.keepAliveTimer);
if (!this.closedExternally && !this.reconnecting) {
if (this.closedDuoToPongOrHeartbeatTimeout) {
this.closedDuoToPongOrHeartbeatTimeout = false;
this.handleConnectionLost('pong-or-heartbeat-timeout');
}
};
this.handleNoPong = () => {
if (this.pingPongOptions.heartbeatOnly) {
const debounce = this.pingPongOptions.heartbeatDebounce ? this.pingPongOptions.heartbeatDebounce : 0;
const tolerance = this.pingPongOptions.toleranceTimeout + debounce;
this.logger.error(`Connection to ${this.url}: Heartbeat was not received for ${tolerance}ms, it will be reset.`);
}
else {
const tolerance = this.pingPongOptions.toleranceTimeout;
this.logger.error(`Connection to ${this.url}: Ping was not answered by a pong for ${tolerance}ms, it will be reset.`);
this.handleConnectionLost('closed-unexpectedly');
}
clearTimeout(this.pingPongTimer);
this.closedDuoToPongOrHeartbeatTimeout = true;
this.closeConnection();
};
this.ping = (intervalOverride) => {
this.pingPongTimer = setTimeout(() => {
if (this.isConnected) {
this.pingPongToleranceTimer = setTimeout(this.handleNoPong, this.pingPongOptions.toleranceTimeout);
if (!this.pingPongOptions.heartbeatOnly) {
this.pingPongOptions.doPing(this.send);
}
}
};
handleError = (event) => {
this.attemptingToEstablishConnection = false;
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
clearTimeout(this.keepAliveTimer);
if (!this.closedExternally && !this.reconnecting) {
this.logger.error(`Connection to ${this.url} encountered an error.`);
this.handleConnectionLost('error', (event && event.message) || undefined);
}
};
handleMessage = (event) => {
if (this.pingPongOptions.enabled) {
if (this.pingPongOptions.doCheckHeartbeat(event)) {
this.emit('heartbeat');
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
if (this.pingPongOptions.heartbeatDebounce !== null) {
this.ping(this.pingPongOptions.heartbeatDebounce);
}
}, intervalOverride || this.pingPongOptions.interval);
};
this.keepAlive = () => {
this.keepAliveTimer = setTimeout(() => {
if (this.isConnected) {
this.keepAliveOptions.doKeepAlive(this.send);
this.keepAlive();
else {
this.ping();
}
}, this.keepAliveOptions.interval);
};
this.handleOpen = () => {
var _a;
this.attemptingToEstablishConnection = false;
this.reconnectingForcefully = false;
this.closedDuoToPongOrHeartbeatTimeout = false;
this.emit('connected');
if (!this.initialConnectionEstablished) {
this.logger.debug(`Connection to ${this.url} was successfully established.`);
this.onInitialConnectionEstablished(this.send);
this.initialConnectionEstablished = true;
if (!this.pingPongOptions.forwardHeartbeatMessage) {
return;
}
}
else {
clearTimeout(this.reconnectBackoffIncrementResetTimer);
this.reconnectBackoffIncrementResetTimer = setTimeout(this.resetBackoffIncrement, this.backoffOptions.backoffIncrementResetTimeout);
this.logger.debug(`Successfully reconnected to ${this.url}.`);
this.onReconnect(this.send);
this.emit('reconnected');
}
if (this.queuedDataToSendOnReconnect.length > 0) {
const queue = this.queuedDataToSendOnReconnect;
this.queuedDataToSendOnReconnect = [];
this.logger.debug(`Attempting to send ${queue.length} queued item(s) to ${this.url}.`);
for (const data of queue) {
(_a = this.connection) === null || _a === void 0 ? void 0 : _a.send(data);
else if (!this.pingPongOptions.heartbeatOnly && this.pingPongOptions.doCheckPong(event)) {
this.emit('pong');
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
this.ping();
if (!this.pingPongOptions.forwardPongMessage) {
return;
}
}
if (this.pingPongOptions.enabled) {
else if (!this.pingPongOptions.disableDebounceOnMessage) {
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
this.ping();
}
if (this.keepAliveOptions.enabled) {
this.keepAlive();
}
const data = event.data === 'string' ? event.data : event.data.toString();
this.onData(data);
this.emit('data', data);
};
checkConnection = () => {
if (this.closedExternally) {
return;
}
if (this.initialConnectionEstablished && !this.reconnecting && !this.isConnected) {
if (this.reconnectingForcefully) {
this.logger.debug(`Connection to ${this.url} was forcefully closed.`);
}
};
this.handleClose = () => {
this.attemptingToEstablishConnection = false;
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
clearTimeout(this.keepAliveTimer);
if (!this.closedExternally && !this.reconnecting) {
if (this.closedDuoToPongOrHeartbeatTimeout) {
this.closedDuoToPongOrHeartbeatTimeout = false;
this.handleConnectionLost('pong-or-heartbeat-timeout');
}
else {
this.handleConnectionLost('closed-unexpectedly');
}
else {
this.logger.error(`Connection to ${this.url} was unexpectedly lost.`);
}
};
this.handleError = (event) => {
this.attemptingToEstablishConnection = false;
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
clearTimeout(this.keepAliveTimer);
if (!this.closedExternally && !this.reconnecting) {
this.logger.error(`Connection to ${this.url} encountered an error.`);
this.handleConnectionLost('error', (event && event.message) || undefined);
if (this.closedDuoToPongOrHeartbeatTimeout) {
this.closedDuoToPongOrHeartbeatTimeout = false;
this.handleConnectionLost('pong-or-heartbeat-timeout');
}
};
this.handleMessage = (event) => {
if (this.pingPongOptions.enabled) {
if (this.pingPongOptions.doCheckHeartbeat(event)) {
this.emit('heartbeat');
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
if (this.pingPongOptions.heartbeatDebounce !== null) {
this.ping(this.pingPongOptions.heartbeatDebounce);
}
else {
this.ping();
}
if (!this.pingPongOptions.forwardHeartbeatMessage) {
return;
}
}
else if (!this.pingPongOptions.heartbeatOnly && this.pingPongOptions.doCheckPong(event)) {
this.emit('pong');
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
this.ping();
if (!this.pingPongOptions.forwardPongMessage) {
return;
}
}
else if (!this.pingPongOptions.disableDebounceOnMessage) {
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
this.ping();
}
else {
this.handleConnectionLost('closed-unexpectedly');
}
const data = event.data === 'string' ? event.data : event.data.toString();
this.onData(data);
this.emit('data', data);
};
this.checkConnection = () => {
if (this.closedExternally) {
return;
}
if (this.initialConnectionEstablished && !this.reconnecting && !this.isConnected) {
if (this.reconnectingForcefully) {
this.logger.debug(`Connection to ${this.url} was forcefully closed.`);
}
else {
this.logger.error(`Connection to ${this.url} was unexpectedly lost.`);
}
clearTimeout(this.pingPongTimer);
clearTimeout(this.pingPongToleranceTimer);
clearTimeout(this.keepAliveTimer);
if (this.closedDuoToPongOrHeartbeatTimeout) {
this.closedDuoToPongOrHeartbeatTimeout = false;
this.handleConnectionLost('pong-or-heartbeat-timeout');
}
else {
this.handleConnectionLost('closed-unexpectedly');
}
}
this.checkConnectionTimer = setTimeout(this.checkConnection, this.connectionCheckInterval);
};
this.connect = () => {
this.closeConnection();
this.attemptingToEstablishConnection = true;
this.logger.debug(`Attempting to connect to ${this.url}.`);
this.connection = new isomorphic_ws_1.default(this.url, { agent: this.agent });
this.onConnecting(this.connection);
this.emit('connecting');
this.connection.onopen = this.handleOpen;
this.connection.onmessage = this.handleMessage;
this.connection.onclose = this.handleClose;
this.connection.onerror = this.handleError;
};
const optionsWithDefaults = (0, defaults_1.getOptionsWithDefaults)(options);
this.logger = optionsWithDefaults.logger;
this.url = optionsWithDefaults.url;
this.reconnectTimeout = optionsWithDefaults.reconnectTimeout;
this.connectionCheckInterval = optionsWithDefaults.connectionCheckInterval;
this.agent = optionsWithDefaults.agent;
this.pingPongOptions = optionsWithDefaults.pingPong;
this.keepAliveOptions = optionsWithDefaults.keepAlive;
this.backoffOptions = optionsWithDefaults.reconnectBackoff;
this.onInitialConnectionEstablished = optionsWithDefaults.onInitialConnectionEstablished;
this.onReconnect = optionsWithDefaults.onReconnect;
this.onData = optionsWithDefaults.onData;
this.onReconnecting = optionsWithDefaults.onReconnecting;
this.onConnecting = optionsWithDefaults.onConnecting;
this.onConnectionLost = optionsWithDefaults.onConnectionLost;
this.connect();
this.checkConnection();
}
}
this.checkConnectionTimer = setTimeout(this.checkConnection, this.connectionCheckInterval);
};
connect = () => {
this.closeConnection();
this.attemptingToEstablishConnection = true;
this.logger.debug(`Attempting to connect to ${this.url}.`);
this.connection = new WebSocket(this.url, { agent: this.agent });
this.onConnecting(this.connection);
this.emit('connecting');
this.connection.onopen = this.handleOpen;
this.connection.onmessage = this.handleMessage;
this.connection.onclose = this.handleClose;
this.connection.onerror = this.handleError;
};
}
exports.PersistentWebsocketConnection = PersistentWebsocketConnection;
//# sourceMappingURL=PersistentWebsocketConnection.js.map

@@ -1,2 +0,2 @@

/// <reference types="node" />
/// <reference types="node" resolution-mode="require"/>
import WebSocket, { MessageEvent } from 'ws';

@@ -3,0 +3,0 @@ import type { Agent } from 'http';

@@ -1,3 +0,2 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
export {};
//# sourceMappingURL=types.js.map
{
"name": "@aurox/persistent-websocket-connection",
"version": "0.5.0",
"version": "0.6.0",
"description": "Aurox Persistent Websocket Connection",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",
"scripts": {

@@ -20,20 +21,20 @@ "prepublishOnly": "npm run build",

"dependencies": {
"@types/node": "^18.11.18",
"@types/ws": "^8.5.3",
"@types/node": "^20.3.0",
"@types/ws": "^8.5.5",
"isomorphic-ws": "^5.0.0",
"tiny-typed-emitter": "^2.1.0",
"tslib": "^2.4.1",
"ws": "^8.11.0"
"tslib": "^2.5.3",
"ws": "^8.13.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.47.1",
"@typescript-eslint/parser": "^5.47.1",
"eslint": "^8.30.0",
"eslint-config-prettier": "^8.5.0",
"@typescript-eslint/eslint-plugin": "^5.59.9",
"@typescript-eslint/parser": "^5.59.9",
"eslint": "^8.42.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"prettier": "^2.8.1",
"rimraf": "^3.0.2",
"prettier": "^2.8.8",
"rimraf": "^5.0.1",
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
"typescript": "^5.1.3"
}
}
import { MessageEvent } from 'ws';
import { PersistentWebsocketConnectionOptions } from './types';
import { PersistentWebsocketConnectionOptions } from './types.js';
import {

@@ -10,3 +10,3 @@ DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_RECONNECT_TIMEOUT,

DEFAULT_PERSISTENT_WEBSOCKET_CONNECTION_KEEP_ALIVE_INTERVAL,
} from './constants';
} from './constants.js';

@@ -13,0 +13,0 @@ function defaultDoPing(send: (data: any) => void) {

@@ -1,5 +0,5 @@

export * from './constants';
export * from './types';
export * from './constants.js';
export * from './types.js';
import { PersistentWebsocketConnection, PersistentWebsocketConnectionEvents } from './PersistentWebsocketConnection';
import { PersistentWebsocketConnection, PersistentWebsocketConnectionEvents } from './PersistentWebsocketConnection.js';

@@ -6,0 +6,0 @@ export { PersistentWebsocketConnectionEvents };

@@ -5,3 +5,3 @@ import WebSocket, { MessageEvent, ErrorEvent } from 'isomorphic-ws';

import { getOptionsWithDefaults } from './defaults';
import { getOptionsWithDefaults } from './defaults.js';
import {

@@ -15,3 +15,3 @@ PersistentWebsocketConnectionPingPongOptions,

PersistentWebsocketConnectionKeepAlive,
} from './types';
} from './types.js';

@@ -18,0 +18,0 @@ export interface PersistentWebsocketConnectionEvents {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc