New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@matrixai/ws

Package Overview
Dependencies
Maintainers
0
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@matrixai/ws - npm Package Compare versions

Comparing version

to
1.2.1

flake.lock

16

dist/types.d.ts
/// <reference types="node" />
import type { IncomingHttpHeaders } from 'http';
/// <reference types="node" />
import type { IncomingHttpHeaders, Server as HttpServer } from 'http';
import type { Server as HttpsServer } from 'https';
/**

@@ -133,2 +135,3 @@ * Generic callback

type WebSocketClientConfigInput = Partial<WebSocketConfig>;
type WebSocketClientConfigInputWithoutTLS = Omit<Partial<WebSocketConfig>, 'key' | 'cert' | 'ca' | 'verifyCallback' | 'verifyPeer'>;
type WebSocketServerConfigInput = Partial<WebSocketConfig> & {

@@ -138,9 +141,4 @@ key: string | Array<string> | Uint8Array | Array<Uint8Array>;

};
type WebSocketServerConfigInputWithInjectedServer = Partial<WebSocketConfig & {
key: undefined;
cert: undefined;
ca: undefined;
verifyCallback: undefined;
verifyPeer: undefined;
}>;
type WebSocketServerConfigInputWithoutTLS = Omit<Partial<WebSocketConfig>, 'key' | 'cert' | 'ca' | 'verifyCallback' | 'verifyPeer'>;
type RawServer = HttpServer | HttpsServer;
type ConnectionError = {

@@ -150,2 +148,2 @@ errorCode: number;

};
export type { Opaque, Callback, PromiseDeconstructed, ConnectionId, Host, Hostname, Port, Address, ResolveHostname, StreamReasonToCode, StreamCodeToReason, ConnectionMetadata, TLSVerifyCallback, WebSocketConfig, WebSocketClientConfigInput, WebSocketServerConfigInput, WebSocketServerConfigInputWithInjectedServer, ConnectionError, };
export type { Opaque, Callback, PromiseDeconstructed, ConnectionId, Host, Hostname, Port, Address, ResolveHostname, StreamReasonToCode, StreamCodeToReason, ConnectionMetadata, TLSVerifyCallback, WebSocketConfig, WebSocketClientConfigInput, WebSocketClientConfigInputWithoutTLS, WebSocketServerConfigInput, WebSocketServerConfigInputWithoutTLS, RawServer, ConnectionError, };

@@ -5,5 +5,7 @@ /// <reference types="node" />

import type { DetailedPeerCertificate } from 'tls';
import * as ws from 'ws';
declare const textEncoder: TextEncoder;
declare const textDecoder: TextDecoder;
declare function never(message?: string): never;
declare function isNodeWebsocket(websocket: any): websocket is ws.WebSocket;
/**

@@ -114,2 +116,12 @@ * Is it an IPv4 address?

/**
* WebSocket ready states
* sourced from: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
*/
declare enum WebSocketReadyState {
Connecting = 0,
Open = 1,
Closing = 2,
Closed = 3
}
/**
* WebSocketConnection error/close codes

@@ -135,2 +147,2 @@ * sourced from: https://www.iana.org/assignments/websocket/websocket.xml

}
export { textEncoder, textDecoder, never, isIPv4, isIPv6, isIPv4MappedIPv6, isIPv4MappedIPv6Hex, isIPv4MappedIPv6Dec, toIPv4MappedIPv6Dec, toIPv4MappedIPv6Hex, fromIPv4MappedIPv6, toCanonicalIp, resolveHostname, resolveHost, isPort, toPort, promisify, promise, bufferWrap, buildAddress, resolvesZeroIP, isHostWildcard, sleep, toPeerCertChain, collectPEMs, pemToDER, derToPEM, formatError, ConnectionErrorCode, };
export { textEncoder, textDecoder, never, isNodeWebsocket, isIPv4, isIPv6, isIPv4MappedIPv6, isIPv4MappedIPv6Hex, isIPv4MappedIPv6Dec, toIPv4MappedIPv6Dec, toIPv4MappedIPv6Hex, fromIPv4MappedIPv6, toCanonicalIp, resolveHostname, resolveHost, isPort, toPort, promisify, promise, bufferWrap, buildAddress, resolvesZeroIP, isHostWildcard, sleep, toPeerCertChain, collectPEMs, pemToDER, derToPEM, formatError, WebSocketReadyState, ConnectionErrorCode, };

@@ -26,5 +26,6 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.formatError = exports.derToPEM = exports.pemToDER = exports.collectPEMs = exports.toPeerCertChain = exports.sleep = exports.isHostWildcard = exports.resolvesZeroIP = exports.buildAddress = exports.bufferWrap = exports.promise = exports.promisify = exports.toPort = exports.isPort = exports.resolveHost = exports.resolveHostname = exports.toCanonicalIp = exports.fromIPv4MappedIPv6 = exports.toIPv4MappedIPv6Hex = exports.toIPv4MappedIPv6Dec = exports.isIPv4MappedIPv6Dec = exports.isIPv4MappedIPv6Hex = exports.isIPv4MappedIPv6 = exports.isIPv6 = exports.isIPv4 = exports.never = exports.textDecoder = exports.textEncoder = void 0;
exports.WebSocketReadyState = exports.formatError = exports.derToPEM = exports.pemToDER = exports.collectPEMs = exports.toPeerCertChain = exports.sleep = exports.isHostWildcard = exports.resolvesZeroIP = exports.buildAddress = exports.bufferWrap = exports.promise = exports.promisify = exports.toPort = exports.isPort = exports.resolveHost = exports.resolveHostname = exports.toCanonicalIp = exports.fromIPv4MappedIPv6 = exports.toIPv4MappedIPv6Hex = exports.toIPv4MappedIPv6Dec = exports.isIPv4MappedIPv6Dec = exports.isIPv4MappedIPv6Hex = exports.isIPv4MappedIPv6 = exports.isIPv6 = exports.isIPv4 = exports.isNodeWebsocket = exports.never = exports.textDecoder = exports.textEncoder = void 0;
const dns = __importStar(require("dns"));
const ip_num_1 = require("ip-num");
const ws = __importStar(require("ws"));
const errors = __importStar(require("./errors"));

@@ -39,2 +40,6 @@ const textEncoder = new TextEncoder();

exports.never = never;
function isNodeWebsocket(websocket) {
return websocket.constructor === ws.WebSocket;
}
exports.isNodeWebsocket = isNodeWebsocket;
/**

@@ -465,2 +470,14 @@ * Is it an IPv4 address?

exports.formatError = formatError;
/**
* WebSocket ready states
* sourced from: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
*/
var WebSocketReadyState;
(function (WebSocketReadyState) {
WebSocketReadyState[WebSocketReadyState["Connecting"] = 0] = "Connecting";
WebSocketReadyState[WebSocketReadyState["Open"] = 1] = "Open";
WebSocketReadyState[WebSocketReadyState["Closing"] = 2] = "Closing";
WebSocketReadyState[WebSocketReadyState["Closed"] = 3] = "Closed";
})(WebSocketReadyState || (WebSocketReadyState = {}));
exports.WebSocketReadyState = WebSocketReadyState;
//# sourceMappingURL=utils.js.map

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

import type { ResolveHostname, StreamCodeToReason, StreamReasonToCode, WebSocketClientConfigInput } from './types';
import type { ResolveHostname, StreamCodeToReason, StreamReasonToCode, WebSocketClientConfigInput, WebSocketClientConfigInputWithoutTLS } from './types';
import type { ContextTimedInput } from '@matrixai/contexts';
import { createDestroy } from '@matrixai/async-init';
import Logger from '@matrixai/logger';
import * as ws from 'ws';
import { EventAll } from '@matrixai/events';

@@ -36,6 +37,12 @@ import WebSocketConnection from './WebSocketConnection';

*/
static createWebSocketClient({ host, port, config, logger, }: {
static createWebSocketClient({ host, port, path, protocol, config, logger, }: ({
protocol?: 'wss';
config?: WebSocketClientConfigInput;
} | {
protocol: 'ws';
config?: WebSocketClientConfigInputWithoutTLS;
}) & {
host: string;
port: number;
config?: WebSocketClientConfigInput;
path?: string;
resolveHostname?: ResolveHostname;

@@ -45,2 +52,3 @@ reasonToCode?: StreamReasonToCode;

logger?: Logger;
_webSocketClass?: typeof globalThis.WebSocket | typeof ws.WebSocket;
}, ctx?: Partial<ContextTimedInput>): Promise<WebSocketClient>;

@@ -47,0 +55,0 @@ /**

@@ -41,3 +41,3 @@ "use strict";

const logger_1 = __importDefault(require("@matrixai/logger"));
const ws_1 = __importDefault(require("ws"));
const ws = __importStar(require("ws"));
const events_2 = require("@matrixai/events");

@@ -63,3 +63,5 @@ const decorators_1 = require("@matrixai/contexts/dist/decorators");

let WebSocketClient = class WebSocketClient {
static async createWebSocketClient({ host, port, config, resolveHostname = utils.resolveHostname, reasonToCode, codeToReason, logger = new logger_1.default(`${this.name}`), }, ctx) {
static async createWebSocketClient({ host, port, protocol = 'wss', path = '', config, resolveHostname = utils.resolveHostname, reasonToCode, codeToReason, logger = new logger_1.default(`${this.name}`), _webSocketClass = globalThis.WebSocket == null
? ws.WebSocket
: globalThis.WebSocket, }, ctx) {
logger.info(`Create ${this.name} to ${host}:${port}`);

@@ -70,19 +72,33 @@ const wsConfig = {

};
let [host_] = await utils.resolveHost(host, resolveHostname);
let hostOrHostname_ = host;
// We only resolve the host when working in Node,
// As `browser.dns.resolve` API is still canary-only on Chrome
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns/resolve
if (_webSocketClass === ws.WebSocket) {
const [host_] = await utils.resolveHost(host, resolveHostname);
// If the target host is in fact a zero IP, it cannot be used
// as a target host, so we need to resolve it to a non-zero IP
// in this case, 0.0.0.0 is resolved to 127.0.0.1 and :: and ::0 is
// resolved to ::1
hostOrHostname_ = utils.resolvesZeroIP(host_);
}
const port_ = utils.toPort(port);
// If the target host is in fact a zero IP, it cannot be used
// as a target host, so we need to resolve it to a non-zero IP
// in this case, 0.0.0.0 is resolved to 127.0.0.1 and :: and ::0 is
// resolved to ::1
host_ = utils.resolvesZeroIP(host_);
const address = `wss://${utils.buildAddress(host_, port_)}`;
// RejectUnauthorized must be false when TLSVerifyCallback exists,
// This is so that verification can be deferred to the callback rather than the system installed Certs
const webSocket = new ws_1.default(address, {
rejectUnauthorized: wsConfig.verifyPeer && wsConfig.verifyCallback == null,
key: wsConfig.key,
cert: wsConfig.cert,
ca: wsConfig.ca,
headers: wsConfig.headers,
});
let path_ = path;
if (path !== '' && path[0] !== '/') {
path_ = `/${path_}`;
}
const address = `${protocol}://${utils.buildAddress(hostOrHostname_, port_)}${path_}`;
let webSocket;
if (_webSocketClass === ws.WebSocket) {
webSocket = new ws.WebSocket(address, {
rejectUnauthorized: wsConfig.verifyPeer && wsConfig.verifyCallback == null,
key: wsConfig.key,
cert: wsConfig.cert,
ca: wsConfig.ca,
headers: wsConfig.headers,
});
}
else {
webSocket = new _webSocketClass(address);
}
const connectionId = 0;

@@ -89,0 +105,0 @@ const connection = new WebSocketConnection_1.default({

/// <reference types="node" />
import type { ConnectionMetadata, Host, Port, StreamCodeToReason, StreamReasonToCode, WebSocketConfig } from './types';
import type { StreamId } from './message';
import type * as ws from 'ws';
import { startStop } from '@matrixai/async-init';
import { Lock } from '@matrixai/async-locks';
import Logger from '@matrixai/logger';
import * as ws from 'ws';
import { Timer } from '@matrixai/timer';

@@ -126,2 +126,3 @@ import { EventAll, EventError } from '@matrixai/events';

protected handleEventWebSocketStreamStopped: (evt: events.EventWebSocketStreamStopped) => void;
protected handleBrowserSocketMessage: (event: MessageEvent<ArrayBuffer>) => Promise<void>;
protected handleSocketMessage: (data: ws.RawData, isBinary: boolean) => Promise<void>;

@@ -131,3 +132,3 @@ protected handleSocketPing: () => void;

protected handleSocketClose: (errorCode: number, reason: Buffer) => void;
protected handleSocketError: (err: Error) => void;
protected handleSocketError: (err: any) => void;
/**

@@ -169,3 +170,3 @@ * Gets an array of local certificates in DER format starting on the leaf.

config: WebSocketConfig;
socket: ws.WebSocket;
socket: ws.WebSocket | typeof globalThis.WebSocket.prototype;
reasonToCode?: StreamReasonToCode;

@@ -179,3 +180,3 @@ codeToReason?: StreamCodeToReason;

config: WebSocketConfig;
socket: ws.WebSocket;
socket: ws.WebSocket | typeof globalThis.WebSocket.prototype;
reasonToCode?: StreamReasonToCode;

@@ -182,0 +183,0 @@ codeToReason?: StreamCodeToReason;

@@ -42,3 +42,2 @@ "use strict";

const logger_1 = __importDefault(require("@matrixai/logger"));
const ws = __importStar(require("ws"));
const timer_1 = require("@matrixai/timer");

@@ -234,2 +233,5 @@ const events_1 = require("@matrixai/events");

};
handleBrowserSocketMessage = async (event) => {
return this.handleSocketMessage(event.data, true);
};
handleSocketMessage = async (data, isBinary) => {

@@ -433,2 +435,3 @@ // If the timer is running, refresh it.

this.connectionId = connectionId;
socket.binaryType = 'arraybuffer';
this.socket = socket;

@@ -466,3 +469,6 @@ this.config = config;

this.socketLocallyClosed = true;
this.socket.close(errorCode, reason);
if (this.socket.readyState !== utils.WebSocketReadyState.Closed &&
this.socket.readyState !== utils.WebSocketReadyState.Closing) {
this.socket.close(errorCode, reason);
}
};

@@ -498,7 +504,7 @@ }

get closed() {
return this.socket.readyState === ws.CLOSED;
return this.socket.readyState === utils.WebSocketReadyState.Closed;
}
async start(ctx) {
this.logger.info(`Start ${this.constructor.name}`);
if (this.socket.readyState === ws.CLOSED) {
if (this.socket.readyState === utils.WebSocketReadyState.Closed) {
throw new errors.ErrorWebSocketConnectionClosed();

@@ -519,3 +525,3 @@ }

// If the socket is already open, then the it is already secure and established by the WebSocketServer
if (this.socket.readyState === ws.OPEN) {
if (this.socket.readyState === utils.WebSocketReadyState.Open) {
this.resolveSecureEstablishedP();

@@ -569,10 +575,18 @@ }

};
this.socket.once('error', openErrorHandler);
const openHandler = () => {
this.resolveSecureEstablishedP();
};
this.socket.once('open', openHandler);
// This will always happen, no need to remove the handler
this.socket.once('close', this.handleSocketClose);
if (this.type === 'client') {
if (utils.isNodeWebsocket(this.socket)) {
this.socket.once('error', openErrorHandler);
this.socket.once('open', openHandler);
// This will always happen, no need to remove the handler
this.socket.once('close', this.handleSocketClose);
}
else {
this.socket.addEventListener('error', openErrorHandler, { once: true });
this.socket.addEventListener('open', openHandler, { once: true });
// This will always happen, no need to remove the handler
this.socket.addEventListener('close', (event) => this.handleSocketClose(event.code, Buffer.from(event.reason)), { once: true });
}
if (this.type === 'client' && utils.isNodeWebsocket(this.socket)) {
this.socket.once('upgrade', async (request) => {

@@ -641,5 +655,10 @@ const tlsSocket = request.socket;

}
this.socket.off('open', openHandler);
// Upgrade only exists on the ws library, we can use removeAllListeners without worrying
this.socket.removeAllListeners('upgrade');
if (utils.isNodeWebsocket(this.socket)) {
this.socket.off('open', openHandler);
// Upgrade only exists on the ws library, we can use removeAllListeners without worrying
this.socket.removeAllListeners('upgrade');
}
else {
this.socket.removeEventListener('open', openHandler);
}
// Close the ws if it's open at this stage

@@ -651,10 +670,23 @@ await this.closedP;

ctx.signal.removeEventListener('abort', abortHandler);
// Upgrade has already been removed by being called once or by the catch
this.socket.off('error', openErrorHandler);
if (utils.isNodeWebsocket(this.socket)) {
// Upgrade has already been removed by being called once or by the catch
this.socket.off('error', openErrorHandler);
}
else {
this.socket.removeEventListener('error', openErrorHandler);
}
}
// Set the connection up
this.socket.on('message', this.handleSocketMessage);
this.socket.on('ping', this.handleSocketPing);
this.socket.on('pong', this.handleSocketPong);
this.socket.once('error', this.handleSocketError);
if (utils.isNodeWebsocket(this.socket)) {
this.socket.on('message', this.handleSocketMessage);
this.socket.on('ping', this.handleSocketPing);
this.socket.on('pong', this.handleSocketPong);
this.socket.once('error', this.handleSocketError);
}
else {
this.socket.addEventListener('message', this.handleBrowserSocketMessage);
this.socket.addEventListener('error', this.handleSocketError, {
once: true,
});
}
if (this.config.keepAliveIntervalTime != null) {

@@ -729,3 +761,3 @@ this.startKeepAliveIntervalTimer(this.config.keepAliveIntervalTime);

// causing all pending send promises to get to the same point and return
if (this.socket.readyState !== ws.OPEN) {
if (this.socket.readyState !== utils.WebSocketReadyState.Open) {
resolveSendReadyP();

@@ -735,11 +767,17 @@ return;

try {
const sendProm = utils.promise();
this.socket.send(array, { binary: true }, (err) => {
if (err == null)
sendProm.resolveP();
else
sendProm.rejectP(err);
});
// Await our own send
await sendProm.p;
if (utils.isNodeWebsocket(this.socket)) {
const sendProm = utils.promise();
this.socket.send(array, { binary: true }, (err) => {
if (err == null)
sendProm.resolveP();
else
sendProm.rejectP(err);
});
// Await our own send
await sendProm.p;
}
else {
// The browser does not accept callbacks to socket.send()
this.socket.send(array);
}
}

@@ -782,4 +820,4 @@ catch (err) {

this.stopKeepAliveTimeoutTimer();
if (this.socket.readyState !== ws.CLOSING &&
this.socket.readyState !== ws.CLOSED) {
if (this.socket.readyState !== utils.WebSocketReadyState.Closing &&
this.socket.readyState !== utils.WebSocketReadyState.Closed) {
this.closeSocket(errorCode, reason);

@@ -801,4 +839,4 @@ const e = new errors.ErrorWebSocketConnectionLocal(`Locally closed with code ${errorCode}`, {

force: force ||
this.socket.readyState === ws.CLOSED ||
this.socket.readyState === ws.CLOSING,
this.socket.readyState === utils.WebSocketReadyState.Closed ||
this.socket.readyState === utils.WebSocketReadyState.Closing,
}));

@@ -812,6 +850,12 @@ }

this.removeEventListener(events.EventWebSocketConnectionClose.name, this.handleEventWebSocketConnectionClose);
this.socket.off('message', this.handleSocketMessage);
this.socket.off('ping', this.handleSocketPing);
this.socket.off('pong', this.handleSocketPong);
this.socket.off('error', this.handleSocketError);
if (utils.isNodeWebsocket(this.socket)) {
this.socket.off('message', this.handleSocketMessage);
this.socket.off('ping', this.handleSocketPing);
this.socket.off('pong', this.handleSocketPong);
this.socket.off('error', this.handleSocketError);
}
else {
this.socket.removeEventListener('message', this.handleBrowserSocketMessage);
this.socket.removeEventListener('error', this.handleSocketError);
}
this.logger.info(`Stopped ${this.constructor.name}`);

@@ -828,3 +872,3 @@ }

return;
if (this.socket.readyState === ws.CLOSED) {
if (this.socket.readyState === utils.WebSocketReadyState.Closed) {
this.resolveClosedP();

@@ -862,3 +906,5 @@ return;

return;
this.socket.ping();
if (utils.isNodeWebsocket(this.socket)) {
this.socket.ping();
}
this.keepAliveIntervalTimer = new timer_1.Timer({

@@ -865,0 +911,0 @@ delay: ms,

/// <reference types="node" />
import type { IncomingMessage, ServerResponse } from 'http';
import type { Host, Port, ResolveHostname, StreamCodeToReason, StreamReasonToCode, WebSocketConfig, WebSocketServerConfigInput, WebSocketServerConfigInputWithInjectedServer } from './types';
import type { Host, Port, RawServer, ResolveHostname, StreamCodeToReason, StreamReasonToCode, WebSocketConfig, WebSocketServerConfigInput, WebSocketServerConfigInputWithoutTLS } from './types';
import type { EventAll } from '@matrixai/events';
import https from 'https';
import { StartStop } from '@matrixai/async-init/dist/StartStop';

@@ -27,5 +26,5 @@ import Logger from '@matrixai/logger';

/**
* Determines whether the socket is injected or not
* If the server is not injected, determines if we create a server or not.
*/
readonly isServerShared: boolean;
readonly isNoServer: boolean;
/**

@@ -53,3 +52,3 @@ * Custom reason to code converter for new connections.

readonly connectionMap: WebSocketConnectionMap;
protected server: https.Server;
protected server: RawServer | undefined;
protected webSocketServer: ws.WebSocketServer;

@@ -100,3 +99,4 @@ protected webSocketServerClosed: boolean;

* @param opts.config - configuration for new connections.
* @param opts.server - if not provided, a new server will be created.
* @param opts.server - if provided, WebSocketServer will use an existing http.
* @param opts.noServer - if true, a new .
* @param opts.reasonToCode - reasonToCode for stream errors

@@ -106,14 +106,16 @@ * @param opts.codeToReason - codeToReason for stream errors

*/
constructor({ config, resolveHostname, server, reasonToCode, codeToReason, connectTimeoutTime, logger, }: {
constructor({ config, resolveHostname, server, noServer, reasonToCode, codeToReason, connectTimeoutTime, logger, }: ({
config?: WebSocketServerConfigInputWithoutTLS;
server?: undefined;
noServer: true;
} | {
config: WebSocketServerConfigInput;
resolveHostname?: ResolveHostname;
server?: undefined;
reasonToCode?: StreamReasonToCode;
codeToReason?: StreamCodeToReason;
connectTimeoutTime?: number;
logger?: Logger;
noServer?: false;
} | {
config?: WebSocketServerConfigInputWithInjectedServer;
config?: WebSocketServerConfigInputWithoutTLS;
server: RawServer;
noServer?: false;
}) & {
resolveHostname?: ResolveHostname;
server: https.Server;
reasonToCode?: StreamReasonToCode;

@@ -124,3 +126,9 @@ codeToReason?: StreamCodeToReason;

});
/**
* Returns the port of the server. This will be 127.0.0.1 if `noServer` was true during construction.
*/
get host(): Host;
/**
* Returns the port of the server. This will be 0 if `noServer` was true during construction.
*/
get port(): Port;

@@ -169,2 +177,17 @@ /**

/**
* Tells the WebSocketServer to manually handle an upgrade request.
* This is useful for when `noServer` is set to `true` during construction.
*/
handleUpgrade(...args: Parameters<typeof this.webSocketServer.handleUpgrade>): ReturnType<typeof this.webSocketServer.handleUpgrade>;
/**
* Checks if the WebSocketServer should handle the request.
* This is useful for when `noServer` is set to `true` during construction.
*/
shouldHandle(...args: Parameters<typeof this.webSocketServer.shouldHandle>): ReturnType<typeof this.webSocketServer.shouldHandle>;
/**
* Manually triggers a `WebSocket` connection with the underlying `ws` library.
* This is useful for when `noServer` is set to `true` during construction.
*/
handleWebSocket(webSocket: ws.WebSocket, request: IncomingMessage): void;
/**
* Will tell any normal HTTP request to upgrade

@@ -171,0 +194,0 @@ */

@@ -35,2 +35,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const tls_1 = require("tls");
const https_1 = __importDefault(require("https"));

@@ -61,5 +62,5 @@ const events_1 = require("@matrixai/events");

/**
* Determines whether the socket is injected or not
* If the server is not injected, determines if we create a server or not.
*/
isServerShared;
isNoServer;
/**

@@ -111,4 +112,4 @@ * Custom reason to code converter for new connections.

this.webSocketServer.off('close', this.handleWebSocketServerClosed);
this.server.off('close', this.handleServerClosed);
if (this.isServerShared) {
this.server?.off('close', this.handleServerClosed);
if (this.server == null) {
if (this.webSocketServerClosed) {

@@ -178,22 +179,27 @@ this.resolveClosedP();

const connectionId = this.connectionMap.allocateId();
const peerCert = httpSocket.getPeerCertificate(true);
const peerCertChain = utils.toPeerCertChain(peerCert);
const localCACertsChain = utils
.collectPEMs(this.config.ca)
.map(utils.pemToDER);
const localCertsChain = utils
.collectPEMs(this.config.cert)
.map(utils.pemToDER);
const meta = {
remoteHost: httpSocket.remoteAddress ?? '',
remotePort: httpSocket.remotePort ?? 0,
localHost: httpSocket.localAddress ?? '',
localPort: httpSocket.localPort ?? 0,
localCACertsChain: [],
localCertsChain: [],
remoteCertsChain: [],
};
// Only perform certificate verification if is TLS Socket
if (httpSocket instanceof tls_1.TLSSocket) {
const peerCert = httpSocket.getPeerCertificate(true);
const peerCertChain = utils.toPeerCertChain(peerCert);
meta.remoteCertsChain = peerCertChain;
meta.localCACertsChain = utils
.collectPEMs(this.config.ca)
.map(utils.pemToDER);
meta.localCertsChain = utils
.collectPEMs(this.config.cert)
.map(utils.pemToDER);
}
const connection = new WebSocketConnection_1.default({
type: 'server',
connectionId: connectionId,
meta: {
remoteHost: httpSocket.remoteAddress ?? '',
remotePort: httpSocket.remotePort ?? 0,
localHost: httpSocket.localAddress ?? '',
localPort: httpSocket.localPort ?? 0,
localCACertsChain,
localCertsChain,
remoteCertsChain: peerCertChain,
},
meta: meta,
socket: webSocket,

@@ -254,3 +260,4 @@ config: { ...this.config },

* @param opts.config - configuration for new connections.
* @param opts.server - if not provided, a new server will be created.
* @param opts.server - if provided, WebSocketServer will use an existing http.
* @param opts.noServer - if true, a new .
* @param opts.reasonToCode - reasonToCode for stream errors

@@ -260,3 +267,3 @@ * @param opts.codeToReason - codeToReason for stream errors

*/
constructor({ config, resolveHostname = utils.resolveHostname, server, reasonToCode, codeToReason, connectTimeoutTime, logger, }) {
constructor({ config, resolveHostname = utils.resolveHostname, server, noServer = false, reasonToCode, codeToReason, connectTimeoutTime, logger, }) {
this.logger = logger ?? new logger_1.default(this.constructor.name);

@@ -282,15 +289,16 @@ this.config = {

this.resolveClosedP = resolveClosedP;
if (server != null) {
this.isServerShared = true;
this.server = server;
}
else {
this.isServerShared = false;
}
this.isNoServer = noServer;
this.server = server;
}
/**
* Returns the port of the server. This will be 127.0.0.1 if `noServer` was true during construction.
*/
get host() {
return this.server.address()?.address ?? '';
return this.server?.address()?.address ?? '127.0.0.1';
}
/**
* Returns the port of the server. This will be 0 if `noServer` was true during construction.
*/
get port() {
return this.server.address()?.port ?? 0;
return this.server?.address()?.port ?? 0;
}

@@ -323,3 +331,3 @@ /**

const port_ = utils.toPort(port);
if (!this.isServerShared) {
if (this.server == null && !this.isNoServer) {
this.server = https_1.default.createServer({

@@ -335,2 +343,3 @@ rejectUnauthorized: this.config.verifyPeer && this.config.verifyCallback == null,

server: this.server,
noServer: this.isNoServer,
path,

@@ -358,7 +367,7 @@ verifyClient: async (info, done) => {

this.webSocketServer.on('close', this.handleWebSocketServerClosed);
this.server.on('close', this.handleServerClosed);
this.server?.on('close', this.handleServerClosed);
this.webSocketServer.on('error', this.handleServerError);
this.server.on('error', this.handleServerError);
this.server.on('request', this.handleServerRequest);
if (!this.server.listening) {
this.server?.on('error', this.handleServerError);
this.server?.on('request', this.handleServerRequest);
if (this.server != null && !this.server.listening) {
const listenProm = utils.promise();

@@ -374,8 +383,8 @@ this.server.listen({

this.addEventListener(events.EventWebSocketServerClose.name, this.handleEventWebSocketServerClose, { once: true });
const serverAddress = this.server.address();
if (serverAddress == null || typeof serverAddress === 'string') {
const serverAddress = this.server?.address();
if (typeof serverAddress === 'string') {
utils.never();
}
this._port = serverAddress.port;
this._host = serverAddress.address ?? '127.0.0.1';
this._port = serverAddress?.port ?? 0;
this._host = serverAddress?.address ?? '127.0.0.1';
this.webSocketServerClosed = false;

@@ -420,6 +429,6 @@ this._closed = false;

this.webSocketServer.off('close', this.handleServerClosed);
this.server.off('close', this.handleServerClosed);
this.server?.off('close', this.handleServerClosed);
this.webSocketServer.off('error', this.handleServerError);
this.server.off('error', this.handleServerError);
this.server.on('request', this.handleServerRequest);
this.server?.off('error', this.handleServerError);
this.server?.on('request', this.handleServerRequest);
this.logger.info(`Stopped ${this.constructor.name}`);

@@ -432,3 +441,2 @@ }

updateConfig(config) {
const tlsServer = this.server;
const wsConfig = {

@@ -438,10 +446,33 @@ ...this.config,

};
tlsServer.setSecureContext({
key: wsConfig.key,
cert: wsConfig.cert,
ca: wsConfig.ca,
});
if (this.server instanceof tls_1.Server) {
this.server.setSecureContext({
key: wsConfig.key,
cert: wsConfig.cert,
ca: wsConfig.ca,
});
}
this.config = wsConfig;
}
/**
* Tells the WebSocketServer to manually handle an upgrade request.
* This is useful for when `noServer` is set to `true` during construction.
*/
handleUpgrade(...args) {
return this.webSocketServer.handleUpgrade(...args);
}
/**
* Checks if the WebSocketServer should handle the request.
* This is useful for when `noServer` is set to `true` during construction.
*/
shouldHandle(...args) {
return this.webSocketServer.shouldHandle(...args);
}
/**
* Manually triggers a `WebSocket` connection with the underlying `ws` library.
* This is useful for when `noServer` is set to `true` during construction.
*/
handleWebSocket(webSocket, request) {
this.webSocketServer.emit('connection', webSocket, request);
}
/**
* Will tell any normal HTTP request to upgrade

@@ -467,2 +498,11 @@ */

], WebSocketServer.prototype, "updateConfig", null);
__decorate([
(0, StartStop_1.ready)(new errors.ErrorWebSocketServerNotRunning())
], WebSocketServer.prototype, "handleUpgrade", null);
__decorate([
(0, StartStop_1.ready)(new errors.ErrorWebSocketServerNotRunning())
], WebSocketServer.prototype, "shouldHandle", null);
__decorate([
(0, StartStop_1.ready)(new errors.ErrorWebSocketServerNotRunning())
], WebSocketServer.prototype, "handleWebSocket", null);
WebSocketServer = __decorate([

@@ -469,0 +509,0 @@ (0, StartStop_1.StartStop)({

{
"name": "@matrixai/ws",
"version": "1.2.0",
"version": "1.2.1",
"author": "Matrix AI",

@@ -5,0 +5,0 @@ "contributors": [

# js-ws
staging:[![pipeline status](https://gitlab.com/MatrixAI/open-source/js-ws/badges/staging/pipeline.svg)](https://gitlab.com/MatrixAI/open-source/js-ws/commits/staging)
master:[![pipeline status](https://gitlab.com/MatrixAI/open-source/js-ws/badges/master/pipeline.svg)](https://gitlab.com/MatrixAI/open-source/js-ws/commits/master)
WebSocket library for TypeScript/JavaScript applications.

@@ -16,2 +13,18 @@

### Browser Usage
To use `WebSocketClient` in a browser environment, you will need to polyfill:
- [`buffer`](https://nodejs.org/api/buffer.html)
- [`perf_hooks`](https://nodejs.org/api/perf_hooks.html)
A good choice for a `buffer` polyfill is [`feross/buffer`](https://github.com/feross/buffer)
To polyfill `perf_hooks`, you can alias the `perf_hooks` using your bundler of choice with a file containing the following code:
```ts
const { performance } = globalThis;
export { performance };
```
## Development

@@ -18,0 +31,0 @@

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