socket.d.ts 21 KB

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