index.d.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /// <reference types="node" />
  2. /// <reference types="node" />
  3. /// <reference types="node" />
  4. import http = require("http");
  5. import type { Server as HTTPSServer } from "https";
  6. import type { Http2SecureServer } from "http2";
  7. import type { ServerOptions as EngineOptions, AttachOptions, BaseServer } from "engine.io";
  8. import { ExtendedError, Namespace, ServerReservedEventsMap } from "./namespace";
  9. import { Adapter, Room, SocketId } from "socket.io-adapter";
  10. import * as parser from "socket.io-parser";
  11. import type { Encoder } from "socket.io-parser";
  12. import { Socket, DisconnectReason } from "./socket";
  13. import type { BroadcastOperator, RemoteSocket } from "./broadcast-operator";
  14. import { EventsMap, DefaultEventsMap, EventParams, StrictEventEmitter, EventNames, DecorateAcknowledgementsWithTimeoutAndMultipleResponses, AllButLast, Last, FirstArg, SecondArg } from "./typed-events";
  15. declare type ParentNspNameMatchFn = (name: string, auth: {
  16. [key: string]: any;
  17. }, fn: (err: Error | null, success: boolean) => void) => void;
  18. declare type AdapterConstructor = typeof Adapter | ((nsp: Namespace) => Adapter);
  19. interface ServerOptions extends EngineOptions, AttachOptions {
  20. /**
  21. * name of the path to capture
  22. * @default "/socket.io"
  23. */
  24. path: string;
  25. /**
  26. * whether to serve the client files
  27. * @default true
  28. */
  29. serveClient: boolean;
  30. /**
  31. * the adapter to use
  32. * @default the in-memory adapter (https://github.com/socketio/socket.io-adapter)
  33. */
  34. adapter: AdapterConstructor;
  35. /**
  36. * the parser to use
  37. * @default the default parser (https://github.com/socketio/socket.io-parser)
  38. */
  39. parser: any;
  40. /**
  41. * how many ms before a client without namespace is closed
  42. * @default 45000
  43. */
  44. connectTimeout: number;
  45. /**
  46. * Whether to enable the recovery of connection state when a client temporarily disconnects.
  47. *
  48. * The connection state includes the missed packets, the rooms the socket was in and the `data` attribute.
  49. */
  50. connectionStateRecovery: {
  51. /**
  52. * The backup duration of the sessions and the packets.
  53. *
  54. * @default 120000 (2 minutes)
  55. */
  56. maxDisconnectionDuration?: number;
  57. /**
  58. * Whether to skip middlewares upon successful connection state recovery.
  59. *
  60. * @default true
  61. */
  62. skipMiddlewares?: boolean;
  63. };
  64. /**
  65. * Whether to remove child namespaces that have no sockets connected to them
  66. * @default false
  67. */
  68. cleanupEmptyChildNamespaces: boolean;
  69. }
  70. /**
  71. * Represents a Socket.IO server.
  72. *
  73. * @example
  74. * import { Server } from "socket.io";
  75. *
  76. * const io = new Server();
  77. *
  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. * // upon disconnection
  89. * socket.on("disconnect", (reason) => {
  90. * console.log(`socket ${socket.id} disconnected due to ${reason}`);
  91. * });
  92. * });
  93. *
  94. * io.listen(3000);
  95. */
  96. export declare class Server<ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, ServerSideEvents extends EventsMap = DefaultEventsMap, SocketData = any> extends StrictEventEmitter<ServerSideEvents, EmitEvents, ServerReservedEventsMap<ListenEvents, EmitEvents, ServerSideEvents, SocketData>> {
  97. readonly sockets: Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>;
  98. /**
  99. * A reference to the underlying Engine.IO server.
  100. *
  101. * @example
  102. * const clientsCount = io.engine.clientsCount;
  103. *
  104. */
  105. engine: BaseServer;
  106. /** @private */
  107. readonly _parser: typeof parser;
  108. /** @private */
  109. readonly encoder: Encoder;
  110. /**
  111. * @private
  112. */
  113. _nsps: Map<string, Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>>;
  114. private parentNsps;
  115. /**
  116. * A subset of the {@link parentNsps} map, only containing {@link ParentNamespace} which are based on a regular
  117. * expression.
  118. *
  119. * @private
  120. */
  121. private parentNamespacesFromRegExp;
  122. private _adapter?;
  123. private _serveClient;
  124. private readonly opts;
  125. private eio;
  126. private _path;
  127. private clientPathRegex;
  128. /**
  129. * @private
  130. */
  131. _connectTimeout: number;
  132. private httpServer;
  133. /**
  134. * Server constructor.
  135. *
  136. * @param srv http server, port, or options
  137. * @param [opts]
  138. */
  139. constructor(opts?: Partial<ServerOptions>);
  140. constructor(srv?: http.Server | HTTPSServer | Http2SecureServer | number, opts?: Partial<ServerOptions>);
  141. constructor(srv: undefined | Partial<ServerOptions> | http.Server | HTTPSServer | Http2SecureServer | number, opts?: Partial<ServerOptions>);
  142. get _opts(): Partial<ServerOptions>;
  143. /**
  144. * Sets/gets whether client code is being served.
  145. *
  146. * @param v - whether to serve client code
  147. * @return self when setting or value when getting
  148. */
  149. serveClient(v: boolean): this;
  150. serveClient(): boolean;
  151. serveClient(v?: boolean): this | boolean;
  152. /**
  153. * Executes the middleware for an incoming namespace not already created on the server.
  154. *
  155. * @param name - name of incoming namespace
  156. * @param auth - the auth parameters
  157. * @param fn - callback
  158. *
  159. * @private
  160. */
  161. _checkNamespace(name: string, auth: {
  162. [key: string]: any;
  163. }, fn: (nsp: Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData> | false) => void): void;
  164. /**
  165. * Sets the client serving path.
  166. *
  167. * @param {String} v pathname
  168. * @return {Server|String} self when setting or value when getting
  169. */
  170. path(v: string): this;
  171. path(): string;
  172. path(v?: string): this | string;
  173. /**
  174. * Set the delay after which a client without namespace is closed
  175. * @param v
  176. */
  177. connectTimeout(v: number): this;
  178. connectTimeout(): number;
  179. connectTimeout(v?: number): this | number;
  180. /**
  181. * Sets the adapter for rooms.
  182. *
  183. * @param v pathname
  184. * @return self when setting or value when getting
  185. */
  186. adapter(): AdapterConstructor | undefined;
  187. adapter(v: AdapterConstructor): this;
  188. /**
  189. * Attaches socket.io to a server or port.
  190. *
  191. * @param srv - server or port
  192. * @param opts - options passed to engine.io
  193. * @return self
  194. */
  195. listen(srv: http.Server | HTTPSServer | Http2SecureServer | number, opts?: Partial<ServerOptions>): this;
  196. /**
  197. * Attaches socket.io to a server or port.
  198. *
  199. * @param srv - server or port
  200. * @param opts - options passed to engine.io
  201. * @return self
  202. */
  203. attach(srv: http.Server | HTTPSServer | Http2SecureServer | number, opts?: Partial<ServerOptions>): this;
  204. attachApp(app: any, opts?: Partial<ServerOptions>): void;
  205. /**
  206. * Initialize engine
  207. *
  208. * @param srv - the server to attach to
  209. * @param opts - options passed to engine.io
  210. * @private
  211. */
  212. private initEngine;
  213. /**
  214. * Attaches the static file serving.
  215. *
  216. * @param srv http server
  217. * @private
  218. */
  219. private attachServe;
  220. /**
  221. * Handles a request serving of client source and map
  222. *
  223. * @param req
  224. * @param res
  225. * @private
  226. */
  227. private serve;
  228. /**
  229. * @param filename
  230. * @param req
  231. * @param res
  232. * @private
  233. */
  234. private static sendFile;
  235. /**
  236. * Binds socket.io to an engine.io instance.
  237. *
  238. * @param engine engine.io (or compatible) server
  239. * @return self
  240. */
  241. bind(engine: BaseServer): this;
  242. /**
  243. * Called with each incoming transport connection.
  244. *
  245. * @param {engine.Socket} conn
  246. * @return self
  247. * @private
  248. */
  249. private onconnection;
  250. /**
  251. * Looks up a namespace.
  252. *
  253. * @example
  254. * // with a simple string
  255. * const myNamespace = io.of("/my-namespace");
  256. *
  257. * // with a regex
  258. * const dynamicNsp = io.of(/^\/dynamic-\d+$/).on("connection", (socket) => {
  259. * const namespace = socket.nsp; // newNamespace.name === "/dynamic-101"
  260. *
  261. * // broadcast to all clients in the given sub-namespace
  262. * namespace.emit("hello");
  263. * });
  264. *
  265. * @param name - nsp name
  266. * @param fn optional, nsp `connection` ev handler
  267. */
  268. of(name: string | RegExp | ParentNspNameMatchFn, fn?: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>) => void): Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>;
  269. /**
  270. * Closes server connection
  271. *
  272. * @param [fn] optional, called as `fn([err])` on error OR all conns closed
  273. */
  274. close(fn?: (err?: Error) => void): void;
  275. /**
  276. * Registers a middleware, which is a function that gets executed for every incoming {@link Socket}.
  277. *
  278. * @example
  279. * io.use((socket, next) => {
  280. * // ...
  281. * next();
  282. * });
  283. *
  284. * @param fn - the middleware function
  285. */
  286. use(fn: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>, next: (err?: ExtendedError) => void) => void): this;
  287. /**
  288. * Targets a room when emitting.
  289. *
  290. * @example
  291. * // the “foo” event will be broadcast to all connected clients in the “room-101” room
  292. * io.to("room-101").emit("foo", "bar");
  293. *
  294. * // with an array of rooms (a client will be notified at most once)
  295. * io.to(["room-101", "room-102"]).emit("foo", "bar");
  296. *
  297. * // with multiple chained calls
  298. * io.to("room-101").to("room-102").emit("foo", "bar");
  299. *
  300. * @param room - a room, or an array of rooms
  301. * @return a new {@link BroadcastOperator} instance for chaining
  302. */
  303. to(room: Room | Room[]): BroadcastOperator<EmitEvents, SocketData>;
  304. /**
  305. * Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
  306. *
  307. * @example
  308. * // disconnect all clients in the "room-101" room
  309. * io.in("room-101").disconnectSockets();
  310. *
  311. * @param room - a room, or an array of rooms
  312. * @return a new {@link BroadcastOperator} instance for chaining
  313. */
  314. in(room: Room | Room[]): BroadcastOperator<EmitEvents, SocketData>;
  315. /**
  316. * Excludes a room when emitting.
  317. *
  318. * @example
  319. * // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
  320. * io.except("room-101").emit("foo", "bar");
  321. *
  322. * // with an array of rooms
  323. * io.except(["room-101", "room-102"]).emit("foo", "bar");
  324. *
  325. * // with multiple chained calls
  326. * io.except("room-101").except("room-102").emit("foo", "bar");
  327. *
  328. * @param room - a room, or an array of rooms
  329. * @return a new {@link BroadcastOperator} instance for chaining
  330. */
  331. except(room: Room | Room[]): BroadcastOperator<EmitEvents, SocketData>;
  332. /**
  333. * Emits an event and waits for an acknowledgement from all clients.
  334. *
  335. * @example
  336. * try {
  337. * const responses = await io.timeout(1000).emitWithAck("some-event");
  338. * console.log(responses); // one response per client
  339. * } catch (e) {
  340. * // some clients did not acknowledge the event in the given delay
  341. * }
  342. *
  343. * @return a Promise that will be fulfilled when all clients have acknowledged the event
  344. */
  345. emitWithAck<Ev extends EventNames<EmitEvents>>(ev: Ev, ...args: AllButLast<EventParams<EmitEvents, Ev>>): Promise<SecondArg<Last<EventParams<EmitEvents, Ev>>>>;
  346. /**
  347. * Sends a `message` event to all clients.
  348. *
  349. * This method mimics the WebSocket.send() method.
  350. *
  351. * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
  352. *
  353. * @example
  354. * io.send("hello");
  355. *
  356. * // this is equivalent to
  357. * io.emit("message", "hello");
  358. *
  359. * @return self
  360. */
  361. send(...args: EventParams<EmitEvents, "message">): this;
  362. /**
  363. * Sends a `message` event to all clients. Alias of {@link send}.
  364. *
  365. * @return self
  366. */
  367. write(...args: EventParams<EmitEvents, "message">): this;
  368. /**
  369. * Sends a message to the other Socket.IO servers of the cluster.
  370. *
  371. * @example
  372. * io.serverSideEmit("hello", "world");
  373. *
  374. * io.on("hello", (arg1) => {
  375. * console.log(arg1); // prints "world"
  376. * });
  377. *
  378. * // acknowledgements (without binary content) are supported too:
  379. * io.serverSideEmit("ping", (err, responses) => {
  380. * if (err) {
  381. * // some servers did not acknowledge the event in the given delay
  382. * } else {
  383. * console.log(responses); // one response per server (except the current one)
  384. * }
  385. * });
  386. *
  387. * io.on("ping", (cb) => {
  388. * cb("pong");
  389. * });
  390. *
  391. * @param ev - the event name
  392. * @param args - an array of arguments, which may include an acknowledgement callback at the end
  393. */
  394. serverSideEmit<Ev extends EventNames<ServerSideEvents>>(ev: Ev, ...args: EventParams<DecorateAcknowledgementsWithTimeoutAndMultipleResponses<ServerSideEvents>, Ev>): boolean;
  395. /**
  396. * Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.
  397. *
  398. * @example
  399. * try {
  400. * const responses = await io.serverSideEmitWithAck("ping");
  401. * console.log(responses); // one response per server (except the current one)
  402. * } catch (e) {
  403. * // some servers did not acknowledge the event in the given delay
  404. * }
  405. *
  406. * @param ev - the event name
  407. * @param args - an array of arguments
  408. *
  409. * @return a Promise that will be fulfilled when all servers have acknowledged the event
  410. */
  411. serverSideEmitWithAck<Ev extends EventNames<ServerSideEvents>>(ev: Ev, ...args: AllButLast<EventParams<ServerSideEvents, Ev>>): Promise<FirstArg<Last<EventParams<ServerSideEvents, Ev>>>[]>;
  412. /**
  413. * Gets a list of socket ids.
  414. *
  415. * @deprecated this method will be removed in the next major release, please use {@link Server#serverSideEmit} or
  416. * {@link Server#fetchSockets} instead.
  417. */
  418. allSockets(): Promise<Set<SocketId>>;
  419. /**
  420. * Sets the compress flag.
  421. *
  422. * @example
  423. * io.compress(false).emit("hello");
  424. *
  425. * @param compress - if `true`, compresses the sending data
  426. * @return a new {@link BroadcastOperator} instance for chaining
  427. */
  428. compress(compress: boolean): BroadcastOperator<EmitEvents, SocketData>;
  429. /**
  430. * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
  431. * receive messages (because of network slowness or other issues, or because they’re connected through long polling
  432. * and is in the middle of a request-response cycle).
  433. *
  434. * @example
  435. * io.volatile.emit("hello"); // the clients may or may not receive it
  436. *
  437. * @return a new {@link BroadcastOperator} instance for chaining
  438. */
  439. get volatile(): BroadcastOperator<EmitEvents, SocketData>;
  440. /**
  441. * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
  442. *
  443. * @example
  444. * // the “foo” event will be broadcast to all connected clients on this node
  445. * io.local.emit("foo", "bar");
  446. *
  447. * @return a new {@link BroadcastOperator} instance for chaining
  448. */
  449. get local(): BroadcastOperator<EmitEvents, SocketData>;
  450. /**
  451. * Adds a timeout in milliseconds for the next operation.
  452. *
  453. * @example
  454. * io.timeout(1000).emit("some-event", (err, responses) => {
  455. * if (err) {
  456. * // some clients did not acknowledge the event in the given delay
  457. * } else {
  458. * console.log(responses); // one response per client
  459. * }
  460. * });
  461. *
  462. * @param timeout
  463. */
  464. timeout(timeout: number): BroadcastOperator<DecorateAcknowledgementsWithTimeoutAndMultipleResponses<EmitEvents>, SocketData>;
  465. /**
  466. * Returns the matching socket instances.
  467. *
  468. * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
  469. *
  470. * @example
  471. * // return all Socket instances
  472. * const sockets = await io.fetchSockets();
  473. *
  474. * // return all Socket instances in the "room1" room
  475. * const sockets = await io.in("room1").fetchSockets();
  476. *
  477. * for (const socket of sockets) {
  478. * console.log(socket.id);
  479. * console.log(socket.handshake);
  480. * console.log(socket.rooms);
  481. * console.log(socket.data);
  482. *
  483. * socket.emit("hello");
  484. * socket.join("room1");
  485. * socket.leave("room2");
  486. * socket.disconnect();
  487. * }
  488. */
  489. fetchSockets(): Promise<RemoteSocket<EmitEvents, SocketData>[]>;
  490. /**
  491. * Makes the matching socket instances join the specified rooms.
  492. *
  493. * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
  494. *
  495. * @example
  496. *
  497. * // make all socket instances join the "room1" room
  498. * io.socketsJoin("room1");
  499. *
  500. * // make all socket instances in the "room1" room join the "room2" and "room3" rooms
  501. * io.in("room1").socketsJoin(["room2", "room3"]);
  502. *
  503. * @param room - a room, or an array of rooms
  504. */
  505. socketsJoin(room: Room | Room[]): void;
  506. /**
  507. * Makes the matching socket instances leave the specified rooms.
  508. *
  509. * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
  510. *
  511. * @example
  512. * // make all socket instances leave the "room1" room
  513. * io.socketsLeave("room1");
  514. *
  515. * // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
  516. * io.in("room1").socketsLeave(["room2", "room3"]);
  517. *
  518. * @param room - a room, or an array of rooms
  519. */
  520. socketsLeave(room: Room | Room[]): void;
  521. /**
  522. * Makes the matching socket instances disconnect.
  523. *
  524. * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
  525. *
  526. * @example
  527. * // make all socket instances disconnect (the connections might be kept alive for other namespaces)
  528. * io.disconnectSockets();
  529. *
  530. * // make all socket instances in the "room1" room disconnect and close the underlying connections
  531. * io.in("room1").disconnectSockets(true);
  532. *
  533. * @param close - whether to close the underlying connection
  534. */
  535. disconnectSockets(close?: boolean): void;
  536. }
  537. export { Socket, DisconnectReason, ServerOptions, Namespace, BroadcastOperator, RemoteSocket, };
  538. export { Event } from "./socket";