From fe8730ca0f15bc92d5de81cf934c89c76d6af329 Mon Sep 17 00:00:00 2001 From: Nikita Kolmogorov Date: Mon, 8 Nov 2021 06:21:48 -0800 Subject: [PATCH] feat: add type information to `socket.data` (#4159) Usage: ```js interface SocketData { name: string; age: number; } const io = new Server(); io.on("connection", (socket) => { socket.data.name = "john"; socket.data.age = 42; }); ``` --- lib/client.ts | 22 +++++++++++------ lib/index.ts | 19 +++++++++++---- lib/namespace.ts | 52 +++++++++++++++++++++++++++-------------- lib/parent-namespace.ts | 16 ++++++++----- lib/socket.ts | 14 +++++++---- 5 files changed, 84 insertions(+), 39 deletions(-) diff --git a/lib/client.ts b/lib/client.ts index 8b9db02532..2db890fe5e 100644 --- a/lib/client.ts +++ b/lib/client.ts @@ -21,21 +21,27 @@ interface WriteOptions { export class Client< ListenEvents extends EventsMap, EmitEvents extends EventsMap, - ServerSideEvents extends EventsMap + ServerSideEvents extends EventsMap, + SocketData = any > { public readonly conn: RawSocket; private readonly id: string; - private readonly server: Server; + private readonly server: Server< + ListenEvents, + EmitEvents, + ServerSideEvents, + SocketData + >; private readonly encoder: Encoder; private readonly decoder: Decoder; private sockets: Map< SocketId, - Socket + Socket > = new Map(); private nsps: Map< string, - Socket + Socket > = new Map(); private connectTimeout?: NodeJS.Timeout; @@ -47,7 +53,7 @@ export class Client< * @package */ constructor( - server: Server, + server: Server, conn: any ) { this.server = server; @@ -112,7 +118,7 @@ export class Client< auth, ( dynamicNspName: - | Namespace + | Namespace | false ) => { if (dynamicNspName) { @@ -171,7 +177,9 @@ export class Client< * * @private */ - _remove(socket: Socket): void { + _remove( + socket: Socket + ): void { if (this.sockets.has(socket.id)) { const nsp = this.sockets.get(socket.id)!.nsp.name; this.sockets.delete(socket.id); diff --git a/lib/index.ts b/lib/index.ts index 53ee552a9e..3fcd7edfb5 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -72,16 +72,23 @@ interface ServerOptions extends EngineOptions, AttachOptions { export class Server< ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, - ServerSideEvents extends EventsMap = DefaultEventsMap + ServerSideEvents extends EventsMap = DefaultEventsMap, + SocketData = any > extends StrictEventEmitter< ServerSideEvents, EmitEvents, - ServerReservedEventsMap + ServerReservedEventsMap< + ListenEvents, + EmitEvents, + ServerSideEvents, + SocketData + > > { public readonly sockets: Namespace< ListenEvents, EmitEvents, - ServerSideEvents + ServerSideEvents, + SocketData >; /** * A reference to the underlying Engine.IO server. @@ -504,7 +511,9 @@ export class Server< */ public of( name: string | RegExp | ParentNspNameMatchFn, - fn?: (socket: Socket) => void + fn?: ( + socket: Socket + ) => void ): Namespace { if (typeof name === "function" || name instanceof RegExp) { const parentNsp = new ParentNamespace(this); @@ -568,7 +577,7 @@ export class Server< */ public use( fn: ( - socket: Socket, + socket: Socket, next: (err?: ExtendedError) => void ) => void ): this { diff --git a/lib/namespace.ts b/lib/namespace.ts index e4bcfc5d20..c1a9297724 100644 --- a/lib/namespace.ts +++ b/lib/namespace.ts @@ -21,56 +21,72 @@ export interface ExtendedError extends Error { export interface NamespaceReservedEventsMap< ListenEvents extends EventsMap, EmitEvents extends EventsMap, - ServerSideEvents extends EventsMap + ServerSideEvents extends EventsMap, + SocketData > { - connect: (socket: Socket) => void; + connect: ( + socket: Socket + ) => void; connection: ( - socket: Socket + socket: Socket ) => void; } export interface ServerReservedEventsMap< ListenEvents, EmitEvents, - ServerSideEvents + ServerSideEvents, + SocketData > extends NamespaceReservedEventsMap< ListenEvents, EmitEvents, - ServerSideEvents + ServerSideEvents, + SocketData > { new_namespace: ( - namespace: Namespace + namespace: Namespace ) => void; } export const RESERVED_EVENTS: ReadonlySet = new Set< - keyof ServerReservedEventsMap + keyof ServerReservedEventsMap >(["connect", "connection", "new_namespace"]); export class Namespace< ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, - ServerSideEvents extends EventsMap = DefaultEventsMap + ServerSideEvents extends EventsMap = DefaultEventsMap, + SocketData = any > extends StrictEventEmitter< ServerSideEvents, EmitEvents, - NamespaceReservedEventsMap + NamespaceReservedEventsMap< + ListenEvents, + EmitEvents, + ServerSideEvents, + SocketData + > > { public readonly name: string; public readonly sockets: Map< SocketId, - Socket + Socket > = new Map(); public adapter: Adapter; /** @private */ - readonly server: Server; + readonly server: Server< + ListenEvents, + EmitEvents, + ServerSideEvents, + SocketData + >; /** @private */ _fns: Array< ( - socket: Socket, + socket: Socket, next: (err?: ExtendedError) => void ) => void > = []; @@ -85,7 +101,7 @@ export class Namespace< * @param name */ constructor( - server: Server, + server: Server, name: string ) { super(); @@ -114,7 +130,7 @@ export class Namespace< */ public use( fn: ( - socket: Socket, + socket: Socket, next: (err?: ExtendedError) => void ) => void ): this { @@ -130,7 +146,7 @@ export class Namespace< * @private */ private run( - socket: Socket, + socket: Socket, fn: (err: ExtendedError | null) => void ) { const fns = this._fns.slice(0); @@ -195,7 +211,7 @@ export class Namespace< client: Client, query, fn?: () => void - ): Socket { + ): Socket { debug("adding socket to nsp %s", this.name); const socket = new Socket(this, client, query); this.run(socket, (err) => { @@ -238,7 +254,9 @@ export class Namespace< * * @private */ - _remove(socket: Socket): void { + _remove( + socket: Socket + ): void { if (this.sockets.has(socket.id)) { this.sockets.delete(socket.id); } else { diff --git a/lib/parent-namespace.ts b/lib/parent-namespace.ts index a3b4d5b82c..9ab3a562ed 100644 --- a/lib/parent-namespace.ts +++ b/lib/parent-namespace.ts @@ -11,13 +11,17 @@ import type { BroadcastOptions } from "socket.io-adapter"; export class ParentNamespace< ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, - ServerSideEvents extends EventsMap = DefaultEventsMap -> extends Namespace { + ServerSideEvents extends EventsMap = DefaultEventsMap, + SocketData = any +> extends Namespace { private static count: number = 0; - private children: Set> = - new Set(); + private children: Set< + Namespace + > = new Set(); - constructor(server: Server) { + constructor( + server: Server + ) { super(server, "/_" + ParentNamespace.count++); } @@ -47,7 +51,7 @@ export class ParentNamespace< createChild( name: string - ): Namespace { + ): Namespace { const namespace = new Namespace(this.server, name); namespace._fns = this._fns.slice(0); this.listeners("connect").forEach((listener) => diff --git a/lib/socket.ts b/lib/socket.ts index e9546bfa83..603c8652fb 100644 --- a/lib/socket.ts +++ b/lib/socket.ts @@ -46,7 +46,7 @@ export interface EventEmitterReservedEventsMap { export const RESERVED_EVENTS: ReadonlySet = new Set< | ClientReservedEvents - | keyof NamespaceReservedEventsMap + | keyof NamespaceReservedEventsMap | keyof SocketReservedEventsMap | keyof EventEmitterReservedEventsMap >([ @@ -113,7 +113,8 @@ type Event = [eventName: string, ...args: any[]]; export class Socket< ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, - ServerSideEvents extends EventsMap = DefaultEventsMap + ServerSideEvents extends EventsMap = DefaultEventsMap, + SocketData = any > extends StrictEventEmitter< ListenEvents, EmitEvents, @@ -124,12 +125,17 @@ export class Socket< /** * Additional information that can be attached to the Socket instance and which will be used in the fetchSockets method */ - public data: any = {}; + public data: Partial = {}; public connected: boolean; public disconnected: boolean; - private readonly server: Server; + private readonly server: Server< + ListenEvents, + EmitEvents, + ServerSideEvents, + SocketData + >; private readonly adapter: Adapter; private acks: Map void> = new Map(); private fns: Array<(event: Event, next: (err?: Error) => void) => void> = [];