@gleamkit/socket.io 4.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,598 @@
1
+ import http from "http";
2
+ import type { Server as HTTPSServer } from "https";
3
+ import type { Http2SecureServer, Http2Server } from "http2";
4
+ import { Server as Engine } from "engine.io";
5
+ import type { ServerOptions as EngineOptions, AttachOptions } from "engine.io";
6
+ import { ExtendedError, Namespace, ServerReservedEventsMap } from "./namespace";
7
+ import { Adapter, Room, SocketId } from "socket.io-adapter";
8
+ import * as parser from "socket.io-parser";
9
+ import type { Encoder } from "socket.io-parser";
10
+ import { Socket } from "./socket";
11
+ import { DisconnectReason } from "./socket-types";
12
+ import type { BroadcastOperator, RemoteSocket } from "./broadcast-operator";
13
+ import { EventsMap, DefaultEventsMap, EventParams, StrictEventEmitter, EventNames, DecorateAcknowledgementsWithTimeoutAndMultipleResponses, AllButLast, Last, RemoveAcknowledgements, EventNamesWithAck, FirstNonErrorArg } from "./typed-events";
14
+ type ParentNspNameMatchFn = (name: string, auth: {
15
+ [key: string]: any;
16
+ }, fn: (err: Error | null, success: boolean) => void) => void;
17
+ type AdapterConstructor = typeof Adapter | ((nsp: Namespace) => Adapter);
18
+ type TServerInstance = http.Server | HTTPSServer | Http2SecureServer | Http2Server;
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<
97
+ /**
98
+ * Types for the events received from the clients.
99
+ *
100
+ * @example
101
+ * interface ClientToServerEvents {
102
+ * hello: (arg: string) => void;
103
+ * }
104
+ *
105
+ * const io = new Server<ClientToServerEvents>();
106
+ *
107
+ * io.on("connection", (socket) => {
108
+ * socket.on("hello", (arg) => {
109
+ * // `arg` is inferred as string
110
+ * });
111
+ * });
112
+ */
113
+ ListenEvents extends EventsMap = DefaultEventsMap,
114
+ /**
115
+ * Types for the events sent to the clients.
116
+ *
117
+ * @example
118
+ * interface ServerToClientEvents {
119
+ * hello: (arg: string) => void;
120
+ * }
121
+ *
122
+ * const io = new Server<DefaultEventMap, ServerToClientEvents>();
123
+ *
124
+ * io.emit("hello", "world");
125
+ */
126
+ EmitEvents extends EventsMap = ListenEvents,
127
+ /**
128
+ * Types for the events received from and sent to the other servers.
129
+ *
130
+ * @example
131
+ * interface InterServerEvents {
132
+ * ping: (arg: number) => void;
133
+ * }
134
+ *
135
+ * const io = new Server<DefaultEventMap, DefaultEventMap, ServerToClientEvents>();
136
+ *
137
+ * io.serverSideEmit("ping", 123);
138
+ *
139
+ * io.on("ping", (arg) => {
140
+ * // `arg` is inferred as number
141
+ * });
142
+ */
143
+ ServerSideEvents extends EventsMap = DefaultEventsMap,
144
+ /**
145
+ * Additional properties that can be attached to the socket instance.
146
+ *
147
+ * Note: any property can be attached directly to the socket instance (`socket.foo = "bar"`), but the `data` object
148
+ * will be included when calling {@link Server#fetchSockets}.
149
+ *
150
+ * @example
151
+ * io.on("connection", (socket) => {
152
+ * socket.data.eventsCount = 0;
153
+ *
154
+ * socket.onAny(() => {
155
+ * socket.data.eventsCount++;
156
+ * });
157
+ * });
158
+ */
159
+ SocketData = any> extends StrictEventEmitter<ServerSideEvents, RemoveAcknowledgements<EmitEvents>, ServerReservedEventsMap<ListenEvents, EmitEvents, ServerSideEvents, SocketData>> {
160
+ readonly sockets: Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>;
161
+ /**
162
+ * A reference to the underlying Engine.IO server.
163
+ *
164
+ * @example
165
+ * const clientsCount = io.engine.clientsCount;
166
+ *
167
+ */
168
+ engine: Engine;
169
+ /**
170
+ * The underlying Node.js HTTP server.
171
+ *
172
+ * @see https://nodejs.org/api/http.html
173
+ */
174
+ httpServer: TServerInstance;
175
+ /** @private */
176
+ readonly _parser: typeof parser;
177
+ /** @private */
178
+ readonly encoder: Encoder;
179
+ /**
180
+ * @private
181
+ */
182
+ _nsps: Map<string, Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>>;
183
+ private parentNsps;
184
+ /**
185
+ * A subset of the {@link parentNsps} map, only containing {@link ParentNamespace} which are based on a regular
186
+ * expression.
187
+ *
188
+ * @private
189
+ */
190
+ private parentNamespacesFromRegExp;
191
+ private _adapter?;
192
+ private _serveClient;
193
+ private readonly opts;
194
+ private eio;
195
+ private _path;
196
+ private clientPathRegex;
197
+ /**
198
+ * @private
199
+ */
200
+ _connectTimeout: number;
201
+ private _corsMiddleware;
202
+ /**
203
+ * Server constructor.
204
+ *
205
+ * @param srv http server, port, or options
206
+ * @param [opts]
207
+ */
208
+ constructor(opts?: Partial<ServerOptions>);
209
+ constructor(srv?: TServerInstance | number, opts?: Partial<ServerOptions>);
210
+ constructor(srv: undefined | Partial<ServerOptions> | TServerInstance | number, opts?: Partial<ServerOptions>);
211
+ get _opts(): Partial<ServerOptions>;
212
+ /**
213
+ * Sets/gets whether client code is being served.
214
+ *
215
+ * @param v - whether to serve client code
216
+ * @return self when setting or value when getting
217
+ */
218
+ serveClient(v: boolean): this;
219
+ serveClient(): boolean;
220
+ serveClient(v?: boolean): this | boolean;
221
+ /**
222
+ * Executes the middleware for an incoming namespace not already created on the server.
223
+ *
224
+ * @param name - name of incoming namespace
225
+ * @param auth - the auth parameters
226
+ * @param fn - callback
227
+ *
228
+ * @private
229
+ */
230
+ _checkNamespace(name: string, auth: {
231
+ [key: string]: any;
232
+ }, fn: (nsp: Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData> | false) => void): void;
233
+ /**
234
+ * Sets the client serving path.
235
+ *
236
+ * @param {String} v pathname
237
+ * @return {Server|String} self when setting or value when getting
238
+ */
239
+ path(v: string): this;
240
+ path(): string;
241
+ path(v?: string): this | string;
242
+ /**
243
+ * Set the delay after which a client without namespace is closed
244
+ * @param v
245
+ */
246
+ connectTimeout(v: number): this;
247
+ connectTimeout(): number;
248
+ connectTimeout(v?: number): this | number;
249
+ /**
250
+ * Sets the adapter for rooms.
251
+ *
252
+ * @param v pathname
253
+ * @return self when setting or value when getting
254
+ */
255
+ adapter(): AdapterConstructor | undefined;
256
+ adapter(v: AdapterConstructor): this;
257
+ /**
258
+ * Attaches socket.io to a server or port.
259
+ *
260
+ * @param srv - server or port
261
+ * @param opts - options passed to engine.io
262
+ * @return self
263
+ */
264
+ listen(srv: TServerInstance | number, opts?: Partial<ServerOptions>): this;
265
+ /**
266
+ * Attaches socket.io to a server or port.
267
+ *
268
+ * @param srv - server or port
269
+ * @param opts - options passed to engine.io
270
+ * @return self
271
+ */
272
+ attach(srv: TServerInstance | number, opts?: Partial<ServerOptions>): this;
273
+ /**
274
+ * Attaches socket.io to a uWebSockets.js app.
275
+ * @param app
276
+ * @param opts
277
+ */
278
+ attachApp(app: any, opts?: Partial<ServerOptions>): void;
279
+ /**
280
+ * Initialize engine
281
+ *
282
+ * @param srv - the server to attach to
283
+ * @param opts - options passed to engine.io
284
+ * @private
285
+ */
286
+ private initEngine;
287
+ /**
288
+ * Attaches the static file serving.
289
+ *
290
+ * @param srv http server
291
+ * @private
292
+ */
293
+ private attachServe;
294
+ /**
295
+ * Handles a request serving of client source and map
296
+ *
297
+ * @param req
298
+ * @param res
299
+ * @private
300
+ */
301
+ private serve;
302
+ /**
303
+ * @param filename
304
+ * @param req
305
+ * @param res
306
+ * @private
307
+ */
308
+ private static sendFile;
309
+ /**
310
+ * Binds socket.io to an engine.io instance.
311
+ *
312
+ * @param engine engine.io (or compatible) server
313
+ * @return self
314
+ */
315
+ bind(engine: any): this;
316
+ /**
317
+ * Called with each incoming transport connection.
318
+ *
319
+ * @param {engine.Socket} conn
320
+ * @return self
321
+ * @private
322
+ */
323
+ private onconnection;
324
+ /**
325
+ * Looks up a namespace.
326
+ *
327
+ * @example
328
+ * // with a simple string
329
+ * const myNamespace = io.of("/my-namespace");
330
+ *
331
+ * // with a regex
332
+ * const dynamicNsp = io.of(/^\/dynamic-\d+$/).on("connection", (socket) => {
333
+ * const namespace = socket.nsp; // newNamespace.name === "/dynamic-101"
334
+ *
335
+ * // broadcast to all clients in the given sub-namespace
336
+ * namespace.emit("hello");
337
+ * });
338
+ *
339
+ * @param name - nsp name
340
+ * @param fn optional, nsp `connection` ev handler
341
+ */
342
+ of(name: string | RegExp | ParentNspNameMatchFn, fn?: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>) => void): Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>;
343
+ /**
344
+ * Closes server connection
345
+ *
346
+ * @param [fn] optional, called as `fn([err])` on error OR all conns closed
347
+ */
348
+ close(fn?: (err?: Error) => void): Promise<void>;
349
+ /**
350
+ * Registers a middleware, which is a function that gets executed for every incoming {@link Socket}.
351
+ *
352
+ * @example
353
+ * io.use((socket, next) => {
354
+ * // ...
355
+ * next();
356
+ * });
357
+ *
358
+ * @param fn - the middleware function
359
+ */
360
+ use(fn: (socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>, next: (err?: ExtendedError) => void) => void): this;
361
+ /**
362
+ * Targets a room when emitting.
363
+ *
364
+ * @example
365
+ * // the “foo” event will be broadcast to all connected clients in the “room-101” room
366
+ * io.to("room-101").emit("foo", "bar");
367
+ *
368
+ * // with an array of rooms (a client will be notified at most once)
369
+ * io.to(["room-101", "room-102"]).emit("foo", "bar");
370
+ *
371
+ * // with multiple chained calls
372
+ * io.to("room-101").to("room-102").emit("foo", "bar");
373
+ *
374
+ * @param room - a room, or an array of rooms
375
+ * @return a new {@link BroadcastOperator} instance for chaining
376
+ */
377
+ to(room: Room | Room[]): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
378
+ /**
379
+ * Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
380
+ *
381
+ * @example
382
+ * // disconnect all clients in the "room-101" room
383
+ * io.in("room-101").disconnectSockets();
384
+ *
385
+ * @param room - a room, or an array of rooms
386
+ * @return a new {@link BroadcastOperator} instance for chaining
387
+ */
388
+ in(room: Room | Room[]): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
389
+ /**
390
+ * Excludes a room when emitting.
391
+ *
392
+ * @example
393
+ * // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
394
+ * io.except("room-101").emit("foo", "bar");
395
+ *
396
+ * // with an array of rooms
397
+ * io.except(["room-101", "room-102"]).emit("foo", "bar");
398
+ *
399
+ * // with multiple chained calls
400
+ * io.except("room-101").except("room-102").emit("foo", "bar");
401
+ *
402
+ * @param room - a room, or an array of rooms
403
+ * @return a new {@link BroadcastOperator} instance for chaining
404
+ */
405
+ except(room: Room | Room[]): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
406
+ /**
407
+ * Sends a `message` event to all clients.
408
+ *
409
+ * This method mimics the WebSocket.send() method.
410
+ *
411
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
412
+ *
413
+ * @example
414
+ * io.send("hello");
415
+ *
416
+ * // this is equivalent to
417
+ * io.emit("message", "hello");
418
+ *
419
+ * @return self
420
+ */
421
+ send(...args: EventParams<EmitEvents, "message">): this;
422
+ /**
423
+ * Sends a `message` event to all clients. Alias of {@link send}.
424
+ *
425
+ * @return self
426
+ */
427
+ write(...args: EventParams<EmitEvents, "message">): this;
428
+ /**
429
+ * Sends a message to the other Socket.IO servers of the cluster.
430
+ *
431
+ * @example
432
+ * io.serverSideEmit("hello", "world");
433
+ *
434
+ * io.on("hello", (arg1) => {
435
+ * console.log(arg1); // prints "world"
436
+ * });
437
+ *
438
+ * // acknowledgements (without binary content) are supported too:
439
+ * io.serverSideEmit("ping", (err, responses) => {
440
+ * if (err) {
441
+ * // some servers did not acknowledge the event in the given delay
442
+ * } else {
443
+ * console.log(responses); // one response per server (except the current one)
444
+ * }
445
+ * });
446
+ *
447
+ * io.on("ping", (cb) => {
448
+ * cb("pong");
449
+ * });
450
+ *
451
+ * @param ev - the event name
452
+ * @param args - an array of arguments, which may include an acknowledgement callback at the end
453
+ */
454
+ serverSideEmit<Ev extends EventNames<ServerSideEvents>>(ev: Ev, ...args: EventParams<DecorateAcknowledgementsWithTimeoutAndMultipleResponses<ServerSideEvents>, Ev>): boolean;
455
+ /**
456
+ * Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.
457
+ *
458
+ * @example
459
+ * try {
460
+ * const responses = await io.serverSideEmitWithAck("ping");
461
+ * console.log(responses); // one response per server (except the current one)
462
+ * } catch (e) {
463
+ * // some servers did not acknowledge the event in the given delay
464
+ * }
465
+ *
466
+ * @param ev - the event name
467
+ * @param args - an array of arguments
468
+ *
469
+ * @return a Promise that will be fulfilled when all servers have acknowledged the event
470
+ */
471
+ serverSideEmitWithAck<Ev extends EventNamesWithAck<ServerSideEvents>>(ev: Ev, ...args: AllButLast<EventParams<ServerSideEvents, Ev>>): Promise<FirstNonErrorArg<Last<EventParams<ServerSideEvents, Ev>>>[]>;
472
+ /**
473
+ * Gets a list of socket ids.
474
+ *
475
+ * @deprecated this method will be removed in the next major release, please use {@link Server#serverSideEmit} or
476
+ * {@link Server#fetchSockets} instead.
477
+ */
478
+ allSockets(): Promise<Set<SocketId>>;
479
+ /**
480
+ * Sets the compress flag.
481
+ *
482
+ * @example
483
+ * io.compress(false).emit("hello");
484
+ *
485
+ * @param compress - if `true`, compresses the sending data
486
+ * @return a new {@link BroadcastOperator} instance for chaining
487
+ */
488
+ compress(compress: boolean): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
489
+ /**
490
+ * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
491
+ * receive messages (because of network slowness or other issues, or because they’re connected through long polling
492
+ * and is in the middle of a request-response cycle).
493
+ *
494
+ * @example
495
+ * io.volatile.emit("hello"); // the clients may or may not receive it
496
+ *
497
+ * @return a new {@link BroadcastOperator} instance for chaining
498
+ */
499
+ get volatile(): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
500
+ /**
501
+ * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
502
+ *
503
+ * @example
504
+ * // the “foo” event will be broadcast to all connected clients on this node
505
+ * io.local.emit("foo", "bar");
506
+ *
507
+ * @return a new {@link BroadcastOperator} instance for chaining
508
+ */
509
+ get local(): BroadcastOperator<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>, SocketData>;
510
+ /**
511
+ * Adds a timeout in milliseconds for the next operation.
512
+ *
513
+ * @example
514
+ * io.timeout(1000).emit("some-event", (err, responses) => {
515
+ * if (err) {
516
+ * // some clients did not acknowledge the event in the given delay
517
+ * } else {
518
+ * console.log(responses); // one response per client
519
+ * }
520
+ * });
521
+ *
522
+ * @param timeout
523
+ */
524
+ timeout(timeout: number): BroadcastOperator<import("./typed-events").DecorateAcknowledgements<import("./typed-events").DecorateAcknowledgementsWithMultipleResponses<EmitEvents>>, SocketData>;
525
+ /**
526
+ * Returns the matching socket instances.
527
+ *
528
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
529
+ *
530
+ * @example
531
+ * // return all Socket instances
532
+ * const sockets = await io.fetchSockets();
533
+ *
534
+ * // return all Socket instances in the "room1" room
535
+ * const sockets = await io.in("room1").fetchSockets();
536
+ *
537
+ * for (const socket of sockets) {
538
+ * console.log(socket.id);
539
+ * console.log(socket.handshake);
540
+ * console.log(socket.rooms);
541
+ * console.log(socket.data);
542
+ *
543
+ * socket.emit("hello");
544
+ * socket.join("room1");
545
+ * socket.leave("room2");
546
+ * socket.disconnect();
547
+ * }
548
+ */
549
+ fetchSockets(): Promise<RemoteSocket<EmitEvents, SocketData>[]>;
550
+ /**
551
+ * Makes the matching socket instances join the specified rooms.
552
+ *
553
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
554
+ *
555
+ * @example
556
+ *
557
+ * // make all socket instances join the "room1" room
558
+ * io.socketsJoin("room1");
559
+ *
560
+ * // make all socket instances in the "room1" room join the "room2" and "room3" rooms
561
+ * io.in("room1").socketsJoin(["room2", "room3"]);
562
+ *
563
+ * @param room - a room, or an array of rooms
564
+ */
565
+ socketsJoin(room: Room | Room[]): void;
566
+ /**
567
+ * Makes the matching socket instances leave the specified rooms.
568
+ *
569
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
570
+ *
571
+ * @example
572
+ * // make all socket instances leave the "room1" room
573
+ * io.socketsLeave("room1");
574
+ *
575
+ * // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
576
+ * io.in("room1").socketsLeave(["room2", "room3"]);
577
+ *
578
+ * @param room - a room, or an array of rooms
579
+ */
580
+ socketsLeave(room: Room | Room[]): void;
581
+ /**
582
+ * Makes the matching socket instances disconnect.
583
+ *
584
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
585
+ *
586
+ * @example
587
+ * // make all socket instances disconnect (the connections might be kept alive for other namespaces)
588
+ * io.disconnectSockets();
589
+ *
590
+ * // make all socket instances in the "room1" room disconnect and close the underlying connections
591
+ * io.in("room1").disconnectSockets(true);
592
+ *
593
+ * @param close - whether to close the underlying connection
594
+ */
595
+ disconnectSockets(close?: boolean): void;
596
+ }
597
+ export { Socket, DisconnectReason, ServerOptions, Namespace, BroadcastOperator, RemoteSocket, DefaultEventsMap, ExtendedError, };
598
+ export { Event } from "./socket";