UNPKG

19.7 kBTypeScriptView Raw
1import { Packet } from "socket.io-parser";
2import { AllButLast, DecorateAcknowledgements, DecorateAcknowledgementsWithMultipleResponses, DefaultEventsMap, EventNames, EventNamesWithAck, EventParams, EventsMap, FirstNonErrorArg, Last, StrictEventEmitter } from "./typed-events";
3import type { Client } from "./client";
4import type { Namespace } from "./namespace";
5import type { IncomingMessage } from "http";
6import type { Room, Session, SocketId } from "socket.io-adapter";
7import { BroadcastOperator } from "./broadcast-operator";
8import { DisconnectReason, Handshake, SocketReservedEventsMap } from "./socket-types";
9/**
10 * `[eventName, ...args]`
11 */
12export type Event = [string, ...any[]];
13/**
14 * This is the main object for interacting with a client.
15 *
16 * A Socket belongs to a given {@link Namespace} and uses an underlying {@link Client} to communicate.
17 *
18 * Within each {@link Namespace}, you can also define arbitrary channels (called "rooms") that the {@link Socket} can
19 * join and leave. That provides a convenient way to broadcast to a group of socket instances.
20 *
21 * @example
22 * io.on("connection", (socket) => {
23 * console.log(`socket ${socket.id} connected`);
24 *
25 * // send an event to the client
26 * socket.emit("foo", "bar");
27 *
28 * socket.on("foobar", () => {
29 * // an event was received from the client
30 * });
31 *
32 * // join the room named "room1"
33 * socket.join("room1");
34 *
35 * // broadcast to everyone in the room named "room1"
36 * io.to("room1").emit("hello");
37 *
38 * // upon disconnection
39 * socket.on("disconnect", (reason) => {
40 * console.log(`socket ${socket.id} disconnected due to ${reason}`);
41 * });
42 * });
43 */
44export declare class Socket<ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, ServerSideEvents extends EventsMap = DefaultEventsMap, SocketData = any> extends StrictEventEmitter<ListenEvents, EmitEvents, SocketReservedEventsMap> {
45 readonly nsp: Namespace<ListenEvents, EmitEvents, ServerSideEvents>;
46 readonly client: Client<ListenEvents, EmitEvents, ServerSideEvents>;
47 /**
48 * An unique identifier for the session.
49 */
50 readonly id: SocketId;
51 /**
52 * Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will
53 * be transmitted to the client, the data attribute and the rooms will be restored.
54 */
55 readonly recovered: boolean;
56 /**
57 * The handshake details.
58 */
59 readonly handshake: Handshake;
60 /**
61 * Additional information that can be attached to the Socket instance and which will be used in the
62 * {@link Server.fetchSockets()} method.
63 */
64 data: SocketData;
65 /**
66 * Whether the socket is currently connected or not.
67 *
68 * @example
69 * io.use((socket, next) => {
70 * console.log(socket.connected); // false
71 * next();
72 * });
73 *
74 * io.on("connection", (socket) => {
75 * console.log(socket.connected); // true
76 * });
77 */
78 connected: boolean;
79 /**
80 * The session ID, which must not be shared (unlike {@link id}).
81 *
82 * @private
83 */
84 private readonly pid;
85 private readonly server;
86 private readonly adapter;
87 private acks;
88 private fns;
89 private flags;
90 private _anyListeners?;
91 private _anyOutgoingListeners?;
92 /**
93 * Interface to a `Client` for a given `Namespace`.
94 *
95 * @param {Namespace} nsp
96 * @param {Client} client
97 * @param {Object} auth
98 * @package
99 */
100 constructor(nsp: Namespace<ListenEvents, EmitEvents, ServerSideEvents>, client: Client<ListenEvents, EmitEvents, ServerSideEvents>, auth: Record<string, unknown>, previousSession?: Session);
101 /**
102 * Builds the `handshake` BC object
103 *
104 * @private
105 */
106 private buildHandshake;
107 /**
108 * Emits to this client.
109 *
110 * @example
111 * io.on("connection", (socket) => {
112 * socket.emit("hello", "world");
113 *
114 * // all serializable datastructures are supported (no need to call JSON.stringify)
115 * socket.emit("hello", 1, "2", { 3: ["4"], 5: Buffer.from([6]) });
116 *
117 * // with an acknowledgement from the client
118 * socket.emit("hello", "world", (val) => {
119 * // ...
120 * });
121 * });
122 *
123 * @return Always returns `true`.
124 */
125 emit<Ev extends EventNames<EmitEvents>>(ev: Ev, ...args: EventParams<EmitEvents, Ev>): boolean;
126 /**
127 * Emits an event and waits for an acknowledgement
128 *
129 * @example
130 * io.on("connection", async (socket) => {
131 * // without timeout
132 * const response = await socket.emitWithAck("hello", "world");
133 *
134 * // with a specific timeout
135 * try {
136 * const response = await socket.timeout(1000).emitWithAck("hello", "world");
137 * } catch (err) {
138 * // the client did not acknowledge the event in the given delay
139 * }
140 * });
141 *
142 * @return a Promise that will be fulfilled when the client acknowledges the event
143 */
144 emitWithAck<Ev extends EventNamesWithAck<EmitEvents>>(ev: Ev, ...args: AllButLast<EventParams<EmitEvents, Ev>>): Promise<FirstNonErrorArg<Last<EventParams<EmitEvents, Ev>>>>;
145 /**
146 * @private
147 */
148 private registerAckCallback;
149 /**
150 * Targets a room when broadcasting.
151 *
152 * @example
153 * io.on("connection", (socket) => {
154 * // the “foo” event will be broadcast to all connected clients in the “room-101” room, except this socket
155 * socket.to("room-101").emit("foo", "bar");
156 *
157 * // the code above is equivalent to:
158 * io.to("room-101").except(socket.id).emit("foo", "bar");
159 *
160 * // with an array of rooms (a client will be notified at most once)
161 * socket.to(["room-101", "room-102"]).emit("foo", "bar");
162 *
163 * // with multiple chained calls
164 * socket.to("room-101").to("room-102").emit("foo", "bar");
165 * });
166 *
167 * @param room - a room, or an array of rooms
168 * @return a new {@link BroadcastOperator} instance for chaining
169 */
170 to(room: Room | Room[]): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
171 /**
172 * Targets a room when broadcasting. Similar to `to()`, but might feel clearer in some cases:
173 *
174 * @example
175 * io.on("connection", (socket) => {
176 * // disconnect all clients in the "room-101" room, except this socket
177 * socket.in("room-101").disconnectSockets();
178 * });
179 *
180 * @param room - a room, or an array of rooms
181 * @return a new {@link BroadcastOperator} instance for chaining
182 */
183 in(room: Room | Room[]): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
184 /**
185 * Excludes a room when broadcasting.
186 *
187 * @example
188 * io.on("connection", (socket) => {
189 * // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
190 * // and this socket
191 * socket.except("room-101").emit("foo", "bar");
192 *
193 * // with an array of rooms
194 * socket.except(["room-101", "room-102"]).emit("foo", "bar");
195 *
196 * // with multiple chained calls
197 * socket.except("room-101").except("room-102").emit("foo", "bar");
198 * });
199 *
200 * @param room - a room, or an array of rooms
201 * @return a new {@link BroadcastOperator} instance for chaining
202 */
203 except(room: Room | Room[]): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
204 /**
205 * Sends a `message` event.
206 *
207 * This method mimics the WebSocket.send() method.
208 *
209 * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
210 *
211 * @example
212 * io.on("connection", (socket) => {
213 * socket.send("hello");
214 *
215 * // this is equivalent to
216 * socket.emit("message", "hello");
217 * });
218 *
219 * @return self
220 */
221 send(...args: EventParams<EmitEvents, "message">): this;
222 /**
223 * Sends a `message` event. Alias of {@link send}.
224 *
225 * @return self
226 */
227 write(...args: EventParams<EmitEvents, "message">): this;
228 /**
229 * Writes a packet.
230 *
231 * @param {Object} packet - packet object
232 * @param {Object} opts - options
233 * @private
234 */
235 private packet;
236 /**
237 * Joins a room.
238 *
239 * @example
240 * io.on("connection", (socket) => {
241 * // join a single room
242 * socket.join("room1");
243 *
244 * // join multiple rooms
245 * socket.join(["room1", "room2"]);
246 * });
247 *
248 * @param {String|Array} rooms - room or array of rooms
249 * @return a Promise or nothing, depending on the adapter
250 */
251 join(rooms: Room | Array<Room>): Promise<void> | void;
252 /**
253 * Leaves a room.
254 *
255 * @example
256 * io.on("connection", (socket) => {
257 * // leave a single room
258 * socket.leave("room1");
259 *
260 * // leave multiple rooms
261 * socket.leave("room1").leave("room2");
262 * });
263 *
264 * @param {String} room
265 * @return a Promise or nothing, depending on the adapter
266 */
267 leave(room: string): Promise<void> | void;
268 /**
269 * Leave all rooms.
270 *
271 * @private
272 */
273 private leaveAll;
274 /**
275 * Called by `Namespace` upon successful
276 * middleware execution (ie: authorization).
277 * Socket is added to namespace array before
278 * call to join, so adapters can access it.
279 *
280 * @private
281 */
282 _onconnect(): void;
283 /**
284 * Called with each packet. Called by `Client`.
285 *
286 * @param {Object} packet
287 * @private
288 */
289 _onpacket(packet: Packet): void;
290 /**
291 * Called upon event packet.
292 *
293 * @param {Packet} packet - packet object
294 * @private
295 */
296 private onevent;
297 /**
298 * Produces an ack callback to emit with an event.
299 *
300 * @param {Number} id - packet id
301 * @private
302 */
303 private ack;
304 /**
305 * Called upon ack packet.
306 *
307 * @private
308 */
309 private onack;
310 /**
311 * Called upon client disconnect packet.
312 *
313 * @private
314 */
315 private ondisconnect;
316 /**
317 * Handles a client error.
318 *
319 * @private
320 */
321 _onerror(err: Error): void;
322 /**
323 * Called upon closing. Called by `Client`.
324 *
325 * @param {String} reason
326 * @param description
327 * @throw {Error} optional error object
328 *
329 * @private
330 */
331 _onclose(reason: DisconnectReason, description?: any): this | undefined;
332 /**
333 * Makes the socket leave all the rooms it was part of and prevents it from joining any other room
334 *
335 * @private
336 */
337 _cleanup(): void;
338 /**
339 * Produces an `error` packet.
340 *
341 * @param {Object} err - error object
342 *
343 * @private
344 */
345 _error(err: any): void;
346 /**
347 * Disconnects this client.
348 *
349 * @example
350 * io.on("connection", (socket) => {
351 * // disconnect this socket (the connection might be kept alive for other namespaces)
352 * socket.disconnect();
353 *
354 * // disconnect this socket and close the underlying connection
355 * socket.disconnect(true);
356 * })
357 *
358 * @param {Boolean} close - if `true`, closes the underlying connection
359 * @return self
360 */
361 disconnect(close?: boolean): this;
362 /**
363 * Sets the compress flag.
364 *
365 * @example
366 * io.on("connection", (socket) => {
367 * socket.compress(false).emit("hello");
368 * });
369 *
370 * @param {Boolean} compress - if `true`, compresses the sending data
371 * @return {Socket} self
372 */
373 compress(compress: boolean): this;
374 /**
375 * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
376 * receive messages (because of network slowness or other issues, or because they’re connected through long polling
377 * and is in the middle of a request-response cycle).
378 *
379 * @example
380 * io.on("connection", (socket) => {
381 * socket.volatile.emit("hello"); // the client may or may not receive it
382 * });
383 *
384 * @return {Socket} self
385 */
386 get volatile(): this;
387 /**
388 * Sets a modifier for a subsequent event emission that the event data will only be broadcast to every sockets but the
389 * sender.
390 *
391 * @example
392 * io.on("connection", (socket) => {
393 * // the “foo” event will be broadcast to all connected clients, except this socket
394 * socket.broadcast.emit("foo", "bar");
395 * });
396 *
397 * @return a new {@link BroadcastOperator} instance for chaining
398 */
399 get broadcast(): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
400 /**
401 * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
402 *
403 * @example
404 * io.on("connection", (socket) => {
405 * // the “foo” event will be broadcast to all connected clients on this node, except this socket
406 * socket.local.emit("foo", "bar");
407 * });
408 *
409 * @return a new {@link BroadcastOperator} instance for chaining
410 */
411 get local(): BroadcastOperator<DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
412 /**
413 * Sets a modifier for a subsequent event emission that the callback will be called with an error when the
414 * given number of milliseconds have elapsed without an acknowledgement from the client:
415 *
416 * @example
417 * io.on("connection", (socket) => {
418 * socket.timeout(5000).emit("my-event", (err) => {
419 * if (err) {
420 * // the client did not acknowledge the event in the given delay
421 * }
422 * });
423 * });
424 *
425 * @returns self
426 */
427 timeout(timeout: number): Socket<ListenEvents, DecorateAcknowledgements<EmitEvents>, ServerSideEvents, SocketData>;
428 /**
429 * Dispatch incoming event to socket listeners.
430 *
431 * @param {Array} event - event that will get emitted
432 * @private
433 */
434 private dispatch;
435 /**
436 * Sets up socket middleware.
437 *
438 * @example
439 * io.on("connection", (socket) => {
440 * socket.use(([event, ...args], next) => {
441 * if (isUnauthorized(event)) {
442 * return next(new Error("unauthorized event"));
443 * }
444 * // do not forget to call next
445 * next();
446 * });
447 *
448 * socket.on("error", (err) => {
449 * if (err && err.message === "unauthorized event") {
450 * socket.disconnect();
451 * }
452 * });
453 * });
454 *
455 * @param {Function} fn - middleware function (event, next)
456 * @return {Socket} self
457 */
458 use(fn: (event: Event, next: (err?: Error) => void) => void): this;
459 /**
460 * Executes the middleware for an incoming event.
461 *
462 * @param {Array} event - event that will get emitted
463 * @param {Function} fn - last fn call in the middleware
464 * @private
465 */
466 private run;
467 /**
468 * Whether the socket is currently disconnected
469 */
470 get disconnected(): boolean;
471 /**
472 * A reference to the request that originated the underlying Engine.IO Socket.
473 */
474 get request(): IncomingMessage;
475 /**
476 * A reference to the underlying Client transport connection (Engine.IO Socket object).
477 *
478 * @example
479 * io.on("connection", (socket) => {
480 * console.log(socket.conn.transport.name); // prints "polling" or "websocket"
481 *
482 * socket.conn.once("upgrade", () => {
483 * console.log(socket.conn.transport.name); // prints "websocket"
484 * });
485 * });
486 */
487 get conn(): import("engine.io").Socket;
488 /**
489 * Returns the rooms the socket is currently in.
490 *
491 * @example
492 * io.on("connection", (socket) => {
493 * console.log(socket.rooms); // Set { <socket.id> }
494 *
495 * socket.join("room1");
496 *
497 * console.log(socket.rooms); // Set { <socket.id>, "room1" }
498 * });
499 */
500 get rooms(): Set<Room>;
501 /**
502 * Adds a listener that will be fired when any event is received. The event name is passed as the first argument to
503 * the callback.
504 *
505 * @example
506 * io.on("connection", (socket) => {
507 * socket.onAny((event, ...args) => {
508 * console.log(`got event ${event}`);
509 * });
510 * });
511 *
512 * @param listener
513 */
514 onAny(listener: (...args: any[]) => void): this;
515 /**
516 * Adds a listener that will be fired when any event is received. The event name is passed as the first argument to
517 * the callback. The listener is added to the beginning of the listeners array.
518 *
519 * @param listener
520 */
521 prependAny(listener: (...args: any[]) => void): this;
522 /**
523 * Removes the listener that will be fired when any event is received.
524 *
525 * @example
526 * io.on("connection", (socket) => {
527 * const catchAllListener = (event, ...args) => {
528 * console.log(`got event ${event}`);
529 * }
530 *
531 * socket.onAny(catchAllListener);
532 *
533 * // remove a specific listener
534 * socket.offAny(catchAllListener);
535 *
536 * // or remove all listeners
537 * socket.offAny();
538 * });
539 *
540 * @param listener
541 */
542 offAny(listener?: (...args: any[]) => void): this;
543 /**
544 * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
545 * e.g. to remove listeners.
546 */
547 listenersAny(): ((...args: any[]) => void)[];
548 /**
549 * Adds a listener that will be fired when any event is sent. The event name is passed as the first argument to
550 * the callback.
551 *
552 * Note: acknowledgements sent to the client are not included.
553 *
554 * @example
555 * io.on("connection", (socket) => {
556 * socket.onAnyOutgoing((event, ...args) => {
557 * console.log(`sent event ${event}`);
558 * });
559 * });
560 *
561 * @param listener
562 */
563 onAnyOutgoing(listener: (...args: any[]) => void): this;
564 /**
565 * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
566 * callback. The listener is added to the beginning of the listeners array.
567 *
568 * @example
569 * io.on("connection", (socket) => {
570 * socket.prependAnyOutgoing((event, ...args) => {
571 * console.log(`sent event ${event}`);
572 * });
573 * });
574 *
575 * @param listener
576 */
577 prependAnyOutgoing(listener: (...args: any[]) => void): this;
578 /**
579 * Removes the listener that will be fired when any event is sent.
580 *
581 * @example
582 * io.on("connection", (socket) => {
583 * const catchAllListener = (event, ...args) => {
584 * console.log(`sent event ${event}`);
585 * }
586 *
587 * socket.onAnyOutgoing(catchAllListener);
588 *
589 * // remove a specific listener
590 * socket.offAnyOutgoing(catchAllListener);
591 *
592 * // or remove all listeners
593 * socket.offAnyOutgoing();
594 * });
595 *
596 * @param listener - the catch-all listener
597 */
598 offAnyOutgoing(listener?: (...args: any[]) => void): this;
599 /**
600 * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
601 * e.g. to remove listeners.
602 */
603 listenersAnyOutgoing(): ((...args: any[]) => void)[];
604 /**
605 * Notify the listeners for each packet sent (emit or broadcast)
606 *
607 * @param packet
608 *
609 * @private
610 */
611 private notifyOutgoingListeners;
612 private newBroadcastOperator;
613}
614
\No newline at end of file