Init. Map does not function and only working on backend at the moment.

This commit is contained in:
eetnaviation
2024-03-15 22:15:20 +02:00
commit d521b9db0c
1488 changed files with 252767 additions and 0 deletions

283
node_modules/socket.io/dist/broadcast-operator.d.ts generated vendored Normal file
View File

@ -0,0 +1,283 @@
import type { BroadcastFlags, Room, SocketId } from "socket.io-adapter";
import { Handshake } from "./socket";
import type { Adapter } from "socket.io-adapter";
import type { EventParams, EventNames, EventsMap, TypedEventBroadcaster, DecorateAcknowledgements, AllButLast, Last, FirstNonErrorArg, EventNamesWithError } from "./typed-events";
export declare class BroadcastOperator<EmitEvents extends EventsMap, SocketData> implements TypedEventBroadcaster<EmitEvents> {
private readonly adapter;
private readonly rooms;
private readonly exceptRooms;
private readonly flags;
constructor(adapter: Adapter, rooms?: Set<Room>, exceptRooms?: Set<Room>, flags?: BroadcastFlags & {
expectSingleResponse?: boolean;
});
/**
* Targets a room when emitting.
*
* @example
* // the “foo” event will be broadcast to all connected clients in the “room-101” room
* io.to("room-101").emit("foo", "bar");
*
* // with an array of rooms (a client will be notified at most once)
* io.to(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* io.to("room-101").to("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
to(room: Room | Room[]): BroadcastOperator<EmitEvents, SocketData>;
/**
* Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
*
* @example
* // disconnect all clients in the "room-101" room
* io.in("room-101").disconnectSockets();
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
in(room: Room | Room[]): BroadcastOperator<EmitEvents, SocketData>;
/**
* Excludes a room when emitting.
*
* @example
* // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
* io.except("room-101").emit("foo", "bar");
*
* // with an array of rooms
* io.except(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* io.except("room-101").except("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
except(room: Room | Room[]): BroadcastOperator<EmitEvents, SocketData>;
/**
* Sets the compress flag.
*
* @example
* io.compress(false).emit("hello");
*
* @param compress - if `true`, compresses the sending data
* @return a new BroadcastOperator instance
*/
compress(compress: boolean): BroadcastOperator<EmitEvents, SocketData>;
/**
* Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
* receive messages (because of network slowness or other issues, or because theyre connected through long polling
* and is in the middle of a request-response cycle).
*
* @example
* io.volatile.emit("hello"); // the clients may or may not receive it
*
* @return a new BroadcastOperator instance
*/
get volatile(): BroadcastOperator<EmitEvents, SocketData>;
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
*
* @example
* // the “foo” event will be broadcast to all connected clients on this node
* io.local.emit("foo", "bar");
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get local(): BroadcastOperator<EmitEvents, SocketData>;
/**
* Adds a timeout in milliseconds for the next operation
*
* @example
* io.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @param timeout
*/
timeout(timeout: number): BroadcastOperator<DecorateAcknowledgements<EmitEvents>, SocketData>;
/**
* Emits to all clients.
*
* @example
* // the “foo” event will be broadcast to all connected clients
* io.emit("foo", "bar");
*
* // the “foo” event will be broadcast to all connected clients in the “room-101” room
* io.to("room-101").emit("foo", "bar");
*
* // with an acknowledgement expected from all connected clients
* io.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @return Always true
*/
emit<Ev extends EventNames<EmitEvents>>(ev: Ev, ...args: EventParams<EmitEvents, Ev>): boolean;
/**
* Emits an event and waits for an acknowledgement from all clients.
*
* @example
* try {
* const responses = await io.timeout(1000).emitWithAck("some-event");
* console.log(responses); // one response per client
* } catch (e) {
* // some clients did not acknowledge the event in the given delay
* }
*
* @return a Promise that will be fulfilled when all clients have acknowledged the event
*/
emitWithAck<Ev extends EventNamesWithError<EmitEvents>>(ev: Ev, ...args: AllButLast<EventParams<EmitEvents, Ev>>): Promise<FirstNonErrorArg<Last<EventParams<EmitEvents, Ev>>>>;
/**
* Gets a list of clients.
*
* @deprecated this method will be removed in the next major release, please use {@link Server#serverSideEmit} or
* {@link fetchSockets} instead.
*/
allSockets(): Promise<Set<SocketId>>;
/**
* Returns the matching socket instances. This method works across a cluster of several Socket.IO servers.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // return all Socket instances
* const sockets = await io.fetchSockets();
*
* // return all Socket instances in the "room1" room
* const sockets = await io.in("room1").fetchSockets();
*
* for (const socket of sockets) {
* console.log(socket.id);
* console.log(socket.handshake);
* console.log(socket.rooms);
* console.log(socket.data);
*
* socket.emit("hello");
* socket.join("room1");
* socket.leave("room2");
* socket.disconnect();
* }
*/
fetchSockets(): Promise<RemoteSocket<EmitEvents, SocketData>[]>;
/**
* Makes the matching socket instances join the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
*
* // make all socket instances join the "room1" room
* io.socketsJoin("room1");
*
* // make all socket instances in the "room1" room join the "room2" and "room3" rooms
* io.in("room1").socketsJoin(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsJoin(room: Room | Room[]): void;
/**
* Makes the matching socket instances leave the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // make all socket instances leave the "room1" room
* io.socketsLeave("room1");
*
* // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
* io.in("room1").socketsLeave(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsLeave(room: Room | Room[]): void;
/**
* Makes the matching socket instances disconnect.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // make all socket instances disconnect (the connections might be kept alive for other namespaces)
* io.disconnectSockets();
*
* // make all socket instances in the "room1" room disconnect and close the underlying connections
* io.in("room1").disconnectSockets(true);
*
* @param close - whether to close the underlying connection
*/
disconnectSockets(close?: boolean): void;
}
/**
* Format of the data when the Socket instance exists on another Socket.IO server
*/
interface SocketDetails<SocketData> {
id: SocketId;
handshake: Handshake;
rooms: Room[];
data: SocketData;
}
/**
* Expose of subset of the attributes and methods of the Socket class
*/
export declare class RemoteSocket<EmitEvents extends EventsMap, SocketData> implements TypedEventBroadcaster<EmitEvents> {
readonly id: SocketId;
readonly handshake: Handshake;
readonly rooms: Set<Room>;
readonly data: SocketData;
private readonly operator;
constructor(adapter: Adapter, details: SocketDetails<SocketData>);
/**
* Adds a timeout in milliseconds for the next operation.
*
* @example
* const sockets = await io.fetchSockets();
*
* for (const socket of sockets) {
* if (someCondition) {
* socket.timeout(1000).emit("some-event", (err) => {
* if (err) {
* // the client did not acknowledge the event in the given delay
* }
* });
* }
* }
*
* // note: if possible, using a room instead of looping over all sockets is preferable
* io.timeout(1000).to(someConditionRoom).emit("some-event", (err, responses) => {
* // ...
* });
*
* @param timeout
*/
timeout(timeout: number): BroadcastOperator<DecorateAcknowledgements<EmitEvents>, SocketData>;
emit<Ev extends EventNames<EmitEvents>>(ev: Ev, ...args: EventParams<EmitEvents, Ev>): boolean;
/**
* Joins a room.
*
* @param {String|Array} room - room or array of rooms
*/
join(room: Room | Room[]): void;
/**
* Leaves a room.
*
* @param {String} room
*/
leave(room: Room): void;
/**
* Disconnects this client.
*
* @param {Boolean} close - if `true`, closes the underlying connection
* @return {Socket} self
*/
disconnect(close?: boolean): this;
}
export {};

437
node_modules/socket.io/dist/broadcast-operator.js generated vendored Normal file
View File

@ -0,0 +1,437 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RemoteSocket = exports.BroadcastOperator = void 0;
const socket_1 = require("./socket");
const socket_io_parser_1 = require("socket.io-parser");
class BroadcastOperator {
constructor(adapter, rooms = new Set(), exceptRooms = new Set(), flags = {}) {
this.adapter = adapter;
this.rooms = rooms;
this.exceptRooms = exceptRooms;
this.flags = flags;
}
/**
* Targets a room when emitting.
*
* @example
* // the “foo” event will be broadcast to all connected clients in the “room-101” room
* io.to("room-101").emit("foo", "bar");
*
* // with an array of rooms (a client will be notified at most once)
* io.to(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* io.to("room-101").to("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
to(room) {
const rooms = new Set(this.rooms);
if (Array.isArray(room)) {
room.forEach((r) => rooms.add(r));
}
else {
rooms.add(room);
}
return new BroadcastOperator(this.adapter, rooms, this.exceptRooms, this.flags);
}
/**
* Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
*
* @example
* // disconnect all clients in the "room-101" room
* io.in("room-101").disconnectSockets();
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
in(room) {
return this.to(room);
}
/**
* Excludes a room when emitting.
*
* @example
* // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
* io.except("room-101").emit("foo", "bar");
*
* // with an array of rooms
* io.except(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* io.except("room-101").except("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
except(room) {
const exceptRooms = new Set(this.exceptRooms);
if (Array.isArray(room)) {
room.forEach((r) => exceptRooms.add(r));
}
else {
exceptRooms.add(room);
}
return new BroadcastOperator(this.adapter, this.rooms, exceptRooms, this.flags);
}
/**
* Sets the compress flag.
*
* @example
* io.compress(false).emit("hello");
*
* @param compress - if `true`, compresses the sending data
* @return a new BroadcastOperator instance
*/
compress(compress) {
const flags = Object.assign({}, this.flags, { compress });
return new BroadcastOperator(this.adapter, this.rooms, this.exceptRooms, flags);
}
/**
* Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
* receive messages (because of network slowness or other issues, or because theyre connected through long polling
* and is in the middle of a request-response cycle).
*
* @example
* io.volatile.emit("hello"); // the clients may or may not receive it
*
* @return a new BroadcastOperator instance
*/
get volatile() {
const flags = Object.assign({}, this.flags, { volatile: true });
return new BroadcastOperator(this.adapter, this.rooms, this.exceptRooms, flags);
}
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
*
* @example
* // the “foo” event will be broadcast to all connected clients on this node
* io.local.emit("foo", "bar");
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get local() {
const flags = Object.assign({}, this.flags, { local: true });
return new BroadcastOperator(this.adapter, this.rooms, this.exceptRooms, flags);
}
/**
* Adds a timeout in milliseconds for the next operation
*
* @example
* io.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @param timeout
*/
timeout(timeout) {
const flags = Object.assign({}, this.flags, { timeout });
return new BroadcastOperator(this.adapter, this.rooms, this.exceptRooms, flags);
}
/**
* Emits to all clients.
*
* @example
* // the “foo” event will be broadcast to all connected clients
* io.emit("foo", "bar");
*
* // the “foo” event will be broadcast to all connected clients in the “room-101” room
* io.to("room-101").emit("foo", "bar");
*
* // with an acknowledgement expected from all connected clients
* io.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @return Always true
*/
emit(ev, ...args) {
if (socket_1.RESERVED_EVENTS.has(ev)) {
throw new Error(`"${String(ev)}" is a reserved event name`);
}
// set up packet object
const data = [ev, ...args];
const packet = {
type: socket_io_parser_1.PacketType.EVENT,
data: data,
};
const withAck = typeof data[data.length - 1] === "function";
if (!withAck) {
this.adapter.broadcast(packet, {
rooms: this.rooms,
except: this.exceptRooms,
flags: this.flags,
});
return true;
}
const ack = data.pop();
let timedOut = false;
let responses = [];
const timer = setTimeout(() => {
timedOut = true;
ack.apply(this, [
new Error("operation has timed out"),
this.flags.expectSingleResponse ? null : responses,
]);
}, this.flags.timeout);
let expectedServerCount = -1;
let actualServerCount = 0;
let expectedClientCount = 0;
const checkCompleteness = () => {
if (!timedOut &&
expectedServerCount === actualServerCount &&
responses.length === expectedClientCount) {
clearTimeout(timer);
ack.apply(this, [
null,
this.flags.expectSingleResponse ? responses[0] : responses,
]);
}
};
this.adapter.broadcastWithAck(packet, {
rooms: this.rooms,
except: this.exceptRooms,
flags: this.flags,
}, (clientCount) => {
// each Socket.IO server in the cluster sends the number of clients that were notified
expectedClientCount += clientCount;
actualServerCount++;
checkCompleteness();
}, (clientResponse) => {
// each client sends an acknowledgement
responses.push(clientResponse);
checkCompleteness();
});
this.adapter.serverCount().then((serverCount) => {
expectedServerCount = serverCount;
checkCompleteness();
});
return true;
}
/**
* Emits an event and waits for an acknowledgement from all clients.
*
* @example
* try {
* const responses = await io.timeout(1000).emitWithAck("some-event");
* console.log(responses); // one response per client
* } catch (e) {
* // some clients did not acknowledge the event in the given delay
* }
*
* @return a Promise that will be fulfilled when all clients have acknowledged the event
*/
emitWithAck(ev, ...args) {
return new Promise((resolve, reject) => {
args.push((err, responses) => {
if (err) {
err.responses = responses;
return reject(err);
}
else {
return resolve(responses);
}
});
this.emit(ev, ...args);
});
}
/**
* Gets a list of clients.
*
* @deprecated this method will be removed in the next major release, please use {@link Server#serverSideEmit} or
* {@link fetchSockets} instead.
*/
allSockets() {
if (!this.adapter) {
throw new Error("No adapter for this namespace, are you trying to get the list of clients of a dynamic namespace?");
}
return this.adapter.sockets(this.rooms);
}
/**
* Returns the matching socket instances. This method works across a cluster of several Socket.IO servers.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // return all Socket instances
* const sockets = await io.fetchSockets();
*
* // return all Socket instances in the "room1" room
* const sockets = await io.in("room1").fetchSockets();
*
* for (const socket of sockets) {
* console.log(socket.id);
* console.log(socket.handshake);
* console.log(socket.rooms);
* console.log(socket.data);
*
* socket.emit("hello");
* socket.join("room1");
* socket.leave("room2");
* socket.disconnect();
* }
*/
fetchSockets() {
return this.adapter
.fetchSockets({
rooms: this.rooms,
except: this.exceptRooms,
flags: this.flags,
})
.then((sockets) => {
return sockets.map((socket) => {
if (socket instanceof socket_1.Socket) {
// FIXME the TypeScript compiler complains about missing private properties
return socket;
}
else {
return new RemoteSocket(this.adapter, socket);
}
});
});
}
/**
* Makes the matching socket instances join the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
*
* // make all socket instances join the "room1" room
* io.socketsJoin("room1");
*
* // make all socket instances in the "room1" room join the "room2" and "room3" rooms
* io.in("room1").socketsJoin(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsJoin(room) {
this.adapter.addSockets({
rooms: this.rooms,
except: this.exceptRooms,
flags: this.flags,
}, Array.isArray(room) ? room : [room]);
}
/**
* Makes the matching socket instances leave the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // make all socket instances leave the "room1" room
* io.socketsLeave("room1");
*
* // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
* io.in("room1").socketsLeave(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsLeave(room) {
this.adapter.delSockets({
rooms: this.rooms,
except: this.exceptRooms,
flags: this.flags,
}, Array.isArray(room) ? room : [room]);
}
/**
* Makes the matching socket instances disconnect.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // make all socket instances disconnect (the connections might be kept alive for other namespaces)
* io.disconnectSockets();
*
* // make all socket instances in the "room1" room disconnect and close the underlying connections
* io.in("room1").disconnectSockets(true);
*
* @param close - whether to close the underlying connection
*/
disconnectSockets(close = false) {
this.adapter.disconnectSockets({
rooms: this.rooms,
except: this.exceptRooms,
flags: this.flags,
}, close);
}
}
exports.BroadcastOperator = BroadcastOperator;
/**
* Expose of subset of the attributes and methods of the Socket class
*/
class RemoteSocket {
constructor(adapter, details) {
this.id = details.id;
this.handshake = details.handshake;
this.rooms = new Set(details.rooms);
this.data = details.data;
this.operator = new BroadcastOperator(adapter, new Set([this.id]), new Set(), {
expectSingleResponse: true, // so that remoteSocket.emit() with acknowledgement behaves like socket.emit()
});
}
/**
* Adds a timeout in milliseconds for the next operation.
*
* @example
* const sockets = await io.fetchSockets();
*
* for (const socket of sockets) {
* if (someCondition) {
* socket.timeout(1000).emit("some-event", (err) => {
* if (err) {
* // the client did not acknowledge the event in the given delay
* }
* });
* }
* }
*
* // note: if possible, using a room instead of looping over all sockets is preferable
* io.timeout(1000).to(someConditionRoom).emit("some-event", (err, responses) => {
* // ...
* });
*
* @param timeout
*/
timeout(timeout) {
return this.operator.timeout(timeout);
}
emit(ev, ...args) {
return this.operator.emit(ev, ...args);
}
/**
* Joins a room.
*
* @param {String|Array} room - room or array of rooms
*/
join(room) {
return this.operator.socketsJoin(room);
}
/**
* Leaves a room.
*
* @param {String} room
*/
leave(room) {
return this.operator.socketsLeave(room);
}
/**
* Disconnects this client.
*
* @param {Boolean} close - if `true`, closes the underlying connection
* @return {Socket} self
*/
disconnect(close = false) {
this.operator.disconnectSockets(close);
return this;
}
}
exports.RemoteSocket = RemoteSocket;

120
node_modules/socket.io/dist/client.d.ts generated vendored Normal file
View File

@ -0,0 +1,120 @@
/// <reference types="node" />
import { Packet } from "socket.io-parser";
import type { IncomingMessage } from "http";
import type { Server } from "./index";
import type { EventsMap } from "./typed-events";
import type { Socket } from "./socket";
import type { Socket as RawSocket } from "engine.io";
interface WriteOptions {
compress?: boolean;
volatile?: boolean;
preEncoded?: boolean;
wsPreEncoded?: string;
}
export declare class Client<ListenEvents extends EventsMap, EmitEvents extends EventsMap, ServerSideEvents extends EventsMap, SocketData = any> {
readonly conn: RawSocket;
private readonly id;
private readonly server;
private readonly encoder;
private readonly decoder;
private sockets;
private nsps;
private connectTimeout?;
/**
* Client constructor.
*
* @param server instance
* @param conn
* @package
*/
constructor(server: Server<ListenEvents, EmitEvents, ServerSideEvents, SocketData>, conn: any);
/**
* @return the reference to the request that originated the Engine.IO connection
*
* @public
*/
get request(): IncomingMessage;
/**
* Sets up event listeners.
*
* @private
*/
private setup;
/**
* Connects a client to a namespace.
*
* @param {String} name - the namespace
* @param {Object} auth - the auth parameters
* @private
*/
private connect;
/**
* Connects a client to a namespace.
*
* @param name - the namespace
* @param {Object} auth - the auth parameters
*
* @private
*/
private doConnect;
/**
* Disconnects from all namespaces and closes transport.
*
* @private
*/
_disconnect(): void;
/**
* Removes a socket. Called by each `Socket`.
*
* @private
*/
_remove(socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>): void;
/**
* Closes the underlying connection.
*
* @private
*/
private close;
/**
* Writes a packet to the transport.
*
* @param {Object} packet object
* @param {Object} opts
* @private
*/
_packet(packet: Packet | any[], opts?: WriteOptions): void;
private writeToEngine;
/**
* Called with incoming transport data.
*
* @private
*/
private ondata;
/**
* Called when parser fully decodes a packet.
*
* @private
*/
private ondecoded;
/**
* Handles an error.
*
* @param {Object} err object
* @private
*/
private onerror;
/**
* Called upon transport close.
*
* @param reason
* @param description
* @private
*/
private onclose;
/**
* Cleans up event listeners.
* @private
*/
private destroy;
}
export {};

268
node_modules/socket.io/dist/client.js generated vendored Normal file
View File

@ -0,0 +1,268 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Client = void 0;
const socket_io_parser_1 = require("socket.io-parser");
const debugModule = require("debug");
const url = require("url");
const debug = debugModule("socket.io:client");
class Client {
/**
* Client constructor.
*
* @param server instance
* @param conn
* @package
*/
constructor(server, conn) {
this.sockets = new Map();
this.nsps = new Map();
this.server = server;
this.conn = conn;
this.encoder = server.encoder;
this.decoder = new server._parser.Decoder();
this.id = conn.id;
this.setup();
}
/**
* @return the reference to the request that originated the Engine.IO connection
*
* @public
*/
get request() {
return this.conn.request;
}
/**
* Sets up event listeners.
*
* @private
*/
setup() {
this.onclose = this.onclose.bind(this);
this.ondata = this.ondata.bind(this);
this.onerror = this.onerror.bind(this);
this.ondecoded = this.ondecoded.bind(this);
// @ts-ignore
this.decoder.on("decoded", this.ondecoded);
this.conn.on("data", this.ondata);
this.conn.on("error", this.onerror);
this.conn.on("close", this.onclose);
this.connectTimeout = setTimeout(() => {
if (this.nsps.size === 0) {
debug("no namespace joined yet, close the client");
this.close();
}
else {
debug("the client has already joined a namespace, nothing to do");
}
}, this.server._connectTimeout);
}
/**
* Connects a client to a namespace.
*
* @param {String} name - the namespace
* @param {Object} auth - the auth parameters
* @private
*/
connect(name, auth = {}) {
if (this.server._nsps.has(name)) {
debug("connecting to namespace %s", name);
return this.doConnect(name, auth);
}
this.server._checkNamespace(name, auth, (dynamicNspName) => {
if (dynamicNspName) {
this.doConnect(name, auth);
}
else {
debug("creation of namespace %s was denied", name);
this._packet({
type: socket_io_parser_1.PacketType.CONNECT_ERROR,
nsp: name,
data: {
message: "Invalid namespace",
},
});
}
});
}
/**
* Connects a client to a namespace.
*
* @param name - the namespace
* @param {Object} auth - the auth parameters
*
* @private
*/
doConnect(name, auth) {
const nsp = this.server.of(name);
nsp._add(this, auth, (socket) => {
this.sockets.set(socket.id, socket);
this.nsps.set(nsp.name, socket);
if (this.connectTimeout) {
clearTimeout(this.connectTimeout);
this.connectTimeout = undefined;
}
});
}
/**
* Disconnects from all namespaces and closes transport.
*
* @private
*/
_disconnect() {
for (const socket of this.sockets.values()) {
socket.disconnect();
}
this.sockets.clear();
this.close();
}
/**
* Removes a socket. Called by each `Socket`.
*
* @private
*/
_remove(socket) {
if (this.sockets.has(socket.id)) {
const nsp = this.sockets.get(socket.id).nsp.name;
this.sockets.delete(socket.id);
this.nsps.delete(nsp);
}
else {
debug("ignoring remove for %s", socket.id);
}
}
/**
* Closes the underlying connection.
*
* @private
*/
close() {
if ("open" === this.conn.readyState) {
debug("forcing transport close");
this.conn.close();
this.onclose("forced server close");
}
}
/**
* Writes a packet to the transport.
*
* @param {Object} packet object
* @param {Object} opts
* @private
*/
_packet(packet, opts = {}) {
if (this.conn.readyState !== "open") {
debug("ignoring packet write %j", packet);
return;
}
const encodedPackets = opts.preEncoded
? packet // previous versions of the adapter incorrectly used socket.packet() instead of writeToEngine()
: this.encoder.encode(packet);
this.writeToEngine(encodedPackets, opts);
}
writeToEngine(encodedPackets, opts) {
if (opts.volatile && !this.conn.transport.writable) {
debug("volatile packet is discarded since the transport is not currently writable");
return;
}
const packets = Array.isArray(encodedPackets)
? encodedPackets
: [encodedPackets];
for (const encodedPacket of packets) {
this.conn.write(encodedPacket, opts);
}
}
/**
* Called with incoming transport data.
*
* @private
*/
ondata(data) {
// try/catch is needed for protocol violations (GH-1880)
try {
this.decoder.add(data);
}
catch (e) {
debug("invalid packet format");
this.onerror(e);
}
}
/**
* Called when parser fully decodes a packet.
*
* @private
*/
ondecoded(packet) {
let namespace;
let authPayload;
if (this.conn.protocol === 3) {
const parsed = url.parse(packet.nsp, true);
namespace = parsed.pathname;
authPayload = parsed.query;
}
else {
namespace = packet.nsp;
authPayload = packet.data;
}
const socket = this.nsps.get(namespace);
if (!socket && packet.type === socket_io_parser_1.PacketType.CONNECT) {
this.connect(namespace, authPayload);
}
else if (socket &&
packet.type !== socket_io_parser_1.PacketType.CONNECT &&
packet.type !== socket_io_parser_1.PacketType.CONNECT_ERROR) {
process.nextTick(function () {
socket._onpacket(packet);
});
}
else {
debug("invalid state (packet type: %s)", packet.type);
this.close();
}
}
/**
* Handles an error.
*
* @param {Object} err object
* @private
*/
onerror(err) {
for (const socket of this.sockets.values()) {
socket._onerror(err);
}
this.conn.close();
}
/**
* Called upon transport close.
*
* @param reason
* @param description
* @private
*/
onclose(reason, description) {
debug("client close with reason %s", reason);
// ignore a potential subsequent `close` event
this.destroy();
// `nsps` and `sockets` are cleaned up seamlessly
for (const socket of this.sockets.values()) {
socket._onclose(reason, description);
}
this.sockets.clear();
this.decoder.destroy(); // clean up decoder
}
/**
* Cleans up event listeners.
* @private
*/
destroy() {
this.conn.removeListener("data", this.ondata);
this.conn.removeListener("error", this.onerror);
this.conn.removeListener("close", this.onclose);
// @ts-ignore
this.decoder.removeListener("decoded", this.ondecoded);
if (this.connectTimeout) {
clearTimeout(this.connectTimeout);
this.connectTimeout = undefined;
}
}
}
exports.Client = Client;

526
node_modules/socket.io/dist/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,526 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import http = require("http");
import type { Server as HTTPSServer } from "https";
import type { Http2SecureServer, Http2Server } from "http2";
import type { ServerOptions as EngineOptions, AttachOptions, BaseServer } from "engine.io";
import { ExtendedError, Namespace, ServerReservedEventsMap } from "./namespace";
import { Adapter, Room, SocketId } from "socket.io-adapter";
import * as parser from "socket.io-parser";
import type { Encoder } from "socket.io-parser";
import { Socket, DisconnectReason } from "./socket";
import type { BroadcastOperator, RemoteSocket } from "./broadcast-operator";
import { EventsMap, DefaultEventsMap, EventParams, StrictEventEmitter, EventNames, DecorateAcknowledgementsWithTimeoutAndMultipleResponses, AllButLast, Last, RemoveAcknowledgements, EventNamesWithAck, FirstNonErrorArg } from "./typed-events";
declare type ParentNspNameMatchFn = (name: string, auth: {
[key: string]: any;
}, fn: (err: Error | null, success: boolean) => void) => void;
declare type AdapterConstructor = typeof Adapter | ((nsp: Namespace) => Adapter);
declare type TServerInstance = http.Server | HTTPSServer | Http2SecureServer | Http2Server;
interface ServerOptions extends EngineOptions, AttachOptions {
/**
* name of the path to capture
* @default "/socket.io"
*/
path: string;
/**
* whether to serve the client files
* @default true
*/
serveClient: boolean;
/**
* the adapter to use
* @default the in-memory adapter (https://github.com/socketio/socket.io-adapter)
*/
adapter: AdapterConstructor;
/**
* the parser to use
* @default the default parser (https://github.com/socketio/socket.io-parser)
*/
parser: any;
/**
* how many ms before a client without namespace is closed
* @default 45000
*/
connectTimeout: number;
/**
* Whether to enable the recovery of connection state when a client temporarily disconnects.
*
* The connection state includes the missed packets, the rooms the socket was in and the `data` attribute.
*/
connectionStateRecovery: {
/**
* The backup duration of the sessions and the packets.
*
* @default 120000 (2 minutes)
*/
maxDisconnectionDuration?: number;
/**
* Whether to skip middlewares upon successful connection state recovery.
*
* @default true
*/
skipMiddlewares?: boolean;
};
/**
* Whether to remove child namespaces that have no sockets connected to them
* @default false
*/
cleanupEmptyChildNamespaces: boolean;
}
/**
* Represents a Socket.IO server.
*
* @example
* import { Server } from "socket.io";
*
* const io = new Server();
*
* io.on("connection", (socket) => {
* console.log(`socket ${socket.id} connected`);
*
* // send an event to the client
* socket.emit("foo", "bar");
*
* socket.on("foobar", () => {
* // an event was received from the client
* });
*
* // upon disconnection
* socket.on("disconnect", (reason) => {
* console.log(`socket ${socket.id} disconnected due to ${reason}`);
* });
* });
*
* io.listen(3000);
*/
export declare class Server<ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, ServerSideEvents extends EventsMap = DefaultEventsMap, SocketData = any> extends StrictEventEmitter<ServerSideEvents, RemoveAcknowledgements<EmitEvents>, ServerReservedEventsMap<ListenEvents, EmitEvents, ServerSideEvents, SocketData>> {
readonly sockets: Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>;
/**
* A reference to the underlying Engine.IO server.
*
* @example
* const clientsCount = io.engine.clientsCount;
*
*/
engine: BaseServer;
/** @private */
readonly _parser: typeof parser;
/** @private */
readonly encoder: Encoder;
/**
* @private
*/
_nsps: Map<string, Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>>;
private parentNsps;
/**
* A subset of the {@link parentNsps} map, only containing {@link ParentNamespace} which are based on a regular
* expression.
*
* @private
*/
private parentNamespacesFromRegExp;
private _adapter?;
private _serveClient;
private readonly opts;
private eio;
private _path;
private clientPathRegex;
/**
* @private
*/
_connectTimeout: number;
private httpServer;
private _corsMiddleware;
/**
* Server constructor.
*
* @param srv http server, port, or options
* @param [opts]
*/
constructor(opts?: Partial<ServerOptions>);
constructor(srv?: TServerInstance | number, opts?: Partial<ServerOptions>);
constructor(srv: undefined | Partial<ServerOptions> | TServerInstance | number, opts?: Partial<ServerOptions>);
get _opts(): Partial<ServerOptions>;
/**
* Sets/gets whether client code is being served.
*
* @param v - whether to serve client code
* @return self when setting or value when getting
*/
serveClient(v: boolean): this;
serveClient(): boolean;
serveClient(v?: boolean): this | boolean;
/**
* Executes the middleware for an incoming namespace not already created on the server.
*
* @param name - name of incoming namespace
* @param auth - the auth parameters
* @param fn - callback
*
* @private
*/
_checkNamespace(name: string, auth: {
[key: string]: any;
}, fn: (nsp: Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData> | false) => void): void;
/**
* Sets the client serving path.
*
* @param {String} v pathname
* @return {Server|String} self when setting or value when getting
*/
path(v: string): this;
path(): string;
path(v?: string): this | string;
/**
* Set the delay after which a client without namespace is closed
* @param v
*/
connectTimeout(v: number): this;
connectTimeout(): number;
connectTimeout(v?: number): this | number;
/**
* Sets the adapter for rooms.
*
* @param v pathname
* @return self when setting or value when getting
*/
adapter(): AdapterConstructor | undefined;
adapter(v: AdapterConstructor): this;
/**
* Attaches socket.io to a server or port.
*
* @param srv - server or port
* @param opts - options passed to engine.io
* @return self
*/
listen(srv: TServerInstance | number, opts?: Partial<ServerOptions>): this;
/**
* Attaches socket.io to a server or port.
*
* @param srv - server or port
* @param opts - options passed to engine.io
* @return self
*/
attach(srv: TServerInstance | number, opts?: Partial<ServerOptions>): this;
attachApp(app: any, opts?: Partial<ServerOptions>): void;
/**
* Initialize engine
*
* @param srv - the server to attach to
* @param opts - options passed to engine.io
* @private
*/
private initEngine;
/**
* Attaches the static file serving.
*
* @param srv http server
* @private
*/
private attachServe;
/**
* Handles a request serving of client source and map
*
* @param req
* @param res
* @private
*/
private serve;
/**
* @param filename
* @param req
* @param res
* @private
*/
private static sendFile;
/**
* Binds socket.io to an engine.io instance.
*
* @param engine engine.io (or compatible) server
* @return self
*/
bind(engine: BaseServer): this;
/**
* Called with each incoming transport connection.
*
* @param {engine.Socket} conn
* @return self
* @private
*/
private onconnection;
/**
* Looks up a namespace.
*
* @example
* // with a simple string
* const myNamespace = io.of("/my-namespace");
*
* // with a regex
* const dynamicNsp = io.of(/^\/dynamic-\d+$/).on("connection", (socket) => {
* const namespace = socket.nsp; // newNamespace.name === "/dynamic-101"
*
* // broadcast to all clients in the given sub-namespace
* namespace.emit("hello");
* });
*
* @param name - nsp name
* @param fn optional, nsp `connection` ev handler
*/
of(name: string | RegExp | ParentNspNameMatchFn, fn?: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>) => void): Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>;
/**
* Closes server connection
*
* @param [fn] optional, called as `fn([err])` on error OR all conns closed
*/
close(fn?: (err?: Error) => void): void;
/**
* Registers a middleware, which is a function that gets executed for every incoming {@link Socket}.
*
* @example
* io.use((socket, next) => {
* // ...
* next();
* });
*
* @param fn - the middleware function
*/
use(fn: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>, next: (err?: ExtendedError) => void) => void): this;
/**
* Targets a room when emitting.
*
* @example
* // the “foo” event will be broadcast to all connected clients in the “room-101” room
* io.to("room-101").emit("foo", "bar");
*
* // with an array of rooms (a client will be notified at most once)
* io.to(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* io.to("room-101").to("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
to(room: Room | Room[]): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
*
* @example
* // disconnect all clients in the "room-101" room
* io.in("room-101").disconnectSockets();
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
in(room: Room | Room[]): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Excludes a room when emitting.
*
* @example
* // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
* io.except("room-101").emit("foo", "bar");
*
* // with an array of rooms
* io.except(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* io.except("room-101").except("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
except(room: Room | Room[]): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Sends a `message` event to all clients.
*
* This method mimics the WebSocket.send() method.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
*
* @example
* io.send("hello");
*
* // this is equivalent to
* io.emit("message", "hello");
*
* @return self
*/
send(...args: EventParams<EmitEvents, "message">): this;
/**
* Sends a `message` event to all clients. Alias of {@link send}.
*
* @return self
*/
write(...args: EventParams<EmitEvents, "message">): this;
/**
* Sends a message to the other Socket.IO servers of the cluster.
*
* @example
* io.serverSideEmit("hello", "world");
*
* io.on("hello", (arg1) => {
* console.log(arg1); // prints "world"
* });
*
* // acknowledgements (without binary content) are supported too:
* io.serverSideEmit("ping", (err, responses) => {
* if (err) {
* // some servers did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per server (except the current one)
* }
* });
*
* io.on("ping", (cb) => {
* cb("pong");
* });
*
* @param ev - the event name
* @param args - an array of arguments, which may include an acknowledgement callback at the end
*/
serverSideEmit<Ev extends EventNames<ServerSideEvents>>(ev: Ev, ...args: EventParams<DecorateAcknowledgementsWithTimeoutAndMultipleResponses<ServerSideEvents>, Ev>): boolean;
/**
* Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.
*
* @example
* try {
* const responses = await io.serverSideEmitWithAck("ping");
* console.log(responses); // one response per server (except the current one)
* } catch (e) {
* // some servers did not acknowledge the event in the given delay
* }
*
* @param ev - the event name
* @param args - an array of arguments
*
* @return a Promise that will be fulfilled when all servers have acknowledged the event
*/
serverSideEmitWithAck<Ev extends EventNamesWithAck<ServerSideEvents>>(ev: Ev, ...args: AllButLast<EventParams<ServerSideEvents, Ev>>): Promise<FirstNonErrorArg<Last<EventParams<ServerSideEvents, Ev>>>[]>;
/**
* Gets a list of socket ids.
*
* @deprecated this method will be removed in the next major release, please use {@link Server#serverSideEmit} or
* {@link Server#fetchSockets} instead.
*/
allSockets(): Promise<Set<SocketId>>;
/**
* Sets the compress flag.
*
* @example
* io.compress(false).emit("hello");
*
* @param compress - if `true`, compresses the sending data
* @return a new {@link BroadcastOperator} instance for chaining
*/
compress(compress: boolean): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
* receive messages (because of network slowness or other issues, or because theyre connected through long polling
* and is in the middle of a request-response cycle).
*
* @example
* io.volatile.emit("hello"); // the clients may or may not receive it
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get volatile(): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
*
* @example
* // the “foo” event will be broadcast to all connected clients on this node
* io.local.emit("foo", "bar");
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get local(): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Adds a timeout in milliseconds for the next operation.
*
* @example
* io.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @param timeout
*/
timeout(timeout: number): BroadcastOperator<import("./typed-events").DecorateAcknowledgements<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>>, SocketData>;
/**
* Returns the matching socket instances.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // return all Socket instances
* const sockets = await io.fetchSockets();
*
* // return all Socket instances in the "room1" room
* const sockets = await io.in("room1").fetchSockets();
*
* for (const socket of sockets) {
* console.log(socket.id);
* console.log(socket.handshake);
* console.log(socket.rooms);
* console.log(socket.data);
*
* socket.emit("hello");
* socket.join("room1");
* socket.leave("room2");
* socket.disconnect();
* }
*/
fetchSockets(): Promise<RemoteSocket<EmitEvents, SocketData>[]>;
/**
* Makes the matching socket instances join the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
*
* // make all socket instances join the "room1" room
* io.socketsJoin("room1");
*
* // make all socket instances in the "room1" room join the "room2" and "room3" rooms
* io.in("room1").socketsJoin(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsJoin(room: Room | Room[]): void;
/**
* Makes the matching socket instances leave the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // make all socket instances leave the "room1" room
* io.socketsLeave("room1");
*
* // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
* io.in("room1").socketsLeave(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsLeave(room: Room | Room[]): void;
/**
* Makes the matching socket instances disconnect.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // make all socket instances disconnect (the connections might be kept alive for other namespaces)
* io.disconnectSockets();
*
* // make all socket instances in the "room1" room disconnect and close the underlying connections
* io.in("room1").disconnectSockets(true);
*
* @param close - whether to close the underlying connection
*/
disconnectSockets(close?: boolean): void;
}
export { Socket, DisconnectReason, ServerOptions, Namespace, BroadcastOperator, RemoteSocket, };
export { Event } from "./socket";

803
node_modules/socket.io/dist/index.js generated vendored Normal file
View File

@ -0,0 +1,803 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Namespace = exports.Socket = exports.Server = void 0;
const http = require("http");
const fs_1 = require("fs");
const zlib_1 = require("zlib");
const accepts = require("accepts");
const stream_1 = require("stream");
const path = require("path");
const engine_io_1 = require("engine.io");
const client_1 = require("./client");
const events_1 = require("events");
const namespace_1 = require("./namespace");
Object.defineProperty(exports, "Namespace", { enumerable: true, get: function () { return namespace_1.Namespace; } });
const parent_namespace_1 = require("./parent-namespace");
const socket_io_adapter_1 = require("socket.io-adapter");
const parser = __importStar(require("socket.io-parser"));
const debug_1 = __importDefault(require("debug"));
const socket_1 = require("./socket");
Object.defineProperty(exports, "Socket", { enumerable: true, get: function () { return socket_1.Socket; } });
const typed_events_1 = require("./typed-events");
const uws_1 = require("./uws");
const cors_1 = __importDefault(require("cors"));
const debug = (0, debug_1.default)("socket.io:server");
const clientVersion = require("../package.json").version;
const dotMapRegex = /\.map/;
/**
* Represents a Socket.IO server.
*
* @example
* import { Server } from "socket.io";
*
* const io = new Server();
*
* io.on("connection", (socket) => {
* console.log(`socket ${socket.id} connected`);
*
* // send an event to the client
* socket.emit("foo", "bar");
*
* socket.on("foobar", () => {
* // an event was received from the client
* });
*
* // upon disconnection
* socket.on("disconnect", (reason) => {
* console.log(`socket ${socket.id} disconnected due to ${reason}`);
* });
* });
*
* io.listen(3000);
*/
class Server extends typed_events_1.StrictEventEmitter {
constructor(srv, opts = {}) {
super();
/**
* @private
*/
this._nsps = new Map();
this.parentNsps = new Map();
/**
* A subset of the {@link parentNsps} map, only containing {@link ParentNamespace} which are based on a regular
* expression.
*
* @private
*/
this.parentNamespacesFromRegExp = new Map();
if ("object" === typeof srv &&
srv instanceof Object &&
!srv.listen) {
opts = srv;
srv = undefined;
}
this.path(opts.path || "/socket.io");
this.connectTimeout(opts.connectTimeout || 45000);
this.serveClient(false !== opts.serveClient);
this._parser = opts.parser || parser;
this.encoder = new this._parser.Encoder();
this.opts = opts;
if (opts.connectionStateRecovery) {
opts.connectionStateRecovery = Object.assign({
maxDisconnectionDuration: 2 * 60 * 1000,
skipMiddlewares: true,
}, opts.connectionStateRecovery);
this.adapter(opts.adapter || socket_io_adapter_1.SessionAwareAdapter);
}
else {
this.adapter(opts.adapter || socket_io_adapter_1.Adapter);
}
opts.cleanupEmptyChildNamespaces = !!opts.cleanupEmptyChildNamespaces;
this.sockets = this.of("/");
if (srv || typeof srv == "number")
this.attach(srv);
if (this.opts.cors) {
this._corsMiddleware = (0, cors_1.default)(this.opts.cors);
}
}
get _opts() {
return this.opts;
}
serveClient(v) {
if (!arguments.length)
return this._serveClient;
this._serveClient = v;
return this;
}
/**
* Executes the middleware for an incoming namespace not already created on the server.
*
* @param name - name of incoming namespace
* @param auth - the auth parameters
* @param fn - callback
*
* @private
*/
_checkNamespace(name, auth, fn) {
if (this.parentNsps.size === 0)
return fn(false);
const keysIterator = this.parentNsps.keys();
const run = () => {
const nextFn = keysIterator.next();
if (nextFn.done) {
return fn(false);
}
nextFn.value(name, auth, (err, allow) => {
if (err || !allow) {
return run();
}
if (this._nsps.has(name)) {
// the namespace was created in the meantime
debug("dynamic namespace %s already exists", name);
return fn(this._nsps.get(name));
}
const namespace = this.parentNsps.get(nextFn.value).createChild(name);
debug("dynamic namespace %s was created", name);
fn(namespace);
});
};
run();
}
path(v) {
if (!arguments.length)
return this._path;
this._path = v.replace(/\/$/, "");
const escapedPath = this._path.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
this.clientPathRegex = new RegExp("^" +
escapedPath +
"/socket\\.io(\\.msgpack|\\.esm)?(\\.min)?\\.js(\\.map)?(?:\\?|$)");
return this;
}
connectTimeout(v) {
if (v === undefined)
return this._connectTimeout;
this._connectTimeout = v;
return this;
}
adapter(v) {
if (!arguments.length)
return this._adapter;
this._adapter = v;
for (const nsp of this._nsps.values()) {
nsp._initAdapter();
}
return this;
}
/**
* Attaches socket.io to a server or port.
*
* @param srv - server or port
* @param opts - options passed to engine.io
* @return self
*/
listen(srv, opts = {}) {
return this.attach(srv, opts);
}
/**
* Attaches socket.io to a server or port.
*
* @param srv - server or port
* @param opts - options passed to engine.io
* @return self
*/
attach(srv, opts = {}) {
if ("function" == typeof srv) {
const msg = "You are trying to attach socket.io to an express " +
"request handler function. Please pass a http.Server instance.";
throw new Error(msg);
}
// handle a port as a string
if (Number(srv) == srv) {
srv = Number(srv);
}
if ("number" == typeof srv) {
debug("creating http server and binding to %d", srv);
const port = srv;
srv = http.createServer((req, res) => {
res.writeHead(404);
res.end();
});
srv.listen(port);
}
// merge the options passed to the Socket.IO server
Object.assign(opts, this.opts);
// set engine.io path to `/socket.io`
opts.path = opts.path || this._path;
this.initEngine(srv, opts);
return this;
}
attachApp(app /*: TemplatedApp */, opts = {}) {
// merge the options passed to the Socket.IO server
Object.assign(opts, this.opts);
// set engine.io path to `/socket.io`
opts.path = opts.path || this._path;
// initialize engine
debug("creating uWebSockets.js-based engine with opts %j", opts);
const engine = new engine_io_1.uServer(opts);
engine.attach(app, opts);
// bind to engine events
this.bind(engine);
if (this._serveClient) {
// attach static file serving
app.get(`${this._path}/*`, (res, req) => {
if (!this.clientPathRegex.test(req.getUrl())) {
req.setYield(true);
return;
}
const filename = req
.getUrl()
.replace(this._path, "")
.replace(/\?.*$/, "")
.replace(/^\//, "");
const isMap = dotMapRegex.test(filename);
const type = isMap ? "map" : "source";
// Per the standard, ETags must be quoted:
// https://tools.ietf.org/html/rfc7232#section-2.3
const expectedEtag = '"' + clientVersion + '"';
const weakEtag = "W/" + expectedEtag;
const etag = req.getHeader("if-none-match");
if (etag) {
if (expectedEtag === etag || weakEtag === etag) {
debug("serve client %s 304", type);
res.writeStatus("304 Not Modified");
res.end();
return;
}
}
debug("serve client %s", type);
res.writeHeader("cache-control", "public, max-age=0");
res.writeHeader("content-type", "application/" + (isMap ? "json" : "javascript") + "; charset=utf-8");
res.writeHeader("etag", expectedEtag);
const filepath = path.join(__dirname, "../client-dist/", filename);
(0, uws_1.serveFile)(res, filepath);
});
}
(0, uws_1.patchAdapter)(app);
}
/**
* Initialize engine
*
* @param srv - the server to attach to
* @param opts - options passed to engine.io
* @private
*/
initEngine(srv, opts) {
// initialize engine
debug("creating engine.io instance with opts %j", opts);
this.eio = (0, engine_io_1.attach)(srv, opts);
// attach static file serving
if (this._serveClient)
this.attachServe(srv);
// Export http server
this.httpServer = srv;
// bind to engine events
this.bind(this.eio);
}
/**
* Attaches the static file serving.
*
* @param srv http server
* @private
*/
attachServe(srv) {
debug("attaching client serving req handler");
const evs = srv.listeners("request").slice(0);
srv.removeAllListeners("request");
srv.on("request", (req, res) => {
if (this.clientPathRegex.test(req.url)) {
if (this._corsMiddleware) {
this._corsMiddleware(req, res, () => {
this.serve(req, res);
});
}
else {
this.serve(req, res);
}
}
else {
for (let i = 0; i < evs.length; i++) {
evs[i].call(srv, req, res);
}
}
});
}
/**
* Handles a request serving of client source and map
*
* @param req
* @param res
* @private
*/
serve(req, res) {
const filename = req.url.replace(this._path, "").replace(/\?.*$/, "");
const isMap = dotMapRegex.test(filename);
const type = isMap ? "map" : "source";
// Per the standard, ETags must be quoted:
// https://tools.ietf.org/html/rfc7232#section-2.3
const expectedEtag = '"' + clientVersion + '"';
const weakEtag = "W/" + expectedEtag;
const etag = req.headers["if-none-match"];
if (etag) {
if (expectedEtag === etag || weakEtag === etag) {
debug("serve client %s 304", type);
res.writeHead(304);
res.end();
return;
}
}
debug("serve client %s", type);
res.setHeader("Cache-Control", "public, max-age=0");
res.setHeader("Content-Type", "application/" + (isMap ? "json" : "javascript") + "; charset=utf-8");
res.setHeader("ETag", expectedEtag);
Server.sendFile(filename, req, res);
}
/**
* @param filename
* @param req
* @param res
* @private
*/
static sendFile(filename, req, res) {
const readStream = (0, fs_1.createReadStream)(path.join(__dirname, "../client-dist/", filename));
const encoding = accepts(req).encodings(["br", "gzip", "deflate"]);
const onError = (err) => {
if (err) {
res.end();
}
};
switch (encoding) {
case "br":
res.writeHead(200, { "content-encoding": "br" });
(0, stream_1.pipeline)(readStream, (0, zlib_1.createBrotliCompress)(), res, onError);
break;
case "gzip":
res.writeHead(200, { "content-encoding": "gzip" });
(0, stream_1.pipeline)(readStream, (0, zlib_1.createGzip)(), res, onError);
break;
case "deflate":
res.writeHead(200, { "content-encoding": "deflate" });
(0, stream_1.pipeline)(readStream, (0, zlib_1.createDeflate)(), res, onError);
break;
default:
res.writeHead(200);
(0, stream_1.pipeline)(readStream, res, onError);
}
}
/**
* Binds socket.io to an engine.io instance.
*
* @param engine engine.io (or compatible) server
* @return self
*/
bind(engine) {
this.engine = engine;
this.engine.on("connection", this.onconnection.bind(this));
return this;
}
/**
* Called with each incoming transport connection.
*
* @param {engine.Socket} conn
* @return self
* @private
*/
onconnection(conn) {
debug("incoming connection with id %s", conn.id);
const client = new client_1.Client(this, conn);
if (conn.protocol === 3) {
// @ts-ignore
client.connect("/");
}
return this;
}
/**
* Looks up a namespace.
*
* @example
* // with a simple string
* const myNamespace = io.of("/my-namespace");
*
* // with a regex
* const dynamicNsp = io.of(/^\/dynamic-\d+$/).on("connection", (socket) => {
* const namespace = socket.nsp; // newNamespace.name === "/dynamic-101"
*
* // broadcast to all clients in the given sub-namespace
* namespace.emit("hello");
* });
*
* @param name - nsp name
* @param fn optional, nsp `connection` ev handler
*/
of(name, fn) {
if (typeof name === "function" || name instanceof RegExp) {
const parentNsp = new parent_namespace_1.ParentNamespace(this);
debug("initializing parent namespace %s", parentNsp.name);
if (typeof name === "function") {
this.parentNsps.set(name, parentNsp);
}
else {
this.parentNsps.set((nsp, conn, next) => next(null, name.test(nsp)), parentNsp);
this.parentNamespacesFromRegExp.set(name, parentNsp);
}
if (fn) {
// @ts-ignore
parentNsp.on("connect", fn);
}
return parentNsp;
}
if (String(name)[0] !== "/")
name = "/" + name;
let nsp = this._nsps.get(name);
if (!nsp) {
for (const [regex, parentNamespace] of this.parentNamespacesFromRegExp) {
if (regex.test(name)) {
debug("attaching namespace %s to parent namespace %s", name, regex);
return parentNamespace.createChild(name);
}
}
debug("initializing namespace %s", name);
nsp = new namespace_1.Namespace(this, name);
this._nsps.set(name, nsp);
if (name !== "/") {
// @ts-ignore
this.sockets.emitReserved("new_namespace", nsp);
}
}
if (fn)
nsp.on("connect", fn);
return nsp;
}
/**
* Closes server connection
*
* @param [fn] optional, called as `fn([err])` on error OR all conns closed
*/
close(fn) {
this._nsps.forEach((nsp) => {
nsp.sockets.forEach((socket) => {
socket._onclose("server shutting down");
});
nsp.adapter.close();
});
this.engine.close();
// restore the Adapter prototype, when the Socket.IO server was attached to a uWebSockets.js server
(0, uws_1.restoreAdapter)();
if (this.httpServer) {
this.httpServer.close(fn);
}
else {
fn && fn();
}
}
/**
* Registers a middleware, which is a function that gets executed for every incoming {@link Socket}.
*
* @example
* io.use((socket, next) => {
* // ...
* next();
* });
*
* @param fn - the middleware function
*/
use(fn) {
this.sockets.use(fn);
return this;
}
/**
* Targets a room when emitting.
*
* @example
* // the “foo” event will be broadcast to all connected clients in the “room-101” room
* io.to("room-101").emit("foo", "bar");
*
* // with an array of rooms (a client will be notified at most once)
* io.to(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* io.to("room-101").to("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
to(room) {
return this.sockets.to(room);
}
/**
* Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
*
* @example
* // disconnect all clients in the "room-101" room
* io.in("room-101").disconnectSockets();
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
in(room) {
return this.sockets.in(room);
}
/**
* Excludes a room when emitting.
*
* @example
* // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
* io.except("room-101").emit("foo", "bar");
*
* // with an array of rooms
* io.except(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* io.except("room-101").except("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
except(room) {
return this.sockets.except(room);
}
/**
* Sends a `message` event to all clients.
*
* This method mimics the WebSocket.send() method.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
*
* @example
* io.send("hello");
*
* // this is equivalent to
* io.emit("message", "hello");
*
* @return self
*/
send(...args) {
// This type-cast is needed because EmitEvents likely doesn't have `message` as a key.
// if you specify the EmitEvents, the type of args will be never.
this.sockets.emit("message", ...args);
return this;
}
/**
* Sends a `message` event to all clients. Alias of {@link send}.
*
* @return self
*/
write(...args) {
// This type-cast is needed because EmitEvents likely doesn't have `message` as a key.
// if you specify the EmitEvents, the type of args will be never.
this.sockets.emit("message", ...args);
return this;
}
/**
* Sends a message to the other Socket.IO servers of the cluster.
*
* @example
* io.serverSideEmit("hello", "world");
*
* io.on("hello", (arg1) => {
* console.log(arg1); // prints "world"
* });
*
* // acknowledgements (without binary content) are supported too:
* io.serverSideEmit("ping", (err, responses) => {
* if (err) {
* // some servers did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per server (except the current one)
* }
* });
*
* io.on("ping", (cb) => {
* cb("pong");
* });
*
* @param ev - the event name
* @param args - an array of arguments, which may include an acknowledgement callback at the end
*/
serverSideEmit(ev, ...args) {
return this.sockets.serverSideEmit(ev, ...args);
}
/**
* Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.
*
* @example
* try {
* const responses = await io.serverSideEmitWithAck("ping");
* console.log(responses); // one response per server (except the current one)
* } catch (e) {
* // some servers did not acknowledge the event in the given delay
* }
*
* @param ev - the event name
* @param args - an array of arguments
*
* @return a Promise that will be fulfilled when all servers have acknowledged the event
*/
serverSideEmitWithAck(ev, ...args) {
return this.sockets.serverSideEmitWithAck(ev, ...args);
}
/**
* Gets a list of socket ids.
*
* @deprecated this method will be removed in the next major release, please use {@link Server#serverSideEmit} or
* {@link Server#fetchSockets} instead.
*/
allSockets() {
return this.sockets.allSockets();
}
/**
* Sets the compress flag.
*
* @example
* io.compress(false).emit("hello");
*
* @param compress - if `true`, compresses the sending data
* @return a new {@link BroadcastOperator} instance for chaining
*/
compress(compress) {
return this.sockets.compress(compress);
}
/**
* Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
* receive messages (because of network slowness or other issues, or because theyre connected through long polling
* and is in the middle of a request-response cycle).
*
* @example
* io.volatile.emit("hello"); // the clients may or may not receive it
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get volatile() {
return this.sockets.volatile;
}
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
*
* @example
* // the “foo” event will be broadcast to all connected clients on this node
* io.local.emit("foo", "bar");
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get local() {
return this.sockets.local;
}
/**
* Adds a timeout in milliseconds for the next operation.
*
* @example
* io.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @param timeout
*/
timeout(timeout) {
return this.sockets.timeout(timeout);
}
/**
* Returns the matching socket instances.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // return all Socket instances
* const sockets = await io.fetchSockets();
*
* // return all Socket instances in the "room1" room
* const sockets = await io.in("room1").fetchSockets();
*
* for (const socket of sockets) {
* console.log(socket.id);
* console.log(socket.handshake);
* console.log(socket.rooms);
* console.log(socket.data);
*
* socket.emit("hello");
* socket.join("room1");
* socket.leave("room2");
* socket.disconnect();
* }
*/
fetchSockets() {
return this.sockets.fetchSockets();
}
/**
* Makes the matching socket instances join the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
*
* // make all socket instances join the "room1" room
* io.socketsJoin("room1");
*
* // make all socket instances in the "room1" room join the "room2" and "room3" rooms
* io.in("room1").socketsJoin(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsJoin(room) {
return this.sockets.socketsJoin(room);
}
/**
* Makes the matching socket instances leave the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // make all socket instances leave the "room1" room
* io.socketsLeave("room1");
*
* // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
* io.in("room1").socketsLeave(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsLeave(room) {
return this.sockets.socketsLeave(room);
}
/**
* Makes the matching socket instances disconnect.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* // make all socket instances disconnect (the connections might be kept alive for other namespaces)
* io.disconnectSockets();
*
* // make all socket instances in the "room1" room disconnect and close the underlying connections
* io.in("room1").disconnectSockets(true);
*
* @param close - whether to close the underlying connection
*/
disconnectSockets(close = false) {
return this.sockets.disconnectSockets(close);
}
}
exports.Server = Server;
/**
* Expose main namespace (/).
*/
const emitterMethods = Object.keys(events_1.EventEmitter.prototype).filter(function (key) {
return typeof events_1.EventEmitter.prototype[key] === "function";
});
emitterMethods.forEach(function (fn) {
Server.prototype[fn] = function () {
return this.sockets[fn].apply(this.sockets, arguments);
};
});
module.exports = (srv, opts) => new Server(srv, opts);
module.exports.Server = Server;
module.exports.Namespace = namespace_1.Namespace;
module.exports.Socket = socket_1.Socket;
var socket_2 = require("./socket");

426
node_modules/socket.io/dist/namespace.d.ts generated vendored Normal file
View File

@ -0,0 +1,426 @@
import { Socket } from "./socket";
import type { Server } from "./index";
import { EventParams, EventNames, EventsMap, StrictEventEmitter, DefaultEventsMap, DecorateAcknowledgementsWithTimeoutAndMultipleResponses, AllButLast, Last, DecorateAcknowledgementsWithMultipleResponses, DecorateAcknowledgements, RemoveAcknowledgements, EventNamesWithAck, FirstNonErrorArg, EventNamesWithoutAck } from "./typed-events";
import type { Client } from "./client";
import type { Adapter, Room, SocketId } from "socket.io-adapter";
import { BroadcastOperator } from "./broadcast-operator";
export interface ExtendedError extends Error {
data?: any;
}
export interface NamespaceReservedEventsMap<ListenEvents extends EventsMap, EmitEvents extends EventsMap, ServerSideEvents extends EventsMap, SocketData> {
connect: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>) => void;
connection: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>) => void;
}
export interface ServerReservedEventsMap<ListenEvents extends EventsMap, EmitEvents extends EventsMap, ServerSideEvents extends EventsMap, SocketData> extends NamespaceReservedEventsMap<ListenEvents, EmitEvents, ServerSideEvents, SocketData> {
new_namespace: (namespace: Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>) => void;
}
export declare const RESERVED_EVENTS: ReadonlySet<string | Symbol>;
/**
* A Namespace is a communication channel that allows you to split the logic of your application over a single shared
* connection.
*
* Each namespace has its own:
*
* - event handlers
*
* ```
* io.of("/orders").on("connection", (socket) => {
* socket.on("order:list", () => {});
* socket.on("order:create", () => {});
* });
*
* io.of("/users").on("connection", (socket) => {
* socket.on("user:list", () => {});
* });
* ```
*
* - rooms
*
* ```
* const orderNamespace = io.of("/orders");
*
* orderNamespace.on("connection", (socket) => {
* socket.join("room1");
* orderNamespace.to("room1").emit("hello");
* });
*
* const userNamespace = io.of("/users");
*
* userNamespace.on("connection", (socket) => {
* socket.join("room1"); // distinct from the room in the "orders" namespace
* userNamespace.to("room1").emit("holà");
* });
* ```
*
* - middlewares
*
* ```
* const orderNamespace = io.of("/orders");
*
* orderNamespace.use((socket, next) => {
* // ensure the socket has access to the "orders" namespace
* });
*
* const userNamespace = io.of("/users");
*
* userNamespace.use((socket, next) => {
* // ensure the socket has access to the "users" namespace
* });
* ```
*/
export declare class Namespace<ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, ServerSideEvents extends EventsMap = DefaultEventsMap, SocketData = any> extends StrictEventEmitter<ServerSideEvents, RemoveAcknowledgements<EmitEvents>, NamespaceReservedEventsMap<ListenEvents, EmitEvents, ServerSideEvents, SocketData>> {
readonly name: string;
readonly sockets: Map<SocketId, Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>>;
adapter: Adapter;
/** @private */
readonly server: Server<ListenEvents, EmitEvents, ServerSideEvents, SocketData>;
/** @private */
_fns: Array<(socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>, next: (err?: ExtendedError) => void) => void>;
/** @private */
_ids: number;
/**
* Namespace constructor.
*
* @param server instance
* @param name
*/
constructor(server: Server<ListenEvents, EmitEvents, ServerSideEvents, SocketData>, name: string);
/**
* Initializes the `Adapter` for this nsp.
* Run upon changing adapter by `Server#adapter`
* in addition to the constructor.
*
* @private
*/
_initAdapter(): void;
/**
* Registers a middleware, which is a function that gets executed for every incoming {@link Socket}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.use((socket, next) => {
* // ...
* next();
* });
*
* @param fn - the middleware function
*/
use(fn: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>, next: (err?: ExtendedError) => void) => void): this;
/**
* Executes the middleware for an incoming client.
*
* @param socket - the socket that will get added
* @param fn - last fn call in the middleware
* @private
*/
private run;
/**
* Targets a room when emitting.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // the “foo” event will be broadcast to all connected clients in the “room-101” room
* myNamespace.to("room-101").emit("foo", "bar");
*
* // with an array of rooms (a client will be notified at most once)
* myNamespace.to(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* myNamespace.to("room-101").to("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
to(room: Room | Room[]): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // disconnect all clients in the "room-101" room
* myNamespace.in("room-101").disconnectSockets();
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
in(room: Room | Room[]): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Excludes a room when emitting.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
* myNamespace.except("room-101").emit("foo", "bar");
*
* // with an array of rooms
* myNamespace.except(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* myNamespace.except("room-101").except("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
except(room: Room | Room[]): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Adds a new client.
*
* @return {Socket}
* @private
*/
_add(client: Client<ListenEvents, EmitEvents, ServerSideEvents>, auth: Record<string, unknown>, fn: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>) => void): any;
private _createSocket;
private _doConnect;
/**
* Removes a client. Called by each `Socket`.
*
* @private
*/
_remove(socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>): void;
/**
* Emits to all connected clients.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.emit("hello", "world");
*
* // all serializable datastructures are supported (no need to call JSON.stringify)
* myNamespace.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) });
*
* // with an acknowledgement from the clients
* myNamespace.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @return Always true
*/
emit<Ev extends EventNamesWithoutAck<EmitEvents>>(ev: Ev, ...args: EventParams<EmitEvents, Ev>): boolean;
/**
* Sends a `message` event to all clients.
*
* This method mimics the WebSocket.send() method.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.send("hello");
*
* // this is equivalent to
* myNamespace.emit("message", "hello");
*
* @return self
*/
send(...args: EventParams<EmitEvents, "message">): this;
/**
* Sends a `message` event to all clients. Sends a `message` event. Alias of {@link send}.
*
* @return self
*/
write(...args: EventParams<EmitEvents, "message">): this;
/**
* Sends a message to the other Socket.IO servers of the cluster.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.serverSideEmit("hello", "world");
*
* myNamespace.on("hello", (arg1) => {
* console.log(arg1); // prints "world"
* });
*
* // acknowledgements (without binary content) are supported too:
* myNamespace.serverSideEmit("ping", (err, responses) => {
* if (err) {
* // some servers did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per server (except the current one)
* }
* });
*
* myNamespace.on("ping", (cb) => {
* cb("pong");
* });
*
* @param ev - the event name
* @param args - an array of arguments, which may include an acknowledgement callback at the end
*/
serverSideEmit<Ev extends EventNames<ServerSideEvents>>(ev: Ev, ...args: EventParams<DecorateAcknowledgementsWithTimeoutAndMultipleResponses<ServerSideEvents>, Ev>): boolean;
/**
* Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* try {
* const responses = await myNamespace.serverSideEmitWithAck("ping");
* console.log(responses); // one response per server (except the current one)
* } catch (e) {
* // some servers did not acknowledge the event in the given delay
* }
*
* @param ev - the event name
* @param args - an array of arguments
*
* @return a Promise that will be fulfilled when all servers have acknowledged the event
*/
serverSideEmitWithAck<Ev extends EventNamesWithAck<ServerSideEvents>>(ev: Ev, ...args: AllButLast<EventParams<ServerSideEvents, Ev>>): Promise<FirstNonErrorArg<Last<EventParams<ServerSideEvents, Ev>>>[]>;
/**
* Called when a packet is received from another Socket.IO server
*
* @param args - an array of arguments, which may include an acknowledgement callback at the end
*
* @private
*/
_onServerSideEmit(args: [string, ...any[]]): void;
/**
* Gets a list of clients.
*
* @deprecated this method will be removed in the next major release, please use {@link Namespace#serverSideEmit} or
* {@link Namespace#fetchSockets} instead.
*/
allSockets(): Promise<Set<SocketId>>;
/**
* Sets the compress flag.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.compress(false).emit("hello");
*
* @param compress - if `true`, compresses the sending data
* @return self
*/
compress(compress: boolean): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
* receive messages (because of network slowness or other issues, or because theyre connected through long polling
* and is in the middle of a request-response cycle).
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.volatile.emit("hello"); // the clients may or may not receive it
*
* @return self
*/
get volatile(): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // the “foo” event will be broadcast to all connected clients on this node
* myNamespace.local.emit("foo", "bar");
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get local(): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Adds a timeout in milliseconds for the next operation.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @param timeout
*/
timeout(timeout: number): BroadcastOperator<DecorateAcknowledgements<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>>, SocketData>;
/**
* Returns the matching socket instances.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // return all Socket instances
* const sockets = await myNamespace.fetchSockets();
*
* // return all Socket instances in the "room1" room
* const sockets = await myNamespace.in("room1").fetchSockets();
*
* for (const socket of sockets) {
* console.log(socket.id);
* console.log(socket.handshake);
* console.log(socket.rooms);
* console.log(socket.data);
*
* socket.emit("hello");
* socket.join("room1");
* socket.leave("room2");
* socket.disconnect();
* }
*/
fetchSockets(): Promise<import("./broadcast-operator").RemoteSocket<EmitEvents, SocketData>[]>;
/**
* Makes the matching socket instances join the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // make all socket instances join the "room1" room
* myNamespace.socketsJoin("room1");
*
* // make all socket instances in the "room1" room join the "room2" and "room3" rooms
* myNamespace.in("room1").socketsJoin(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsJoin(room: Room | Room[]): void;
/**
* Makes the matching socket instances leave the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // make all socket instances leave the "room1" room
* myNamespace.socketsLeave("room1");
*
* // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
* myNamespace.in("room1").socketsLeave(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsLeave(room: Room | Room[]): void;
/**
* Makes the matching socket instances disconnect.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // make all socket instances disconnect (the connections might be kept alive for other namespaces)
* myNamespace.disconnectSockets();
*
* // make all socket instances in the "room1" room disconnect and close the underlying connections
* myNamespace.in("room1").disconnectSockets(true);
*
* @param close - whether to close the underlying connection
*/
disconnectSockets(close?: boolean): void;
}

579
node_modules/socket.io/dist/namespace.js generated vendored Normal file
View File

@ -0,0 +1,579 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Namespace = exports.RESERVED_EVENTS = void 0;
const socket_1 = require("./socket");
const typed_events_1 = require("./typed-events");
const debug_1 = __importDefault(require("debug"));
const broadcast_operator_1 = require("./broadcast-operator");
const debug = (0, debug_1.default)("socket.io:namespace");
exports.RESERVED_EVENTS = new Set(["connect", "connection", "new_namespace"]);
/**
* A Namespace is a communication channel that allows you to split the logic of your application over a single shared
* connection.
*
* Each namespace has its own:
*
* - event handlers
*
* ```
* io.of("/orders").on("connection", (socket) => {
* socket.on("order:list", () => {});
* socket.on("order:create", () => {});
* });
*
* io.of("/users").on("connection", (socket) => {
* socket.on("user:list", () => {});
* });
* ```
*
* - rooms
*
* ```
* const orderNamespace = io.of("/orders");
*
* orderNamespace.on("connection", (socket) => {
* socket.join("room1");
* orderNamespace.to("room1").emit("hello");
* });
*
* const userNamespace = io.of("/users");
*
* userNamespace.on("connection", (socket) => {
* socket.join("room1"); // distinct from the room in the "orders" namespace
* userNamespace.to("room1").emit("holà");
* });
* ```
*
* - middlewares
*
* ```
* const orderNamespace = io.of("/orders");
*
* orderNamespace.use((socket, next) => {
* // ensure the socket has access to the "orders" namespace
* });
*
* const userNamespace = io.of("/users");
*
* userNamespace.use((socket, next) => {
* // ensure the socket has access to the "users" namespace
* });
* ```
*/
class Namespace extends typed_events_1.StrictEventEmitter {
/**
* Namespace constructor.
*
* @param server instance
* @param name
*/
constructor(server, name) {
super();
this.sockets = new Map();
/** @private */
this._fns = [];
/** @private */
this._ids = 0;
this.server = server;
this.name = name;
this._initAdapter();
}
/**
* Initializes the `Adapter` for this nsp.
* Run upon changing adapter by `Server#adapter`
* in addition to the constructor.
*
* @private
*/
_initAdapter() {
// @ts-ignore
this.adapter = new (this.server.adapter())(this);
}
/**
* Registers a middleware, which is a function that gets executed for every incoming {@link Socket}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.use((socket, next) => {
* // ...
* next();
* });
*
* @param fn - the middleware function
*/
use(fn) {
this._fns.push(fn);
return this;
}
/**
* Executes the middleware for an incoming client.
*
* @param socket - the socket that will get added
* @param fn - last fn call in the middleware
* @private
*/
run(socket, fn) {
const fns = this._fns.slice(0);
if (!fns.length)
return fn(null);
function run(i) {
fns[i](socket, function (err) {
// upon error, short-circuit
if (err)
return fn(err);
// if no middleware left, summon callback
if (!fns[i + 1])
return fn(null);
// go on to next
run(i + 1);
});
}
run(0);
}
/**
* Targets a room when emitting.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // the “foo” event will be broadcast to all connected clients in the “room-101” room
* myNamespace.to("room-101").emit("foo", "bar");
*
* // with an array of rooms (a client will be notified at most once)
* myNamespace.to(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* myNamespace.to("room-101").to("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
to(room) {
return new broadcast_operator_1.BroadcastOperator(this.adapter).to(room);
}
/**
* Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // disconnect all clients in the "room-101" room
* myNamespace.in("room-101").disconnectSockets();
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
in(room) {
return new broadcast_operator_1.BroadcastOperator(this.adapter).in(room);
}
/**
* Excludes a room when emitting.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
* myNamespace.except("room-101").emit("foo", "bar");
*
* // with an array of rooms
* myNamespace.except(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* myNamespace.except("room-101").except("room-102").emit("foo", "bar");
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
except(room) {
return new broadcast_operator_1.BroadcastOperator(this.adapter).except(room);
}
/**
* Adds a new client.
*
* @return {Socket}
* @private
*/
async _add(client, auth, fn) {
var _a;
debug("adding socket to nsp %s", this.name);
const socket = await this._createSocket(client, auth);
if (
// @ts-ignore
((_a = this.server.opts.connectionStateRecovery) === null || _a === void 0 ? void 0 : _a.skipMiddlewares) &&
socket.recovered &&
client.conn.readyState === "open") {
return this._doConnect(socket, fn);
}
this.run(socket, (err) => {
process.nextTick(() => {
if ("open" !== client.conn.readyState) {
debug("next called after client was closed - ignoring socket");
socket._cleanup();
return;
}
if (err) {
debug("middleware error, sending CONNECT_ERROR packet to the client");
socket._cleanup();
if (client.conn.protocol === 3) {
return socket._error(err.data || err.message);
}
else {
return socket._error({
message: err.message,
data: err.data,
});
}
}
this._doConnect(socket, fn);
});
});
}
async _createSocket(client, auth) {
const sessionId = auth.pid;
const offset = auth.offset;
if (
// @ts-ignore
this.server.opts.connectionStateRecovery &&
typeof sessionId === "string" &&
typeof offset === "string") {
let session;
try {
session = await this.adapter.restoreSession(sessionId, offset);
}
catch (e) {
debug("error while restoring session: %s", e);
}
if (session) {
debug("connection state recovered for sid %s", session.sid);
return new socket_1.Socket(this, client, auth, session);
}
}
return new socket_1.Socket(this, client, auth);
}
_doConnect(socket, fn) {
// track socket
this.sockets.set(socket.id, socket);
// it's paramount that the internal `onconnect` logic
// fires before user-set events to prevent state order
// violations (such as a disconnection before the connection
// logic is complete)
socket._onconnect();
if (fn)
fn(socket);
// fire user-set events
this.emitReserved("connect", socket);
this.emitReserved("connection", socket);
}
/**
* Removes a client. Called by each `Socket`.
*
* @private
*/
_remove(socket) {
if (this.sockets.has(socket.id)) {
this.sockets.delete(socket.id);
}
else {
debug("ignoring remove for %s", socket.id);
}
}
/**
* Emits to all connected clients.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.emit("hello", "world");
*
* // all serializable datastructures are supported (no need to call JSON.stringify)
* myNamespace.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) });
*
* // with an acknowledgement from the clients
* myNamespace.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @return Always true
*/
emit(ev, ...args) {
return new broadcast_operator_1.BroadcastOperator(this.adapter).emit(ev, ...args);
}
/**
* Sends a `message` event to all clients.
*
* This method mimics the WebSocket.send() method.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.send("hello");
*
* // this is equivalent to
* myNamespace.emit("message", "hello");
*
* @return self
*/
send(...args) {
// This type-cast is needed because EmitEvents likely doesn't have `message` as a key.
// if you specify the EmitEvents, the type of args will be never.
this.emit("message", ...args);
return this;
}
/**
* Sends a `message` event to all clients. Sends a `message` event. Alias of {@link send}.
*
* @return self
*/
write(...args) {
// This type-cast is needed because EmitEvents likely doesn't have `message` as a key.
// if you specify the EmitEvents, the type of args will be never.
this.emit("message", ...args);
return this;
}
/**
* Sends a message to the other Socket.IO servers of the cluster.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.serverSideEmit("hello", "world");
*
* myNamespace.on("hello", (arg1) => {
* console.log(arg1); // prints "world"
* });
*
* // acknowledgements (without binary content) are supported too:
* myNamespace.serverSideEmit("ping", (err, responses) => {
* if (err) {
* // some servers did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per server (except the current one)
* }
* });
*
* myNamespace.on("ping", (cb) => {
* cb("pong");
* });
*
* @param ev - the event name
* @param args - an array of arguments, which may include an acknowledgement callback at the end
*/
serverSideEmit(ev, ...args) {
if (exports.RESERVED_EVENTS.has(ev)) {
throw new Error(`"${String(ev)}" is a reserved event name`);
}
args.unshift(ev);
this.adapter.serverSideEmit(args);
return true;
}
/**
* Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* try {
* const responses = await myNamespace.serverSideEmitWithAck("ping");
* console.log(responses); // one response per server (except the current one)
* } catch (e) {
* // some servers did not acknowledge the event in the given delay
* }
*
* @param ev - the event name
* @param args - an array of arguments
*
* @return a Promise that will be fulfilled when all servers have acknowledged the event
*/
serverSideEmitWithAck(ev, ...args) {
return new Promise((resolve, reject) => {
args.push((err, responses) => {
if (err) {
err.responses = responses;
return reject(err);
}
else {
return resolve(responses);
}
});
this.serverSideEmit(ev, ...args);
});
}
/**
* Called when a packet is received from another Socket.IO server
*
* @param args - an array of arguments, which may include an acknowledgement callback at the end
*
* @private
*/
_onServerSideEmit(args) {
super.emitUntyped.apply(this, args);
}
/**
* Gets a list of clients.
*
* @deprecated this method will be removed in the next major release, please use {@link Namespace#serverSideEmit} or
* {@link Namespace#fetchSockets} instead.
*/
allSockets() {
return new broadcast_operator_1.BroadcastOperator(this.adapter).allSockets();
}
/**
* Sets the compress flag.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.compress(false).emit("hello");
*
* @param compress - if `true`, compresses the sending data
* @return self
*/
compress(compress) {
return new broadcast_operator_1.BroadcastOperator(this.adapter).compress(compress);
}
/**
* Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
* receive messages (because of network slowness or other issues, or because theyre connected through long polling
* and is in the middle of a request-response cycle).
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.volatile.emit("hello"); // the clients may or may not receive it
*
* @return self
*/
get volatile() {
return new broadcast_operator_1.BroadcastOperator(this.adapter).volatile;
}
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // the “foo” event will be broadcast to all connected clients on this node
* myNamespace.local.emit("foo", "bar");
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get local() {
return new broadcast_operator_1.BroadcastOperator(this.adapter).local;
}
/**
* Adds a timeout in milliseconds for the next operation.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* myNamespace.timeout(1000).emit("some-event", (err, responses) => {
* if (err) {
* // some clients did not acknowledge the event in the given delay
* } else {
* console.log(responses); // one response per client
* }
* });
*
* @param timeout
*/
timeout(timeout) {
return new broadcast_operator_1.BroadcastOperator(this.adapter).timeout(timeout);
}
/**
* Returns the matching socket instances.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // return all Socket instances
* const sockets = await myNamespace.fetchSockets();
*
* // return all Socket instances in the "room1" room
* const sockets = await myNamespace.in("room1").fetchSockets();
*
* for (const socket of sockets) {
* console.log(socket.id);
* console.log(socket.handshake);
* console.log(socket.rooms);
* console.log(socket.data);
*
* socket.emit("hello");
* socket.join("room1");
* socket.leave("room2");
* socket.disconnect();
* }
*/
fetchSockets() {
return new broadcast_operator_1.BroadcastOperator(this.adapter).fetchSockets();
}
/**
* Makes the matching socket instances join the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // make all socket instances join the "room1" room
* myNamespace.socketsJoin("room1");
*
* // make all socket instances in the "room1" room join the "room2" and "room3" rooms
* myNamespace.in("room1").socketsJoin(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsJoin(room) {
return new broadcast_operator_1.BroadcastOperator(this.adapter).socketsJoin(room);
}
/**
* Makes the matching socket instances leave the specified rooms.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // make all socket instances leave the "room1" room
* myNamespace.socketsLeave("room1");
*
* // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
* myNamespace.in("room1").socketsLeave(["room2", "room3"]);
*
* @param room - a room, or an array of rooms
*/
socketsLeave(room) {
return new broadcast_operator_1.BroadcastOperator(this.adapter).socketsLeave(room);
}
/**
* Makes the matching socket instances disconnect.
*
* Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
*
* @example
* const myNamespace = io.of("/my-namespace");
*
* // make all socket instances disconnect (the connections might be kept alive for other namespaces)
* myNamespace.disconnectSockets();
*
* // make all socket instances in the "room1" room disconnect and close the underlying connections
* myNamespace.in("room1").disconnectSockets(true);
*
* @param close - whether to close the underlying connection
*/
disconnectSockets(close = false) {
return new broadcast_operator_1.BroadcastOperator(this.adapter).disconnectSockets(close);
}
}
exports.Namespace = Namespace;

30
node_modules/socket.io/dist/parent-namespace.d.ts generated vendored Normal file
View File

@ -0,0 +1,30 @@
import { Namespace } from "./namespace";
import type { Server, RemoteSocket } from "./index";
import type { EventParams, EventsMap, DefaultEventsMap, EventNamesWithoutAck } from "./typed-events";
/**
* A parent namespace is a special {@link Namespace} that holds a list of child namespaces which were created either
* with a regular expression or with a function.
*
* @example
* const parentNamespace = io.of(/\/dynamic-\d+/);
*
* parentNamespace.on("connection", (socket) => {
* const childNamespace = socket.nsp;
* }
*
* // will reach all the clients that are in one of the child namespaces, like "/dynamic-101"
* parentNamespace.emit("hello", "world");
*
*/
export declare class ParentNamespace<ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, ServerSideEvents extends EventsMap = DefaultEventsMap, SocketData = any> extends Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData> {
private static count;
private readonly children;
constructor(server: Server<ListenEvents, EmitEvents, ServerSideEvents, SocketData>);
/**
* @private
*/
_initAdapter(): void;
emit<Ev extends EventNamesWithoutAck<EmitEvents>>(ev: Ev, ...args: EventParams<EmitEvents, Ev>): boolean;
createChild(name: string): Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>;
fetchSockets(): Promise<RemoteSocket<EmitEvents, SocketData>[]>;
}

92
node_modules/socket.io/dist/parent-namespace.js generated vendored Normal file
View File

@ -0,0 +1,92 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParentNamespace = void 0;
const namespace_1 = require("./namespace");
const socket_io_adapter_1 = require("socket.io-adapter");
const debug_1 = __importDefault(require("debug"));
const debug = (0, debug_1.default)("socket.io:parent-namespace");
/**
* A parent namespace is a special {@link Namespace} that holds a list of child namespaces which were created either
* with a regular expression or with a function.
*
* @example
* const parentNamespace = io.of(/\/dynamic-\d+/);
*
* parentNamespace.on("connection", (socket) => {
* const childNamespace = socket.nsp;
* }
*
* // will reach all the clients that are in one of the child namespaces, like "/dynamic-101"
* parentNamespace.emit("hello", "world");
*
*/
class ParentNamespace extends namespace_1.Namespace {
constructor(server) {
super(server, "/_" + ParentNamespace.count++);
this.children = new Set();
}
/**
* @private
*/
_initAdapter() {
this.adapter = new ParentBroadcastAdapter(this, this.children);
}
emit(ev, ...args) {
this.children.forEach((nsp) => {
nsp.emit(ev, ...args);
});
return true;
}
createChild(name) {
debug("creating child namespace %s", name);
const namespace = new namespace_1.Namespace(this.server, name);
namespace._fns = this._fns.slice(0);
this.listeners("connect").forEach((listener) => namespace.on("connect", listener));
this.listeners("connection").forEach((listener) => namespace.on("connection", listener));
this.children.add(namespace);
if (this.server._opts.cleanupEmptyChildNamespaces) {
const remove = namespace._remove;
namespace._remove = (socket) => {
remove.call(namespace, socket);
if (namespace.sockets.size === 0) {
debug("closing child namespace %s", name);
namespace.adapter.close();
this.server._nsps.delete(namespace.name);
this.children.delete(namespace);
}
};
}
this.server._nsps.set(name, namespace);
// @ts-ignore
this.server.sockets.emitReserved("new_namespace", namespace);
return namespace;
}
fetchSockets() {
// note: we could make the fetchSockets() method work for dynamic namespaces created with a regex (by sending the
// regex to the other Socket.IO servers, and returning the sockets of each matching namespace for example), but
// the behavior for namespaces created with a function is less clear
// note²: we cannot loop over each children namespace, because with multiple Socket.IO servers, a given namespace
// may exist on one node but not exist on another (since it is created upon client connection)
throw new Error("fetchSockets() is not supported on parent namespaces");
}
}
exports.ParentNamespace = ParentNamespace;
ParentNamespace.count = 0;
/**
* A dummy adapter that only supports broadcasting to child (concrete) namespaces.
* @private file
*/
class ParentBroadcastAdapter extends socket_io_adapter_1.Adapter {
constructor(parentNsp, children) {
super(parentNsp);
this.children = children;
}
broadcast(packet, opts) {
this.children.forEach((nsp) => {
nsp.adapter.broadcast(packet, opts);
});
}
}

669
node_modules/socket.io/dist/socket.d.ts generated vendored Normal file
View File

@ -0,0 +1,669 @@
/// <reference types="node" />
/// <reference types="node" />
import { Packet } from "socket.io-parser";
import { AllButLast, DecorateAcknowledgements, DecorateAcknowledgementsWithMultipleResponses, DefaultEventsMap, EventNames, EventNamesWithAck, EventParams, EventsMap, FirstNonErrorArg, Last, StrictEventEmitter } from "./typed-events";
import type { Client } from "./client";
import type { Namespace } from "./namespace";
import type { IncomingHttpHeaders, IncomingMessage } from "http";
import type { Room, Session, SocketId } from "socket.io-adapter";
import type { ParsedUrlQuery } from "querystring";
import { BroadcastOperator } from "./broadcast-operator";
export declare type DisconnectReason = "transport error" | "transport close" | "forced close" | "ping timeout" | "parse error" | "server shutting down" | "forced server close" | "client namespace disconnect" | "server namespace disconnect";
export interface SocketReservedEventsMap {
disconnect: (reason: DisconnectReason, description?: any) => void;
disconnecting: (reason: DisconnectReason, description?: any) => void;
error: (err: Error) => void;
}
export interface EventEmitterReservedEventsMap {
newListener: (eventName: string | Symbol, listener: (...args: any[]) => void) => void;
removeListener: (eventName: string | Symbol, listener: (...args: any[]) => void) => void;
}
export declare const RESERVED_EVENTS: ReadonlySet<string | Symbol>;
/**
* The handshake details
*/
export interface Handshake {
/**
* The headers sent as part of the handshake
*/
headers: IncomingHttpHeaders;
/**
* The date of creation (as string)
*/
time: string;
/**
* The ip of the client
*/
address: string;
/**
* Whether the connection is cross-domain
*/
xdomain: boolean;
/**
* Whether the connection is secure
*/
secure: boolean;
/**
* The date of creation (as unix timestamp)
*/
issued: number;
/**
* The request URL string
*/
url: string;
/**
* The query object
*/
query: ParsedUrlQuery;
/**
* The auth object
*/
auth: {
[key: string]: any;
};
}
/**
* `[eventName, ...args]`
*/
export declare type Event = [string, ...any[]];
/**
* This is the main object for interacting with a client.
*
* A Socket belongs to a given {@link Namespace} and uses an underlying {@link Client} to communicate.
*
* Within each {@link Namespace}, you can also define arbitrary channels (called "rooms") that the {@link Socket} can
* join and leave. That provides a convenient way to broadcast to a group of socket instances.
*
* @example
* io.on("connection", (socket) => {
* console.log(`socket ${socket.id} connected`);
*
* // send an event to the client
* socket.emit("foo", "bar");
*
* socket.on("foobar", () => {
* // an event was received from the client
* });
*
* // join the room named "room1"
* socket.join("room1");
*
* // broadcast to everyone in the room named "room1"
* io.to("room1").emit("hello");
*
* // upon disconnection
* socket.on("disconnect", (reason) => {
* console.log(`socket ${socket.id} disconnected due to ${reason}`);
* });
* });
*/
export declare class Socket<ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, ServerSideEvents extends EventsMap = DefaultEventsMap, SocketData = any> extends StrictEventEmitter<ListenEvents, EmitEvents, SocketReservedEventsMap> {
readonly nsp: Namespace<ListenEvents, EmitEvents, ServerSideEvents>;
readonly client: Client<ListenEvents, EmitEvents, ServerSideEvents>;
/**
* An unique identifier for the session.
*/
readonly id: SocketId;
/**
* Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will
* be transmitted to the client, the data attribute and the rooms will be restored.
*/
readonly recovered: boolean;
/**
* The handshake details.
*/
readonly handshake: Handshake;
/**
* Additional information that can be attached to the Socket instance and which will be used in the
* {@link Server.fetchSockets()} method.
*/
data: SocketData;
/**
* Whether the socket is currently connected or not.
*
* @example
* io.use((socket, next) => {
* console.log(socket.connected); // false
* next();
* });
*
* io.on("connection", (socket) => {
* console.log(socket.connected); // true
* });
*/
connected: boolean;
/**
* The session ID, which must not be shared (unlike {@link id}).
*
* @private
*/
private readonly pid;
private readonly server;
private readonly adapter;
private acks;
private fns;
private flags;
private _anyListeners?;
private _anyOutgoingListeners?;
/**
* Interface to a `Client` for a given `Namespace`.
*
* @param {Namespace} nsp
* @param {Client} client
* @param {Object} auth
* @package
*/
constructor(nsp: Namespace<ListenEvents, EmitEvents, ServerSideEvents>, client: Client<ListenEvents, EmitEvents, ServerSideEvents>, auth: Record<string, unknown>, previousSession?: Session);
/**
* Builds the `handshake` BC object
*
* @private
*/
private buildHandshake;
/**
* Emits to this client.
*
* @example
* io.on("connection", (socket) => {
* socket.emit("hello", "world");
*
* // all serializable datastructures are supported (no need to call JSON.stringify)
* socket.emit("hello", 1, "2", { 3: ["4"], 5: Buffer.from([6]) });
*
* // with an acknowledgement from the client
* socket.emit("hello", "world", (val) => {
* // ...
* });
* });
*
* @return Always returns `true`.
*/
emit<Ev extends EventNames<EmitEvents>>(ev: Ev, ...args: EventParams<EmitEvents, Ev>): boolean;
/**
* Emits an event and waits for an acknowledgement
*
* @example
* io.on("connection", async (socket) => {
* // without timeout
* const response = await socket.emitWithAck("hello", "world");
*
* // with a specific timeout
* try {
* const response = await socket.timeout(1000).emitWithAck("hello", "world");
* } catch (err) {
* // the client did not acknowledge the event in the given delay
* }
* });
*
* @return a Promise that will be fulfilled when the client acknowledges the event
*/
emitWithAck<Ev extends EventNamesWithAck<EmitEvents>>(ev: Ev, ...args: AllButLast<EventParams<EmitEvents, Ev>>): Promise<FirstNonErrorArg<Last<EventParams<EmitEvents, Ev>>>>;
/**
* @private
*/
private registerAckCallback;
/**
* Targets a room when broadcasting.
*
* @example
* io.on("connection", (socket) => {
* // the “foo” event will be broadcast to all connected clients in the “room-101” room, except this socket
* socket.to("room-101").emit("foo", "bar");
*
* // the code above is equivalent to:
* io.to("room-101").except(socket.id).emit("foo", "bar");
*
* // with an array of rooms (a client will be notified at most once)
* socket.to(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* socket.to("room-101").to("room-102").emit("foo", "bar");
* });
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
to(room: Room | Room[]): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Targets a room when broadcasting. Similar to `to()`, but might feel clearer in some cases:
*
* @example
* io.on("connection", (socket) => {
* // disconnect all clients in the "room-101" room, except this socket
* socket.in("room-101").disconnectSockets();
* });
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
in(room: Room | Room[]): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Excludes a room when broadcasting.
*
* @example
* io.on("connection", (socket) => {
* // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
* // and this socket
* socket.except("room-101").emit("foo", "bar");
*
* // with an array of rooms
* socket.except(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* socket.except("room-101").except("room-102").emit("foo", "bar");
* });
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
except(room: Room | Room[]): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Sends a `message` event.
*
* This method mimics the WebSocket.send() method.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
*
* @example
* io.on("connection", (socket) => {
* socket.send("hello");
*
* // this is equivalent to
* socket.emit("message", "hello");
* });
*
* @return self
*/
send(...args: EventParams<EmitEvents, "message">): this;
/**
* Sends a `message` event. Alias of {@link send}.
*
* @return self
*/
write(...args: EventParams<EmitEvents, "message">): this;
/**
* Writes a packet.
*
* @param {Object} packet - packet object
* @param {Object} opts - options
* @private
*/
private packet;
/**
* Joins a room.
*
* @example
* io.on("connection", (socket) => {
* // join a single room
* socket.join("room1");
*
* // join multiple rooms
* socket.join(["room1", "room2"]);
* });
*
* @param {String|Array} rooms - room or array of rooms
* @return a Promise or nothing, depending on the adapter
*/
join(rooms: Room | Array<Room>): Promise<void> | void;
/**
* Leaves a room.
*
* @example
* io.on("connection", (socket) => {
* // leave a single room
* socket.leave("room1");
*
* // leave multiple rooms
* socket.leave("room1").leave("room2");
* });
*
* @param {String} room
* @return a Promise or nothing, depending on the adapter
*/
leave(room: string): Promise<void> | void;
/**
* Leave all rooms.
*
* @private
*/
private leaveAll;
/**
* Called by `Namespace` upon successful
* middleware execution (ie: authorization).
* Socket is added to namespace array before
* call to join, so adapters can access it.
*
* @private
*/
_onconnect(): void;
/**
* Called with each packet. Called by `Client`.
*
* @param {Object} packet
* @private
*/
_onpacket(packet: Packet): void;
/**
* Called upon event packet.
*
* @param {Packet} packet - packet object
* @private
*/
private onevent;
/**
* Produces an ack callback to emit with an event.
*
* @param {Number} id - packet id
* @private
*/
private ack;
/**
* Called upon ack packet.
*
* @private
*/
private onack;
/**
* Called upon client disconnect packet.
*
* @private
*/
private ondisconnect;
/**
* Handles a client error.
*
* @private
*/
_onerror(err: Error): void;
/**
* Called upon closing. Called by `Client`.
*
* @param {String} reason
* @param description
* @throw {Error} optional error object
*
* @private
*/
_onclose(reason: DisconnectReason, description?: any): this | undefined;
/**
* Makes the socket leave all the rooms it was part of and prevents it from joining any other room
*
* @private
*/
_cleanup(): void;
/**
* Produces an `error` packet.
*
* @param {Object} err - error object
*
* @private
*/
_error(err: any): void;
/**
* Disconnects this client.
*
* @example
* io.on("connection", (socket) => {
* // disconnect this socket (the connection might be kept alive for other namespaces)
* socket.disconnect();
*
* // disconnect this socket and close the underlying connection
* socket.disconnect(true);
* })
*
* @param {Boolean} close - if `true`, closes the underlying connection
* @return self
*/
disconnect(close?: boolean): this;
/**
* Sets the compress flag.
*
* @example
* io.on("connection", (socket) => {
* socket.compress(false).emit("hello");
* });
*
* @param {Boolean} compress - if `true`, compresses the sending data
* @return {Socket} self
*/
compress(compress: boolean): this;
/**
* Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
* receive messages (because of network slowness or other issues, or because theyre connected through long polling
* and is in the middle of a request-response cycle).
*
* @example
* io.on("connection", (socket) => {
* socket.volatile.emit("hello"); // the client may or may not receive it
* });
*
* @return {Socket} self
*/
get volatile(): this;
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to every sockets but the
* sender.
*
* @example
* io.on("connection", (socket) => {
* // the “foo” event will be broadcast to all connected clients, except this socket
* socket.broadcast.emit("foo", "bar");
* });
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get broadcast(): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
*
* @example
* io.on("connection", (socket) => {
* // the “foo” event will be broadcast to all connected clients on this node, except this socket
* socket.local.emit("foo", "bar");
* });
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get local(): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
/**
* Sets a modifier for a subsequent event emission that the callback will be called with an error when the
* given number of milliseconds have elapsed without an acknowledgement from the client:
*
* @example
* io.on("connection", (socket) => {
* socket.timeout(5000).emit("my-event", (err) => {
* if (err) {
* // the client did not acknowledge the event in the given delay
* }
* });
* });
*
* @returns self
*/
timeout(timeout: number): Socket<ListenEvents, DecorateAcknowledgements<EmitEvents>, ServerSideEvents, SocketData>;
/**
* Dispatch incoming event to socket listeners.
*
* @param {Array} event - event that will get emitted
* @private
*/
private dispatch;
/**
* Sets up socket middleware.
*
* @example
* io.on("connection", (socket) => {
* socket.use(([event, ...args], next) => {
* if (isUnauthorized(event)) {
* return next(new Error("unauthorized event"));
* }
* // do not forget to call next
* next();
* });
*
* socket.on("error", (err) => {
* if (err && err.message === "unauthorized event") {
* socket.disconnect();
* }
* });
* });
*
* @param {Function} fn - middleware function (event, next)
* @return {Socket} self
*/
use(fn: (event: Event, next: (err?: Error) => void) => void): this;
/**
* Executes the middleware for an incoming event.
*
* @param {Array} event - event that will get emitted
* @param {Function} fn - last fn call in the middleware
* @private
*/
private run;
/**
* Whether the socket is currently disconnected
*/
get disconnected(): boolean;
/**
* A reference to the request that originated the underlying Engine.IO Socket.
*/
get request(): IncomingMessage;
/**
* A reference to the underlying Client transport connection (Engine.IO Socket object).
*
* @example
* io.on("connection", (socket) => {
* console.log(socket.conn.transport.name); // prints "polling" or "websocket"
*
* socket.conn.once("upgrade", () => {
* console.log(socket.conn.transport.name); // prints "websocket"
* });
* });
*/
get conn(): import("engine.io").Socket;
/**
* Returns the rooms the socket is currently in.
*
* @example
* io.on("connection", (socket) => {
* console.log(socket.rooms); // Set { <socket.id> }
*
* socket.join("room1");
*
* console.log(socket.rooms); // Set { <socket.id>, "room1" }
* });
*/
get rooms(): Set<Room>;
/**
* Adds a listener that will be fired when any event is received. The event name is passed as the first argument to
* the callback.
*
* @example
* io.on("connection", (socket) => {
* socket.onAny((event, ...args) => {
* console.log(`got event ${event}`);
* });
* });
*
* @param listener
*/
onAny(listener: (...args: any[]) => void): this;
/**
* Adds a listener that will be fired when any event is received. The event name is passed as the first argument to
* the callback. The listener is added to the beginning of the listeners array.
*
* @param listener
*/
prependAny(listener: (...args: any[]) => void): this;
/**
* Removes the listener that will be fired when any event is received.
*
* @example
* io.on("connection", (socket) => {
* const catchAllListener = (event, ...args) => {
* console.log(`got event ${event}`);
* }
*
* socket.onAny(catchAllListener);
*
* // remove a specific listener
* socket.offAny(catchAllListener);
*
* // or remove all listeners
* socket.offAny();
* });
*
* @param listener
*/
offAny(listener?: (...args: any[]) => void): this;
/**
* Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
* e.g. to remove listeners.
*/
listenersAny(): ((...args: any[]) => void)[];
/**
* Adds a listener that will be fired when any event is sent. The event name is passed as the first argument to
* the callback.
*
* Note: acknowledgements sent to the client are not included.
*
* @example
* io.on("connection", (socket) => {
* socket.onAnyOutgoing((event, ...args) => {
* console.log(`sent event ${event}`);
* });
* });
*
* @param listener
*/
onAnyOutgoing(listener: (...args: any[]) => void): this;
/**
* Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
* callback. The listener is added to the beginning of the listeners array.
*
* @example
* io.on("connection", (socket) => {
* socket.prependAnyOutgoing((event, ...args) => {
* console.log(`sent event ${event}`);
* });
* });
*
* @param listener
*/
prependAnyOutgoing(listener: (...args: any[]) => void): this;
/**
* Removes the listener that will be fired when any event is sent.
*
* @example
* io.on("connection", (socket) => {
* const catchAllListener = (event, ...args) => {
* console.log(`sent event ${event}`);
* }
*
* socket.onAnyOutgoing(catchAllListener);
*
* // remove a specific listener
* socket.offAnyOutgoing(catchAllListener);
*
* // or remove all listeners
* socket.offAnyOutgoing();
* });
*
* @param listener - the catch-all listener
*/
offAnyOutgoing(listener?: (...args: any[]) => void): this;
/**
* Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
* e.g. to remove listeners.
*/
listenersAnyOutgoing(): ((...args: any[]) => void)[];
/**
* Notify the listeners for each packet sent (emit or broadcast)
*
* @param packet
*
* @private
*/
private notifyOutgoingListeners;
private newBroadcastOperator;
}

984
node_modules/socket.io/dist/socket.js generated vendored Normal file
View File

@ -0,0 +1,984 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Socket = exports.RESERVED_EVENTS = void 0;
const socket_io_parser_1 = require("socket.io-parser");
const debug_1 = __importDefault(require("debug"));
const typed_events_1 = require("./typed-events");
const base64id_1 = __importDefault(require("base64id"));
const broadcast_operator_1 = require("./broadcast-operator");
const debug = (0, debug_1.default)("socket.io:socket");
const RECOVERABLE_DISCONNECT_REASONS = new Set([
"transport error",
"transport close",
"forced close",
"ping timeout",
"server shutting down",
"forced server close",
]);
exports.RESERVED_EVENTS = new Set([
"connect",
"connect_error",
"disconnect",
"disconnecting",
"newListener",
"removeListener",
]);
function noop() { }
/**
* This is the main object for interacting with a client.
*
* A Socket belongs to a given {@link Namespace} and uses an underlying {@link Client} to communicate.
*
* Within each {@link Namespace}, you can also define arbitrary channels (called "rooms") that the {@link Socket} can
* join and leave. That provides a convenient way to broadcast to a group of socket instances.
*
* @example
* io.on("connection", (socket) => {
* console.log(`socket ${socket.id} connected`);
*
* // send an event to the client
* socket.emit("foo", "bar");
*
* socket.on("foobar", () => {
* // an event was received from the client
* });
*
* // join the room named "room1"
* socket.join("room1");
*
* // broadcast to everyone in the room named "room1"
* io.to("room1").emit("hello");
*
* // upon disconnection
* socket.on("disconnect", (reason) => {
* console.log(`socket ${socket.id} disconnected due to ${reason}`);
* });
* });
*/
class Socket extends typed_events_1.StrictEventEmitter {
/**
* Interface to a `Client` for a given `Namespace`.
*
* @param {Namespace} nsp
* @param {Client} client
* @param {Object} auth
* @package
*/
constructor(nsp, client, auth, previousSession) {
super();
this.nsp = nsp;
this.client = client;
/**
* Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will
* be transmitted to the client, the data attribute and the rooms will be restored.
*/
this.recovered = false;
/**
* Additional information that can be attached to the Socket instance and which will be used in the
* {@link Server.fetchSockets()} method.
*/
this.data = {};
/**
* Whether the socket is currently connected or not.
*
* @example
* io.use((socket, next) => {
* console.log(socket.connected); // false
* next();
* });
*
* io.on("connection", (socket) => {
* console.log(socket.connected); // true
* });
*/
this.connected = false;
this.acks = new Map();
this.fns = [];
this.flags = {};
this.server = nsp.server;
this.adapter = this.nsp.adapter;
if (previousSession) {
this.id = previousSession.sid;
this.pid = previousSession.pid;
previousSession.rooms.forEach((room) => this.join(room));
this.data = previousSession.data;
previousSession.missedPackets.forEach((packet) => {
this.packet({
type: socket_io_parser_1.PacketType.EVENT,
data: packet,
});
});
this.recovered = true;
}
else {
if (client.conn.protocol === 3) {
// @ts-ignore
this.id = nsp.name !== "/" ? nsp.name + "#" + client.id : client.id;
}
else {
this.id = base64id_1.default.generateId(); // don't reuse the Engine.IO id because it's sensitive information
}
if (this.server._opts.connectionStateRecovery) {
this.pid = base64id_1.default.generateId();
}
}
this.handshake = this.buildHandshake(auth);
// prevents crash when the socket receives an "error" event without listener
this.on("error", noop);
}
/**
* Builds the `handshake` BC object
*
* @private
*/
buildHandshake(auth) {
var _a, _b, _c, _d;
return {
headers: ((_a = this.request) === null || _a === void 0 ? void 0 : _a.headers) || {},
time: new Date() + "",
address: this.conn.remoteAddress,
xdomain: !!((_b = this.request) === null || _b === void 0 ? void 0 : _b.headers.origin),
// @ts-ignore
secure: !this.request || !!this.request.connection.encrypted,
issued: +new Date(),
url: (_c = this.request) === null || _c === void 0 ? void 0 : _c.url,
// @ts-ignore
query: ((_d = this.request) === null || _d === void 0 ? void 0 : _d._query) || {},
auth,
};
}
/**
* Emits to this client.
*
* @example
* io.on("connection", (socket) => {
* socket.emit("hello", "world");
*
* // all serializable datastructures are supported (no need to call JSON.stringify)
* socket.emit("hello", 1, "2", { 3: ["4"], 5: Buffer.from([6]) });
*
* // with an acknowledgement from the client
* socket.emit("hello", "world", (val) => {
* // ...
* });
* });
*
* @return Always returns `true`.
*/
emit(ev, ...args) {
if (exports.RESERVED_EVENTS.has(ev)) {
throw new Error(`"${String(ev)}" is a reserved event name`);
}
const data = [ev, ...args];
const packet = {
type: socket_io_parser_1.PacketType.EVENT,
data: data,
};
// access last argument to see if it's an ACK callback
if (typeof data[data.length - 1] === "function") {
const id = this.nsp._ids++;
debug("emitting packet with ack id %d", id);
this.registerAckCallback(id, data.pop());
packet.id = id;
}
const flags = Object.assign({}, this.flags);
this.flags = {};
// @ts-ignore
if (this.nsp.server.opts.connectionStateRecovery) {
// this ensures the packet is stored and can be transmitted upon reconnection
this.adapter.broadcast(packet, {
rooms: new Set([this.id]),
except: new Set(),
flags,
});
}
else {
this.notifyOutgoingListeners(packet);
this.packet(packet, flags);
}
return true;
}
/**
* Emits an event and waits for an acknowledgement
*
* @example
* io.on("connection", async (socket) => {
* // without timeout
* const response = await socket.emitWithAck("hello", "world");
*
* // with a specific timeout
* try {
* const response = await socket.timeout(1000).emitWithAck("hello", "world");
* } catch (err) {
* // the client did not acknowledge the event in the given delay
* }
* });
*
* @return a Promise that will be fulfilled when the client acknowledges the event
*/
emitWithAck(ev, ...args) {
// the timeout flag is optional
const withErr = this.flags.timeout !== undefined;
return new Promise((resolve, reject) => {
args.push((arg1, arg2) => {
if (withErr) {
return arg1 ? reject(arg1) : resolve(arg2);
}
else {
return resolve(arg1);
}
});
this.emit(ev, ...args);
});
}
/**
* @private
*/
registerAckCallback(id, ack) {
const timeout = this.flags.timeout;
if (timeout === undefined) {
this.acks.set(id, ack);
return;
}
const timer = setTimeout(() => {
debug("event with ack id %d has timed out after %d ms", id, timeout);
this.acks.delete(id);
ack.call(this, new Error("operation has timed out"));
}, timeout);
this.acks.set(id, (...args) => {
clearTimeout(timer);
ack.apply(this, [null, ...args]);
});
}
/**
* Targets a room when broadcasting.
*
* @example
* io.on("connection", (socket) => {
* // the “foo” event will be broadcast to all connected clients in the “room-101” room, except this socket
* socket.to("room-101").emit("foo", "bar");
*
* // the code above is equivalent to:
* io.to("room-101").except(socket.id).emit("foo", "bar");
*
* // with an array of rooms (a client will be notified at most once)
* socket.to(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* socket.to("room-101").to("room-102").emit("foo", "bar");
* });
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
to(room) {
return this.newBroadcastOperator().to(room);
}
/**
* Targets a room when broadcasting. Similar to `to()`, but might feel clearer in some cases:
*
* @example
* io.on("connection", (socket) => {
* // disconnect all clients in the "room-101" room, except this socket
* socket.in("room-101").disconnectSockets();
* });
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
in(room) {
return this.newBroadcastOperator().in(room);
}
/**
* Excludes a room when broadcasting.
*
* @example
* io.on("connection", (socket) => {
* // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
* // and this socket
* socket.except("room-101").emit("foo", "bar");
*
* // with an array of rooms
* socket.except(["room-101", "room-102"]).emit("foo", "bar");
*
* // with multiple chained calls
* socket.except("room-101").except("room-102").emit("foo", "bar");
* });
*
* @param room - a room, or an array of rooms
* @return a new {@link BroadcastOperator} instance for chaining
*/
except(room) {
return this.newBroadcastOperator().except(room);
}
/**
* Sends a `message` event.
*
* This method mimics the WebSocket.send() method.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
*
* @example
* io.on("connection", (socket) => {
* socket.send("hello");
*
* // this is equivalent to
* socket.emit("message", "hello");
* });
*
* @return self
*/
send(...args) {
this.emit("message", ...args);
return this;
}
/**
* Sends a `message` event. Alias of {@link send}.
*
* @return self
*/
write(...args) {
this.emit("message", ...args);
return this;
}
/**
* Writes a packet.
*
* @param {Object} packet - packet object
* @param {Object} opts - options
* @private
*/
packet(packet, opts = {}) {
packet.nsp = this.nsp.name;
opts.compress = false !== opts.compress;
this.client._packet(packet, opts);
}
/**
* Joins a room.
*
* @example
* io.on("connection", (socket) => {
* // join a single room
* socket.join("room1");
*
* // join multiple rooms
* socket.join(["room1", "room2"]);
* });
*
* @param {String|Array} rooms - room or array of rooms
* @return a Promise or nothing, depending on the adapter
*/
join(rooms) {
debug("join room %s", rooms);
return this.adapter.addAll(this.id, new Set(Array.isArray(rooms) ? rooms : [rooms]));
}
/**
* Leaves a room.
*
* @example
* io.on("connection", (socket) => {
* // leave a single room
* socket.leave("room1");
*
* // leave multiple rooms
* socket.leave("room1").leave("room2");
* });
*
* @param {String} room
* @return a Promise or nothing, depending on the adapter
*/
leave(room) {
debug("leave room %s", room);
return this.adapter.del(this.id, room);
}
/**
* Leave all rooms.
*
* @private
*/
leaveAll() {
this.adapter.delAll(this.id);
}
/**
* Called by `Namespace` upon successful
* middleware execution (ie: authorization).
* Socket is added to namespace array before
* call to join, so adapters can access it.
*
* @private
*/
_onconnect() {
debug("socket connected - writing packet");
this.connected = true;
this.join(this.id);
if (this.conn.protocol === 3) {
this.packet({ type: socket_io_parser_1.PacketType.CONNECT });
}
else {
this.packet({
type: socket_io_parser_1.PacketType.CONNECT,
data: { sid: this.id, pid: this.pid },
});
}
}
/**
* Called with each packet. Called by `Client`.
*
* @param {Object} packet
* @private
*/
_onpacket(packet) {
debug("got packet %j", packet);
switch (packet.type) {
case socket_io_parser_1.PacketType.EVENT:
this.onevent(packet);
break;
case socket_io_parser_1.PacketType.BINARY_EVENT:
this.onevent(packet);
break;
case socket_io_parser_1.PacketType.ACK:
this.onack(packet);
break;
case socket_io_parser_1.PacketType.BINARY_ACK:
this.onack(packet);
break;
case socket_io_parser_1.PacketType.DISCONNECT:
this.ondisconnect();
break;
}
}
/**
* Called upon event packet.
*
* @param {Packet} packet - packet object
* @private
*/
onevent(packet) {
const args = packet.data || [];
debug("emitting event %j", args);
if (null != packet.id) {
debug("attaching ack callback to event");
args.push(this.ack(packet.id));
}
if (this._anyListeners && this._anyListeners.length) {
const listeners = this._anyListeners.slice();
for (const listener of listeners) {
listener.apply(this, args);
}
}
this.dispatch(args);
}
/**
* Produces an ack callback to emit with an event.
*
* @param {Number} id - packet id
* @private
*/
ack(id) {
const self = this;
let sent = false;
return function () {
// prevent double callbacks
if (sent)
return;
const args = Array.prototype.slice.call(arguments);
debug("sending ack %j", args);
self.packet({
id: id,
type: socket_io_parser_1.PacketType.ACK,
data: args,
});
sent = true;
};
}
/**
* Called upon ack packet.
*
* @private
*/
onack(packet) {
const ack = this.acks.get(packet.id);
if ("function" == typeof ack) {
debug("calling ack %s with %j", packet.id, packet.data);
ack.apply(this, packet.data);
this.acks.delete(packet.id);
}
else {
debug("bad ack %s", packet.id);
}
}
/**
* Called upon client disconnect packet.
*
* @private
*/
ondisconnect() {
debug("got disconnect packet");
this._onclose("client namespace disconnect");
}
/**
* Handles a client error.
*
* @private
*/
_onerror(err) {
// FIXME the meaning of the "error" event is overloaded:
// - it can be sent by the client (`socket.emit("error")`)
// - it can be emitted when the connection encounters an error (an invalid packet for example)
// - it can be emitted when a packet is rejected in a middleware (`socket.use()`)
this.emitReserved("error", err);
}
/**
* Called upon closing. Called by `Client`.
*
* @param {String} reason
* @param description
* @throw {Error} optional error object
*
* @private
*/
_onclose(reason, description) {
if (!this.connected)
return this;
debug("closing socket - reason %s", reason);
this.emitReserved("disconnecting", reason, description);
if (this.server._opts.connectionStateRecovery &&
RECOVERABLE_DISCONNECT_REASONS.has(reason)) {
debug("connection state recovery is enabled for sid %s", this.id);
this.adapter.persistSession({
sid: this.id,
pid: this.pid,
rooms: [...this.rooms],
data: this.data,
});
}
this._cleanup();
this.client._remove(this);
this.connected = false;
this.emitReserved("disconnect", reason, description);
return;
}
/**
* Makes the socket leave all the rooms it was part of and prevents it from joining any other room
*
* @private
*/
_cleanup() {
this.leaveAll();
this.nsp._remove(this);
this.join = noop;
}
/**
* Produces an `error` packet.
*
* @param {Object} err - error object
*
* @private
*/
_error(err) {
this.packet({ type: socket_io_parser_1.PacketType.CONNECT_ERROR, data: err });
}
/**
* Disconnects this client.
*
* @example
* io.on("connection", (socket) => {
* // disconnect this socket (the connection might be kept alive for other namespaces)
* socket.disconnect();
*
* // disconnect this socket and close the underlying connection
* socket.disconnect(true);
* })
*
* @param {Boolean} close - if `true`, closes the underlying connection
* @return self
*/
disconnect(close = false) {
if (!this.connected)
return this;
if (close) {
this.client._disconnect();
}
else {
this.packet({ type: socket_io_parser_1.PacketType.DISCONNECT });
this._onclose("server namespace disconnect");
}
return this;
}
/**
* Sets the compress flag.
*
* @example
* io.on("connection", (socket) => {
* socket.compress(false).emit("hello");
* });
*
* @param {Boolean} compress - if `true`, compresses the sending data
* @return {Socket} self
*/
compress(compress) {
this.flags.compress = compress;
return this;
}
/**
* Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
* receive messages (because of network slowness or other issues, or because theyre connected through long polling
* and is in the middle of a request-response cycle).
*
* @example
* io.on("connection", (socket) => {
* socket.volatile.emit("hello"); // the client may or may not receive it
* });
*
* @return {Socket} self
*/
get volatile() {
this.flags.volatile = true;
return this;
}
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to every sockets but the
* sender.
*
* @example
* io.on("connection", (socket) => {
* // the “foo” event will be broadcast to all connected clients, except this socket
* socket.broadcast.emit("foo", "bar");
* });
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get broadcast() {
return this.newBroadcastOperator();
}
/**
* Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
*
* @example
* io.on("connection", (socket) => {
* // the “foo” event will be broadcast to all connected clients on this node, except this socket
* socket.local.emit("foo", "bar");
* });
*
* @return a new {@link BroadcastOperator} instance for chaining
*/
get local() {
return this.newBroadcastOperator().local;
}
/**
* Sets a modifier for a subsequent event emission that the callback will be called with an error when the
* given number of milliseconds have elapsed without an acknowledgement from the client:
*
* @example
* io.on("connection", (socket) => {
* socket.timeout(5000).emit("my-event", (err) => {
* if (err) {
* // the client did not acknowledge the event in the given delay
* }
* });
* });
*
* @returns self
*/
timeout(timeout) {
this.flags.timeout = timeout;
return this;
}
/**
* Dispatch incoming event to socket listeners.
*
* @param {Array} event - event that will get emitted
* @private
*/
dispatch(event) {
debug("dispatching an event %j", event);
this.run(event, (err) => {
process.nextTick(() => {
if (err) {
return this._onerror(err);
}
if (this.connected) {
super.emitUntyped.apply(this, event);
}
else {
debug("ignore packet received after disconnection");
}
});
});
}
/**
* Sets up socket middleware.
*
* @example
* io.on("connection", (socket) => {
* socket.use(([event, ...args], next) => {
* if (isUnauthorized(event)) {
* return next(new Error("unauthorized event"));
* }
* // do not forget to call next
* next();
* });
*
* socket.on("error", (err) => {
* if (err && err.message === "unauthorized event") {
* socket.disconnect();
* }
* });
* });
*
* @param {Function} fn - middleware function (event, next)
* @return {Socket} self
*/
use(fn) {
this.fns.push(fn);
return this;
}
/**
* Executes the middleware for an incoming event.
*
* @param {Array} event - event that will get emitted
* @param {Function} fn - last fn call in the middleware
* @private
*/
run(event, fn) {
const fns = this.fns.slice(0);
if (!fns.length)
return fn(null);
function run(i) {
fns[i](event, function (err) {
// upon error, short-circuit
if (err)
return fn(err);
// if no middleware left, summon callback
if (!fns[i + 1])
return fn(null);
// go on to next
run(i + 1);
});
}
run(0);
}
/**
* Whether the socket is currently disconnected
*/
get disconnected() {
return !this.connected;
}
/**
* A reference to the request that originated the underlying Engine.IO Socket.
*/
get request() {
return this.client.request;
}
/**
* A reference to the underlying Client transport connection (Engine.IO Socket object).
*
* @example
* io.on("connection", (socket) => {
* console.log(socket.conn.transport.name); // prints "polling" or "websocket"
*
* socket.conn.once("upgrade", () => {
* console.log(socket.conn.transport.name); // prints "websocket"
* });
* });
*/
get conn() {
return this.client.conn;
}
/**
* Returns the rooms the socket is currently in.
*
* @example
* io.on("connection", (socket) => {
* console.log(socket.rooms); // Set { <socket.id> }
*
* socket.join("room1");
*
* console.log(socket.rooms); // Set { <socket.id>, "room1" }
* });
*/
get rooms() {
return this.adapter.socketRooms(this.id) || new Set();
}
/**
* Adds a listener that will be fired when any event is received. The event name is passed as the first argument to
* the callback.
*
* @example
* io.on("connection", (socket) => {
* socket.onAny((event, ...args) => {
* console.log(`got event ${event}`);
* });
* });
*
* @param listener
*/
onAny(listener) {
this._anyListeners = this._anyListeners || [];
this._anyListeners.push(listener);
return this;
}
/**
* Adds a listener that will be fired when any event is received. The event name is passed as the first argument to
* the callback. The listener is added to the beginning of the listeners array.
*
* @param listener
*/
prependAny(listener) {
this._anyListeners = this._anyListeners || [];
this._anyListeners.unshift(listener);
return this;
}
/**
* Removes the listener that will be fired when any event is received.
*
* @example
* io.on("connection", (socket) => {
* const catchAllListener = (event, ...args) => {
* console.log(`got event ${event}`);
* }
*
* socket.onAny(catchAllListener);
*
* // remove a specific listener
* socket.offAny(catchAllListener);
*
* // or remove all listeners
* socket.offAny();
* });
*
* @param listener
*/
offAny(listener) {
if (!this._anyListeners) {
return this;
}
if (listener) {
const listeners = this._anyListeners;
for (let i = 0; i < listeners.length; i++) {
if (listener === listeners[i]) {
listeners.splice(i, 1);
return this;
}
}
}
else {
this._anyListeners = [];
}
return this;
}
/**
* Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
* e.g. to remove listeners.
*/
listenersAny() {
return this._anyListeners || [];
}
/**
* Adds a listener that will be fired when any event is sent. The event name is passed as the first argument to
* the callback.
*
* Note: acknowledgements sent to the client are not included.
*
* @example
* io.on("connection", (socket) => {
* socket.onAnyOutgoing((event, ...args) => {
* console.log(`sent event ${event}`);
* });
* });
*
* @param listener
*/
onAnyOutgoing(listener) {
this._anyOutgoingListeners = this._anyOutgoingListeners || [];
this._anyOutgoingListeners.push(listener);
return this;
}
/**
* Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
* callback. The listener is added to the beginning of the listeners array.
*
* @example
* io.on("connection", (socket) => {
* socket.prependAnyOutgoing((event, ...args) => {
* console.log(`sent event ${event}`);
* });
* });
*
* @param listener
*/
prependAnyOutgoing(listener) {
this._anyOutgoingListeners = this._anyOutgoingListeners || [];
this._anyOutgoingListeners.unshift(listener);
return this;
}
/**
* Removes the listener that will be fired when any event is sent.
*
* @example
* io.on("connection", (socket) => {
* const catchAllListener = (event, ...args) => {
* console.log(`sent event ${event}`);
* }
*
* socket.onAnyOutgoing(catchAllListener);
*
* // remove a specific listener
* socket.offAnyOutgoing(catchAllListener);
*
* // or remove all listeners
* socket.offAnyOutgoing();
* });
*
* @param listener - the catch-all listener
*/
offAnyOutgoing(listener) {
if (!this._anyOutgoingListeners) {
return this;
}
if (listener) {
const listeners = this._anyOutgoingListeners;
for (let i = 0; i < listeners.length; i++) {
if (listener === listeners[i]) {
listeners.splice(i, 1);
return this;
}
}
}
else {
this._anyOutgoingListeners = [];
}
return this;
}
/**
* Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
* e.g. to remove listeners.
*/
listenersAnyOutgoing() {
return this._anyOutgoingListeners || [];
}
/**
* Notify the listeners for each packet sent (emit or broadcast)
*
* @param packet
*
* @private
*/
notifyOutgoingListeners(packet) {
if (this._anyOutgoingListeners && this._anyOutgoingListeners.length) {
const listeners = this._anyOutgoingListeners.slice();
for (const listener of listeners) {
listener.apply(this, packet.data);
}
}
}
newBroadcastOperator() {
const flags = Object.assign({}, this.flags);
this.flags = {};
return new broadcast_operator_1.BroadcastOperator(this.adapter, new Set(), new Set([this.id]), flags);
}
}
exports.Socket = Socket;

204
node_modules/socket.io/dist/typed-events.d.ts generated vendored Normal file
View File

@ -0,0 +1,204 @@
/// <reference types="node" />
import { EventEmitter } from "events";
/**
* An events map is an interface that maps event names to their value, which
* represents the type of the `on` listener.
*/
export interface EventsMap {
[event: string]: any;
}
/**
* The default events map, used if no EventsMap is given. Using this EventsMap
* is equivalent to accepting all event names, and any data.
*/
export interface DefaultEventsMap {
[event: string]: (...args: any[]) => void;
}
/**
* Returns a union type containing all the keys of an event map.
*/
export declare type EventNames<Map extends EventsMap> = keyof Map & (string | symbol);
/**
* Returns a union type containing all the keys of an event map that have an acknowledgement callback.
*
* That also have *some* data coming in.
*/
export declare type EventNamesWithAck<Map extends EventsMap, K extends EventNames<Map> = EventNames<Map>> = IfAny<Last<Parameters<Map[K]>> | Map[K], K, K extends (Last<Parameters<Map[K]>> extends (...args: any[]) => any ? FirstNonErrorArg<Last<Parameters<Map[K]>>> extends void ? never : K : never) ? K : never>;
/**
* Returns a union type containing all the keys of an event map that have an acknowledgement callback.
*
* That also have *some* data coming in.
*/
export declare type EventNamesWithoutAck<Map extends EventsMap, K extends EventNames<Map> = EventNames<Map>> = IfAny<Last<Parameters<Map[K]>> | Map[K], K, K extends (Parameters<Map[K]> extends never[] ? K : never) ? K : K extends (Last<Parameters<Map[K]>> extends (...args: any[]) => any ? never : K) ? K : never>;
export declare type RemoveAcknowledgements<E extends EventsMap> = {
[K in EventNamesWithoutAck<E>]: E[K];
};
export declare type EventNamesWithError<Map extends EventsMap, K extends EventNamesWithAck<Map> = EventNamesWithAck<Map>> = IfAny<Last<Parameters<Map[K]>> | Map[K], K, K extends (LooseParameters<Last<Parameters<Map[K]>>>[0] extends Error ? K : never) ? K : never>;
/** The tuple type representing the parameters of an event listener */
export declare type EventParams<Map extends EventsMap, Ev extends EventNames<Map>> = Parameters<Map[Ev]>;
/**
* The event names that are either in ReservedEvents or in UserEvents
*/
export declare type ReservedOrUserEventNames<ReservedEventsMap extends EventsMap, UserEvents extends EventsMap> = EventNames<ReservedEventsMap> | EventNames<UserEvents>;
/**
* Type of a listener of a user event or a reserved event. If `Ev` is in
* `ReservedEvents`, the reserved event listener is returned.
*/
export declare type ReservedOrUserListener<ReservedEvents extends EventsMap, UserEvents extends EventsMap, Ev extends ReservedOrUserEventNames<ReservedEvents, UserEvents>> = FallbackToUntypedListener<Ev extends EventNames<ReservedEvents> ? ReservedEvents[Ev] : Ev extends EventNames<UserEvents> ? UserEvents[Ev] : never>;
/**
* Returns an untyped listener type if `T` is `never`; otherwise, returns `T`.
*
* This is a hack to mitigate https://github.com/socketio/socket.io/issues/3833.
* Needed because of https://github.com/microsoft/TypeScript/issues/41778
*/
declare type FallbackToUntypedListener<T> = [T] extends [never] ? (...args: any[]) => void | Promise<void> : T;
/**
* Interface for classes that aren't `EventEmitter`s, but still expose a
* strictly typed `emit` method.
*/
export interface TypedEventBroadcaster<EmitEvents extends EventsMap> {
emit<Ev extends EventNames<EmitEvents>>(ev: Ev, ...args: EventParams<EmitEvents, Ev>): boolean;
}
/**
* Strictly typed version of an `EventEmitter`. A `TypedEventEmitter` takes type
* parameters for mappings of event names to event data types, and strictly
* types method calls to the `EventEmitter` according to these event maps.
*
* @typeParam ListenEvents - `EventsMap` of user-defined events that can be
* listened to with `on` or `once`
* @typeParam EmitEvents - `EventsMap` of user-defined events that can be
* emitted with `emit`
* @typeParam ReservedEvents - `EventsMap` of reserved events, that can be
* emitted by socket.io with `emitReserved`, and can be listened to with
* `listen`.
*/
export declare abstract class StrictEventEmitter<ListenEvents extends EventsMap, EmitEvents extends EventsMap, ReservedEvents extends EventsMap = {}> extends EventEmitter implements TypedEventBroadcaster<EmitEvents> {
/**
* Adds the `listener` function as an event listener for `ev`.
*
* @param ev Name of the event
* @param listener Callback function
*/
on<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(ev: Ev, listener: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>): this;
/**
* Adds a one-time `listener` function as an event listener for `ev`.
*
* @param ev Name of the event
* @param listener Callback function
*/
once<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(ev: Ev, listener: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>): this;
/**
* Emits an event.
*
* @param ev Name of the event
* @param args Values to send to listeners of this event
*/
emit<Ev extends EventNames<EmitEvents>>(ev: Ev, ...args: EventParams<EmitEvents, Ev>): boolean;
/**
* Emits a reserved event.
*
* This method is `protected`, so that only a class extending
* `StrictEventEmitter` can emit its own reserved events.
*
* @param ev Reserved event name
* @param args Arguments to emit along with the event
*/
protected emitReserved<Ev extends EventNames<ReservedEvents>>(ev: Ev, ...args: EventParams<ReservedEvents, Ev>): boolean;
/**
* Emits an event.
*
* This method is `protected`, so that only a class extending
* `StrictEventEmitter` can get around the strict typing. This is useful for
* calling `emit.apply`, which can be called as `emitUntyped.apply`.
*
* @param ev Event name
* @param args Arguments to emit along with the event
*/
protected emitUntyped(ev: string, ...args: any[]): boolean;
/**
* Returns the listeners listening to an event.
*
* @param event Event name
* @returns Array of listeners subscribed to `event`
*/
listeners<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(event: Ev): ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>[];
}
/**
* Returns a boolean for whether the given type is `any`.
*
* @link https://stackoverflow.com/a/49928360/1490091
*
* Useful in type utilities, such as disallowing `any`s to be passed to a function.
*
* @author sindresorhus
* @link https://github.com/sindresorhus/type-fest
*/
declare type IsAny<T> = 0 extends 1 & T ? true : false;
/**
* An if-else-like type that resolves depending on whether the given type is `any`.
*
* @see {@link IsAny}
*
* @author sindresorhus
* @link https://github.com/sindresorhus/type-fest
*/
declare type IfAny<T, TypeIfAny = true, TypeIfNotAny = false> = IsAny<T> extends true ? TypeIfAny : TypeIfNotAny;
/**
* Extracts the type of the last element of an array.
*
* Use-case: Defining the return type of functions that extract the last element of an array, for example [`lodash.last`](https://lodash.com/docs/4.17.15#last).
*
* @author sindresorhus
* @link https://github.com/sindresorhus/type-fest
*/
export declare type Last<ValueType extends readonly unknown[]> = ValueType extends readonly [infer ElementType] ? ElementType : ValueType extends readonly [infer _, ...infer Tail] ? Last<Tail> : ValueType extends ReadonlyArray<infer ElementType> ? ElementType : never;
export declare type FirstNonErrorTuple<T extends unknown[]> = T[0] extends Error ? T[1] : T[0];
export declare type AllButLast<T extends any[]> = T extends [...infer H, infer L] ? H : any[];
/**
* Like `Parameters<T>`, but doesn't require `T` to be a function ahead of time.
*/
declare type LooseParameters<T> = T extends (...args: infer P) => any ? P : never;
export declare type FirstNonErrorArg<T> = T extends (...args: infer Params) => any ? FirstNonErrorTuple<Params> : any;
declare type PrependTimeoutError<T extends any[]> = {
[K in keyof T]: T[K] extends (...args: infer Params) => infer Result ? Params[0] extends Error ? T[K] : (err: Error, ...args: Params) => Result : T[K];
};
export declare type MultiplyArray<T extends unknown[]> = {
[K in keyof T]: T[K][];
};
declare type InferFirstAndPreserveLabel<T extends any[]> = T extends [any, ...infer R] ? T extends [...infer H, ...R] ? H : never : never;
/**
* Utility type to decorate the acknowledgement callbacks multiple values
* on the first non error element while removing any elements after
*/
declare type ExpectMultipleResponses<T extends any[]> = {
[K in keyof T]: T[K] extends (...args: infer Params) => infer Result ? Params extends [Error] ? (err: Error) => Result : Params extends [Error, ...infer Rest] ? (err: Error, ...args: InferFirstAndPreserveLabel<MultiplyArray<Rest>>) => Result : Params extends [] ? () => Result : (...args: InferFirstAndPreserveLabel<MultiplyArray<Params>>) => Result : T[K];
};
/**
* Utility type to decorate the acknowledgement callbacks with a timeout error.
*
* This is needed because the timeout() flag breaks the symmetry between the sender and the receiver:
*
* @example
* interface Events {
* "my-event": (val: string) => void;
* }
*
* socket.on("my-event", (cb) => {
* cb("123"); // one single argument here
* });
*
* socket.timeout(1000).emit("my-event", (err, val) => {
* // two arguments there (the "err" argument is not properly typed)
* });
*
*/
export declare type DecorateAcknowledgements<E> = {
[K in keyof E]: E[K] extends (...args: infer Params) => infer Result ? (...args: PrependTimeoutError<Params>) => Result : E[K];
};
export declare type DecorateAcknowledgementsWithTimeoutAndMultipleResponses<E> = {
[K in keyof E]: E[K] extends (...args: infer Params) => infer Result ? (...args: ExpectMultipleResponses<PrependTimeoutError<Params>>) => Result : E[K];
};
export declare type DecorateAcknowledgementsWithMultipleResponses<E> = {
[K in keyof E]: E[K] extends (...args: infer Params) => infer Result ? (...args: ExpectMultipleResponses<Params>) => Result : E[K];
};
export {};

81
node_modules/socket.io/dist/typed-events.js generated vendored Normal file
View File

@ -0,0 +1,81 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StrictEventEmitter = void 0;
const events_1 = require("events");
/**
* Strictly typed version of an `EventEmitter`. A `TypedEventEmitter` takes type
* parameters for mappings of event names to event data types, and strictly
* types method calls to the `EventEmitter` according to these event maps.
*
* @typeParam ListenEvents - `EventsMap` of user-defined events that can be
* listened to with `on` or `once`
* @typeParam EmitEvents - `EventsMap` of user-defined events that can be
* emitted with `emit`
* @typeParam ReservedEvents - `EventsMap` of reserved events, that can be
* emitted by socket.io with `emitReserved`, and can be listened to with
* `listen`.
*/
class StrictEventEmitter extends events_1.EventEmitter {
/**
* Adds the `listener` function as an event listener for `ev`.
*
* @param ev Name of the event
* @param listener Callback function
*/
on(ev, listener) {
return super.on(ev, listener);
}
/**
* Adds a one-time `listener` function as an event listener for `ev`.
*
* @param ev Name of the event
* @param listener Callback function
*/
once(ev, listener) {
return super.once(ev, listener);
}
/**
* Emits an event.
*
* @param ev Name of the event
* @param args Values to send to listeners of this event
*/
emit(ev, ...args) {
return super.emit(ev, ...args);
}
/**
* Emits a reserved event.
*
* This method is `protected`, so that only a class extending
* `StrictEventEmitter` can emit its own reserved events.
*
* @param ev Reserved event name
* @param args Arguments to emit along with the event
*/
emitReserved(ev, ...args) {
return super.emit(ev, ...args);
}
/**
* Emits an event.
*
* This method is `protected`, so that only a class extending
* `StrictEventEmitter` can get around the strict typing. This is useful for
* calling `emit.apply`, which can be called as `emitUntyped.apply`.
*
* @param ev Event name
* @param args Arguments to emit along with the event
*/
emitUntyped(ev, ...args) {
return super.emit(ev, ...args);
}
/**
* Returns the listeners listening to an event.
*
* @param event Event name
* @returns Array of listeners subscribed to `event`
*/
listeners(event) {
return super.listeners(event);
}
}
exports.StrictEventEmitter = StrictEventEmitter;

3
node_modules/socket.io/dist/uws.d.ts generated vendored Normal file
View File

@ -0,0 +1,3 @@
export declare function patchAdapter(app: any): void;
export declare function restoreAdapter(): void;
export declare function serveFile(res: any, filepath: string): void;

135
node_modules/socket.io/dist/uws.js generated vendored Normal file
View File

@ -0,0 +1,135 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.serveFile = exports.restoreAdapter = exports.patchAdapter = void 0;
const socket_io_adapter_1 = require("socket.io-adapter");
const fs_1 = require("fs");
const debug_1 = __importDefault(require("debug"));
const debug = (0, debug_1.default)("socket.io:adapter-uws");
const SEPARATOR = "\x1f"; // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text
const { addAll, del, broadcast } = socket_io_adapter_1.Adapter.prototype;
function patchAdapter(app /* : TemplatedApp */) {
socket_io_adapter_1.Adapter.prototype.addAll = function (id, rooms) {
const isNew = !this.sids.has(id);
addAll.call(this, id, rooms);
const socket = this.nsp.sockets.get(id);
if (!socket) {
return;
}
if (socket.conn.transport.name === "websocket") {
subscribe(this.nsp.name, socket, isNew, rooms);
return;
}
if (isNew) {
socket.conn.on("upgrade", () => {
const rooms = this.sids.get(id);
if (rooms) {
subscribe(this.nsp.name, socket, isNew, rooms);
}
});
}
};
socket_io_adapter_1.Adapter.prototype.del = function (id, room) {
del.call(this, id, room);
const socket = this.nsp.sockets.get(id);
if (socket && socket.conn.transport.name === "websocket") {
// @ts-ignore
const sessionId = socket.conn.id;
// @ts-ignore
const websocket = socket.conn.transport.socket;
const topic = `${this.nsp.name}${SEPARATOR}${room}`;
debug("unsubscribe connection %s from topic %s", sessionId, topic);
websocket.unsubscribe(topic);
}
};
socket_io_adapter_1.Adapter.prototype.broadcast = function (packet, opts) {
const useFastPublish = opts.rooms.size <= 1 && opts.except.size === 0;
if (!useFastPublish) {
broadcast.call(this, packet, opts);
return;
}
const flags = opts.flags || {};
const basePacketOpts = {
preEncoded: true,
volatile: flags.volatile,
compress: flags.compress,
};
packet.nsp = this.nsp.name;
const encodedPackets = this.encoder.encode(packet);
const topic = opts.rooms.size === 0
? this.nsp.name
: `${this.nsp.name}${SEPARATOR}${opts.rooms.keys().next().value}`;
debug("fast publish to %s", topic);
// fast publish for clients connected with WebSocket
encodedPackets.forEach((encodedPacket) => {
const isBinary = typeof encodedPacket !== "string";
// "4" being the message type in the Engine.IO protocol, see https://github.com/socketio/engine.io-protocol
app.publish(topic, isBinary ? encodedPacket : "4" + encodedPacket, isBinary);
});
this.apply(opts, (socket) => {
if (socket.conn.transport.name !== "websocket") {
// classic publish for clients connected with HTTP long-polling
socket.client.writeToEngine(encodedPackets, basePacketOpts);
}
});
};
}
exports.patchAdapter = patchAdapter;
function subscribe(namespaceName, socket, isNew, rooms) {
// @ts-ignore
const sessionId = socket.conn.id;
// @ts-ignore
const websocket = socket.conn.transport.socket;
if (isNew) {
debug("subscribe connection %s to topic %s", sessionId, namespaceName);
websocket.subscribe(namespaceName);
}
rooms.forEach((room) => {
const topic = `${namespaceName}${SEPARATOR}${room}`; // '#' can be used as wildcard
debug("subscribe connection %s to topic %s", sessionId, topic);
websocket.subscribe(topic);
});
}
function restoreAdapter() {
socket_io_adapter_1.Adapter.prototype.addAll = addAll;
socket_io_adapter_1.Adapter.prototype.del = del;
socket_io_adapter_1.Adapter.prototype.broadcast = broadcast;
}
exports.restoreAdapter = restoreAdapter;
const toArrayBuffer = (buffer) => {
const { buffer: arrayBuffer, byteOffset, byteLength } = buffer;
return arrayBuffer.slice(byteOffset, byteOffset + byteLength);
};
// imported from https://github.com/kolodziejczak-sz/uwebsocket-serve
function serveFile(res /* : HttpResponse */, filepath) {
const { size } = (0, fs_1.statSync)(filepath);
const readStream = (0, fs_1.createReadStream)(filepath);
const destroyReadStream = () => !readStream.destroyed && readStream.destroy();
const onError = (error) => {
destroyReadStream();
throw error;
};
const onDataChunk = (chunk) => {
const arrayBufferChunk = toArrayBuffer(chunk);
const lastOffset = res.getWriteOffset();
const [ok, done] = res.tryEnd(arrayBufferChunk, size);
if (!done && !ok) {
readStream.pause();
res.onWritable((offset) => {
const [ok, done] = res.tryEnd(arrayBufferChunk.slice(offset - lastOffset), size);
if (!done && ok) {
readStream.resume();
}
return ok;
});
}
};
res.onAborted(destroyReadStream);
readStream
.on("data", onDataChunk)
.on("error", onError)
.on("end", destroyReadStream);
}
exports.serveFile = serveFile;