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

socket.io-adapter

Package Overview
Dependencies
Maintainers
2
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

socket.io-adapter - npm Package Compare versions

Comparing version 2.4.0 to 2.5.0

dist/contrib/yeast.d.ts

45

dist/index.d.ts
/// <reference types="node" />
import { EventEmitter } from "events";
export declare type SocketId = string;
export declare type Room = string;
/**
* A public ID, sent by the server at the beginning of the Socket.IO session and which can be used for private messaging
*/
export type SocketId = string;
/**
* A private ID, sent by the server at the beginning of the Socket.IO session and used for connection state recovery
* upon reconnection
*/
export type PrivateSessionId = string;
export type Room = string;
export interface BroadcastFlags {

@@ -15,5 +23,14 @@ volatile?: boolean;

rooms: Set<Room>;
except?: Set<SocketId>;
except?: Set<Room>;
flags?: BroadcastFlags;
}
interface SessionToPersist {
sid: SocketId;
pid: PrivateSessionId;
rooms: Room[];
data: unknown;
}
export type Session = SessionToPersist & {
missedPackets: unknown[][];
};
export declare class Adapter extends EventEmitter {

@@ -95,2 +112,3 @@ readonly nsp: any;

broadcastWithAck(packet: any, opts: BroadcastOptions, clientCountCallback: (clientCount: number) => void, ack: (...args: any[]) => void): void;
private _encode;
/**

@@ -142,2 +160,23 @@ * Gets a list of sockets by sid.

serverSideEmit(packet: any[]): void;
/**
* Save the client session in order to restore it upon reconnection.
*/
persistSession(session: SessionToPersist): void;
/**
* Restore the session and find the packets that were missed by the client.
* @param pid
* @param offset
*/
restoreSession(pid: PrivateSessionId, offset: string): Promise<Session>;
}
export declare class SessionAwareAdapter extends Adapter {
readonly nsp: any;
private readonly maxDisconnectionDuration;
private sessions;
private packets;
constructor(nsp: any);
persistSession(session: SessionToPersist): void;
restoreSession(pid: PrivateSessionId, offset: string): Promise<Session>;
broadcast(packet: any, opts: BroadcastOptions): void;
}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Adapter = void 0;
exports.SessionAwareAdapter = exports.Adapter = void 0;
const events_1 = require("events");
const yeast_1 = require("./contrib/yeast");
const ws_1 = require("ws");
class Adapter extends events_1.EventEmitter {

@@ -112,7 +114,7 @@ /**

volatile: flags.volatile,
compress: flags.compress
compress: flags.compress,
};
packet.nsp = this.nsp.name;
const encodedPackets = this.encoder.encode(packet);
this.apply(opts, socket => {
const encodedPackets = this._encode(packet, packetOpts);
this.apply(opts, (socket) => {
if (typeof socket.notifyOutgoingListeners === "function") {

@@ -144,3 +146,3 @@ socket.notifyOutgoingListeners(packet);

volatile: flags.volatile,
compress: flags.compress
compress: flags.compress,
};

@@ -150,5 +152,5 @@ packet.nsp = this.nsp.name;

packet.id = this.nsp._ids++;
const encodedPackets = this.encoder.encode(packet);
const encodedPackets = this._encode(packet, packetOpts);
let clientCount = 0;
this.apply(opts, socket => {
this.apply(opts, (socket) => {
// track the total number of acknowledgements that are expected

@@ -165,2 +167,18 @@ clientCount++;

}
_encode(packet, packetOpts) {
const encodedPackets = this.encoder.encode(packet);
if (encodedPackets.length === 1 && typeof encodedPackets[0] === "string") {
// "4" being the "message" packet type in the Engine.IO protocol
const data = Buffer.from("4" + encodedPackets[0]);
// see https://github.com/websockets/ws/issues/617#issuecomment-283002469
packetOpts.wsPreEncodedFrame = ws_1.WebSocket.Sender.frame(data, {
readOnly: false,
mask: false,
rsv1: false,
opcode: 1,
fin: true,
});
}
return encodedPackets;
}
/**

@@ -173,3 +191,3 @@ * Gets a list of sockets by sid.

const sids = new Set();
this.apply({ rooms }, socket => {
this.apply({ rooms }, (socket) => {
sids.add(socket.id);

@@ -194,3 +212,3 @@ });

const sockets = [];
this.apply(opts, socket => {
this.apply(opts, (socket) => {
sockets.push(socket);

@@ -207,3 +225,3 @@ });

addSockets(opts, rooms) {
this.apply(opts, socket => {
this.apply(opts, (socket) => {
socket.join(rooms);

@@ -219,4 +237,4 @@ });

delSockets(opts, rooms) {
this.apply(opts, socket => {
rooms.forEach(room => socket.leave(room));
this.apply(opts, (socket) => {
rooms.forEach((room) => socket.leave(room));
});

@@ -231,3 +249,3 @@ }

disconnectSockets(opts, close) {
this.apply(opts, socket => {
this.apply(opts, (socket) => {
socket.disconnect(close);

@@ -270,3 +288,3 @@ });

if (this.rooms.has(room)) {
this.rooms.get(room).forEach(sid => exceptSids.add(sid));
this.rooms.get(room).forEach((sid) => exceptSids.add(sid));
}

@@ -284,3 +302,100 @@ }

}
/**
* Save the client session in order to restore it upon reconnection.
*/
persistSession(session) { }
/**
* Restore the session and find the packets that were missed by the client.
* @param pid
* @param offset
*/
restoreSession(pid, offset) {
return null;
}
}
exports.Adapter = Adapter;
class SessionAwareAdapter extends Adapter {
constructor(nsp) {
super(nsp);
this.nsp = nsp;
this.sessions = new Map();
this.packets = [];
this.maxDisconnectionDuration =
nsp.server.opts.connectionStateRecovery.maxDisconnectionDuration;
const timer = setInterval(() => {
const threshold = Date.now() - this.maxDisconnectionDuration;
this.sessions.forEach((session, sessionId) => {
const hasExpired = session.disconnectedAt < threshold;
if (hasExpired) {
this.sessions.delete(sessionId);
}
});
for (let i = this.packets.length - 1; i >= 0; i--) {
const hasExpired = this.packets[i].emittedAt < threshold;
if (hasExpired) {
this.packets.splice(0, i + 1);
break;
}
}
}, 60 * 1000);
// prevents the timer from keeping the process alive
timer.unref();
}
persistSession(session) {
session.disconnectedAt = Date.now();
this.sessions.set(session.pid, session);
}
restoreSession(pid, offset) {
const session = this.sessions.get(pid);
if (!session) {
// the session may have expired
return null;
}
const hasExpired = session.disconnectedAt + this.maxDisconnectionDuration < Date.now();
if (hasExpired) {
// the session has expired
this.sessions.delete(pid);
return null;
}
const index = this.packets.findIndex((packet) => packet.id === offset);
if (index === -1) {
// the offset may be too old
return null;
}
const missedPackets = [];
for (let i = index + 1; i < this.packets.length; i++) {
const packet = this.packets[i];
if (shouldIncludePacket(session.rooms, packet.opts)) {
missedPackets.push(packet.data);
}
}
return Promise.resolve(Object.assign(Object.assign({}, session), { missedPackets }));
}
broadcast(packet, opts) {
var _a;
const isEventPacket = packet.type === 2;
// packets with acknowledgement are not stored because the acknowledgement function cannot be serialized and
// restored on another server upon reconnection
const withoutAcknowledgement = packet.id === undefined;
const notVolatile = ((_a = opts.flags) === null || _a === void 0 ? void 0 : _a.volatile) === undefined;
if (isEventPacket && withoutAcknowledgement && notVolatile) {
const id = (0, yeast_1.yeast)();
// the offset is stored at the end of the data array, so the client knows the ID of the last packet it has
// processed (and the format is backward-compatible)
packet.data.push(id);
this.packets.push({
id,
opts,
data: packet.data,
emittedAt: Date.now(),
});
}
super.broadcast(packet, opts);
}
}
exports.SessionAwareAdapter = SessionAwareAdapter;
function shouldIncludePacket(sessionRooms, opts) {
const included = opts.rooms.size === 0 || sessionRooms.some((room) => opts.rooms.has(room));
const notExcluded = sessionRooms.every((room) => !opts.except.has(room));
return included && notExcluded;
}

19

package.json
{
"name": "socket.io-adapter",
"version": "2.4.0",
"version": "2.5.0",
"license": "MIT",

@@ -15,16 +15,21 @@ "repository": {

"description": "default socket.io in-memory adapter",
"peerDependencies": {
"ws": "*"
},
"devDependencies": {
"@types/mocha": "^10.0.1",
"@types/node": "^14.11.2",
"expect.js": "^0.3.1",
"mocha": "^8.1.3",
"mocha": "^10.2.0",
"nyc": "^15.1.0",
"prettier": "^1.19.1",
"typescript": "^4.0.3"
"prettier": "^2.8.1",
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
},
"scripts": {
"test": "npm run format:check && tsc && nyc mocha test/index.js",
"format:check": "prettier --parser typescript --check 'lib/**/*.ts' 'test/**/*.js'",
"format:fix": "prettier --parser typescript --write 'lib/**/*.ts' 'test/**/*.js'",
"test": "npm run format:check && tsc && nyc mocha --require ts-node/register test/index.ts",
"format:check": "prettier --parser typescript --check 'lib/**/*.ts' 'test/**/*.ts'",
"format:fix": "prettier --parser typescript --write 'lib/**/*.ts' 'test/**/*.ts'",
"prepack": "tsc"
}
}
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