Socket
Socket
Sign inDemoInstall

@helenejs/server

Package Overview
Dependencies
141
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.3.0-alpha.14 to 1.3.0-alpha.15

26

lib/client-node.d.ts

@@ -1,7 +0,3 @@

/// <reference types="ws" />
/// <reference types="node" />
/// <reference types="node" />
import IsomorphicWebSocket from 'isomorphic-ws';
import { WebSocketMessageOptions } from './transports';
import http from 'http';
import { Presentation } from '@helenejs/utils';

@@ -12,2 +8,4 @@ import { Request, Response } from 'express';

import { EventEmitter2 } from 'eventemitter2';
import sockjs from 'sockjs';
import http from 'http';
export type ClientNodeContext = Record<string, any>;

@@ -21,3 +19,3 @@ export declare class ClientNode extends EventEmitter2 {

user: Record<string, any>;
socket?: IsomorphicWebSocket;
socket?: sockjs.Connection;
isEventSource: boolean;

@@ -32,25 +30,23 @@ req?: Request;

userAgent: string;
keepAliveInterval: NodeJS.Timeout;
terminationTimeout: NodeJS.Timeout;
eventSourceDataId: number;
static KEEP_ALIVE_INTERVAL: number;
static ENABLE_KEEP_ALIVE: boolean;
constructor(server: Server, socket?: IsomorphicWebSocket, req?: Request, res?: Response, limit?: RateLimit);
constructor(server: Server, socket?: sockjs.Connection, req?: Request, res?: Response, limit?: RateLimit);
get storage(): unknown;
get authenticated(): boolean;
set authenticated(authenticated: boolean);
get readyState(): 0 | 1 | 2 | 3;
setId(request: http.IncomingMessage): void;
get readyState(): number;
setId(uuid: string): void;
setContext(context: ClientNodeContext): void;
setTrackingProperties(request: http.IncomingMessage): void;
setTrackingProperties(conn: sockjs.Connection | http.IncomingMessage): void;
setUserId(): void;
writeEventSource(res: Response, payload: string | Record<string, any>): void;
send(payload: Presentation.Payload | string, opts?: WebSocketMessageOptions): void;
result(payload: Presentation.MethodResultPayloadPartial, opts?: WebSocketMessageOptions): void;
send(payload: Presentation.Payload | string): void;
result(payload: Presentation.MethodResultPayloadPartial): void;
/**
* @warning There is an `event` property already in the super class.
*/
sendEvent(event: string, params?: any, opts?: WebSocketMessageOptions): void;
error(payload: Presentation.ErrorPayloadPartial, opts?: WebSocketMessageOptions): void;
sendEvent(event: string, params?: any): void;
error(payload: Presentation.ErrorPayloadPartial): void;
close(): void;
}

@@ -7,4 +7,2 @@ "use strict";

exports.ClientNode = void 0;
const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
const url_1 = __importDefault(require("url"));
const isString_1 = __importDefault(require("lodash/isString"));

@@ -15,2 +13,3 @@ const utils_1 = require("@helenejs/utils");

const eventemitter2_1 = require("eventemitter2");
const http_1 = __importDefault(require("http"));
class ClientNode extends eventemitter2_1.EventEmitter2 {

@@ -45,18 +44,2 @@ constructor(server, socket, req, res, limit) {

}
if (socket) {
this.keepAliveInterval = setInterval(() => {
if (ClientNode.ENABLE_KEEP_ALIVE &&
socket.readyState === isomorphic_ws_1.default.OPEN) {
this.sendEvent(utils_1.HeleneEvents.KEEP_ALIVE);
this.terminationTimeout = setTimeout(() => {
clearInterval(this.keepAliveInterval);
if (socket.readyState === isomorphic_ws_1.default.OPEN) {
socket?.terminate?.();
socket?.close?.();
this.emit(utils_1.HeleneEvents.KEEP_ALIVE_DISCONNECT);
}
}, ClientNode.KEEP_ALIVE_INTERVAL / 2);
}
}, ClientNode.KEEP_ALIVE_INTERVAL);
}
}

@@ -75,5 +58,4 @@ get storage() {

}
setId(request) {
const { query } = url_1.default.parse(request.url, true);
this.uuid = query?.uuid ?? utils_1.Presentation.uuid();
setId(uuid) {
this.uuid = uuid;
}

@@ -84,7 +66,12 @@ setContext(context) {

}
setTrackingProperties(request) {
this.headers = request.headers;
this.remoteAddress =
request.headers['x-forwarded-for'] || request.socket.remoteAddress;
this.userAgent = request.headers['user-agent'];
setTrackingProperties(conn) {
if (conn instanceof http_1.default.IncomingMessage) {
this.remoteAddress =
conn.headers['x-forwarded-for'] || conn.socket.remoteAddress;
}
else {
this.remoteAddress = conn.headers['x-forwarded-for'] || conn.remoteAddress;
}
this.headers = conn.headers;
this.userAgent = conn.headers['user-agent'];
}

@@ -109,3 +96,3 @@ // The user ID is used for authorizing the user's channel.

}
send(payload, opts) {
send(payload) {
if (!this.socket) {

@@ -116,6 +103,6 @@ const clientNode = this.server.httpTransport.eventSourceClients.get(this.uuid);

}
this.socket?.send((0, isString_1.default)(payload) ? payload : utils_1.Presentation.encode(payload), opts);
this.socket?.write((0, isString_1.default)(payload) ? payload : utils_1.Presentation.encode(payload));
}
result(payload, opts) {
this.socket.send(utils_1.Presentation.Outbound.result(payload), opts);
result(payload) {
this.socket.write(utils_1.Presentation.Outbound.result(payload));
}

@@ -125,3 +112,3 @@ /**

*/
sendEvent(event, params, opts) {
sendEvent(event, params) {
return this.send({

@@ -132,9 +119,8 @@ uuid: utils_1.Presentation.uuid(),

params,
}, opts);
});
}
error(payload, opts) {
this.socket?.send(utils_1.Presentation.Outbound.error(payload), opts);
error(payload) {
this.socket?.write(utils_1.Presentation.Outbound.error(payload));
}
close() {
this.socket?.terminate?.();
this.socket?.close?.();

@@ -154,3 +140,2 @@ if (this.isEventSource) {

ClientNode.KEEP_ALIVE_INTERVAL = 10000;
ClientNode.ENABLE_KEEP_ALIVE = true;
//# sourceMappingURL=client-node.js.map
import WebSocket from 'ws';
import { Server } from '../server';
import { Presentation } from '@helenejs/utils';
import http from 'http';
import { ClientNode } from '../client-node';
import IsomorphicWebSocket from 'isomorphic-ws';
import sockjs from 'sockjs';
export declare enum WebSocketTransportEvents {

@@ -14,10 +14,12 @@ WEBSOCKET_SERVER_ERROR = "websocket:server:error",

server: Server;
wss: WebSocket.Server;
wss: sockjs.Server;
options: WebSocket.ServerOptions;
constructor(server: Server, opts: WebSocket.ServerOptions);
handleConnection: (socket: WebSocket, request: http.IncomingMessage) => void;
handleConnection: (conn: sockjs.Connection) => void;
handleClose: (node: ClientNode) => () => void;
handleMessage: (node: ClientNode) => (data: WebSocket.Data) => Promise<void>;
handleMessage: (node: ClientNode) => (data: {
data: string;
}) => Promise<void>;
execute(payload: Presentation.MethodCallPayload, node: ClientNode): Promise<void>;
close(): Promise<void>;
}

@@ -7,5 +7,5 @@ "use strict";

exports.WebSocketTransport = exports.WebSocketTransportEvents = void 0;
const ws_1 = __importDefault(require("ws"));
const utils_1 = require("@helenejs/utils");
const client_node_1 = require("../client-node");
const sockjs_1 = __importDefault(require("sockjs"));
var WebSocketTransportEvents;

@@ -22,10 +22,13 @@ (function (WebSocketTransportEvents) {

};
this.handleConnection = (socket, request) => {
const node = new client_node_1.ClientNode(this.server, socket, undefined, undefined, this.server.rateLimit);
node.setId(request);
node.setTrackingProperties(request);
this.server.addClient(node);
socket.on(utils_1.WebSocketEvents.CLOSE, this.handleClose(node));
socket.on(utils_1.WebSocketEvents.ERROR, error => this.server.emit(utils_1.ServerEvents.SOCKET_ERROR, socket, error));
socket.on(utils_1.WebSocketEvents.MESSAGE, this.handleMessage(node));
this.handleConnection = (conn) => {
if (!this.server.acceptConnections) {
conn.destroy();
console.log('Helene: Connection Refused');
return;
}
const node = new client_node_1.ClientNode(this.server, conn, undefined, undefined, this.server.rateLimit);
node.setTrackingProperties(conn);
conn.on('close', this.handleClose(node));
conn.on('error', (error) => this.server.emit(utils_1.ServerEvents.SOCKET_ERROR, conn, error));
conn.on('data', this.handleMessage(node));
this.server.emit(utils_1.ServerEvents.CONNECTION, node);

@@ -38,13 +41,10 @@ };

this.handleMessage = (node) => async (data) => {
if (Buffer.isBuffer(data))
data = data.toString();
const opts = {
binary: data instanceof ArrayBuffer,
};
try {
if (node.readyState !== 1) {
console.warn(`Socket Not Ready`, node.readyState, node.uuid);
const parsedData = utils_1.Presentation.decode(data);
if (parsedData.type === utils_1.Presentation.PayloadType.SETUP) {
node.setId(parsedData.uuid);
this.server.addClient(node);
}
if (parsedData.type !== utils_1.Presentation.PayloadType.METHOD)
return;
}
const parsedData = utils_1.Presentation.decode(data);
if (parsedData.method !== utils_1.Methods.KEEP_ALIVE)

@@ -58,3 +58,3 @@ this.server.debugger(`Message Received`, parsedData);

stack: error.stack,
}, opts);
});
}

@@ -64,18 +64,7 @@ };

Object.assign(this.options, opts ?? {});
this.wss = new ws_1.default.Server(this.options);
this.wss = sockjs_1.default.createServer();
this.wss.on(utils_1.WebSocketEvents.CONNECTION, this.handleConnection);
this.wss.on(utils_1.WebSocketEvents.ERROR, error => server.emit(WebSocketTransportEvents.WEBSOCKET_SERVER_ERROR, error));
this.server.httpTransport.http.on(utils_1.ServerEvents.UPGRADE, (request, socket, head) => {
// Allows other upgrade requests to work alongside Helene, e.g. NextJS HMR.
if (!request.url.startsWith(this.options.path))
return;
if (!this.server.acceptConnections) {
socket.write(`HTTP/${request.httpVersion} 503 Service Unavailable\r\n\r\n`);
socket.destroy();
console.log('Helene: Upgrade Connection Refused');
return;
}
this.wss.handleUpgrade(request, socket, head, socket => {
this.wss.emit(utils_1.WebSocketEvents.CONNECTION, socket, request);
});
this.wss.on(utils_1.WebSocketEvents.ERROR, (error) => server.emit(WebSocketTransportEvents.WEBSOCKET_SERVER_ERROR, error));
this.wss.installHandlers(this.server.httpTransport.http, {
prefix: this.options.path,
});

@@ -144,18 +133,10 @@ }

close() {
return new Promise((resolve, reject) => {
return new Promise(resolve => {
if (!this.wss)
return resolve();
this.wss.clients.forEach(socket => {
socket.terminate();
this.server.allClients.forEach(node => {
if (node.socket)
node.close();
});
/**
* @todo Clean all client nodes from namespace and events.
*/
this.wss.close(err => {
if (err)
return reject(err);
this.wss = undefined;
this.server.emit(WebSocketTransportEvents.WEBSOCKET_SERVER_CLOSED);
resolve();
});
resolve();
});

@@ -162,0 +143,0 @@ }

{
"name": "@helenejs/server",
"version": "1.3.0-alpha.14",
"version": "1.3.0-alpha.15",
"description": "Real-time Web Apps for Node.js and Bun",

@@ -15,3 +15,3 @@ "main": "lib/index.js",

"dependencies": {
"@helenejs/utils": "^1.3.0-alpha.13",
"@helenejs/utils": "^1.3.0-alpha.15",
"@lukeed/uuid": "^2.0.1",

@@ -31,2 +31,3 @@ "ahooks": "^3.7.7",

"redis": "^4.6.7",
"sockjs": "^0.3.24",
"ws": "^8.13.0",

@@ -37,2 +38,3 @@ "yup": "^0.32.11"

"@types/express": "^4.17.13",
"@types/sockjs": "^0.3.36",
"@types/ws": "^8.5.5",

@@ -67,3 +69,3 @@ "rimraf": "^5.0.5",

},
"gitHead": "f5dcc45f2604bdba91bae368ac040228c10c34b3"
"gitHead": "838fc609b212aa2bdc00698b3bb4d6883206b670"
}

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc