123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669 |
- /// <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 they’re 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;
- }
|