socket.d.ts 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. import { Packet } from "socket.io-parser";
  2. import { AllButLast, DecorateAcknowledgements, DecorateAcknowledgementsWithMultipleResponses, DefaultEventsMap, EventNames, EventNamesWithAck, EventParams, EventsMap, FirstNonErrorArg, Last, StrictEventEmitter } from "./typed-events";
  3. import type { Client } from "./client";
  4. import type { Namespace } from "./namespace";
  5. import type { IncomingMessage } from "http";
  6. import type { Room, Session, SocketId } from "socket.io-adapter";
  7. import { BroadcastOperator } from "./broadcast-operator";
  8. import { DisconnectReason, Handshake, SocketReservedEventsMap } from "./socket-types";
  9. /**
  10. * `[eventName, ...args]`
  11. */
  12. export 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. */
  44. export 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. }