@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.
package/dist/index.js ADDED
@@ -0,0 +1,818 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.Namespace = exports.Socket = exports.Server = void 0;
30
+ const http_1 = __importDefault(require("http"));
31
+ const fs_1 = require("fs");
32
+ const zlib_1 = require("zlib");
33
+ const accepts = require("accepts");
34
+ const stream_1 = require("stream");
35
+ const path = require("path");
36
+ const engine_io_1 = require("engine.io");
37
+ const client_1 = require("./client");
38
+ const events_1 = require("events");
39
+ const namespace_1 = require("./namespace");
40
+ Object.defineProperty(exports, "Namespace", { enumerable: true, get: function () { return namespace_1.Namespace; } });
41
+ const parent_namespace_1 = require("./parent-namespace");
42
+ const socket_io_adapter_1 = require("socket.io-adapter");
43
+ const parser = __importStar(require("socket.io-parser"));
44
+ const debug_1 = __importDefault(require("debug"));
45
+ const socket_1 = require("./socket");
46
+ Object.defineProperty(exports, "Socket", { enumerable: true, get: function () { return socket_1.Socket; } });
47
+ const typed_events_1 = require("./typed-events");
48
+ const uws_1 = require("./uws");
49
+ const cors_1 = __importDefault(require("cors"));
50
+ const debug = (0, debug_1.default)("socket.io:server");
51
+ const clientVersion = require("../package.json").version;
52
+ const dotMapRegex = /\.map/;
53
+ /**
54
+ * Represents a Socket.IO server.
55
+ *
56
+ * @example
57
+ * import { Server } from "socket.io";
58
+ *
59
+ * const io = new Server();
60
+ *
61
+ * io.on("connection", (socket) => {
62
+ * console.log(`socket ${socket.id} connected`);
63
+ *
64
+ * // send an event to the client
65
+ * socket.emit("foo", "bar");
66
+ *
67
+ * socket.on("foobar", () => {
68
+ * // an event was received from the client
69
+ * });
70
+ *
71
+ * // upon disconnection
72
+ * socket.on("disconnect", (reason) => {
73
+ * console.log(`socket ${socket.id} disconnected due to ${reason}`);
74
+ * });
75
+ * });
76
+ *
77
+ * io.listen(3000);
78
+ */
79
+ class Server extends typed_events_1.StrictEventEmitter {
80
+ constructor(srv, opts = {}) {
81
+ super();
82
+ /**
83
+ * @private
84
+ */
85
+ this._nsps = new Map();
86
+ this.parentNsps = new Map();
87
+ /**
88
+ * A subset of the {@link parentNsps} map, only containing {@link ParentNamespace} which are based on a regular
89
+ * expression.
90
+ *
91
+ * @private
92
+ */
93
+ this.parentNamespacesFromRegExp = new Map();
94
+ if ("object" === typeof srv &&
95
+ srv instanceof Object &&
96
+ !srv.listen) {
97
+ opts = srv;
98
+ srv = undefined;
99
+ }
100
+ this.path(opts.path || "/socket.io");
101
+ this.connectTimeout(opts.connectTimeout || 45000);
102
+ this.serveClient(false !== opts.serveClient);
103
+ this._parser = opts.parser || parser;
104
+ this.encoder = new this._parser.Encoder();
105
+ this.opts = opts;
106
+ if (opts.connectionStateRecovery) {
107
+ opts.connectionStateRecovery = Object.assign({
108
+ maxDisconnectionDuration: 2 * 60 * 1000,
109
+ skipMiddlewares: true,
110
+ }, opts.connectionStateRecovery);
111
+ this.adapter(opts.adapter || socket_io_adapter_1.SessionAwareAdapter);
112
+ }
113
+ else {
114
+ this.adapter(opts.adapter || socket_io_adapter_1.Adapter);
115
+ }
116
+ opts.cleanupEmptyChildNamespaces = !!opts.cleanupEmptyChildNamespaces;
117
+ this.sockets = this.of("/");
118
+ if (srv || typeof srv == "number")
119
+ this.attach(srv);
120
+ if (this.opts.cors) {
121
+ this._corsMiddleware = (0, cors_1.default)(this.opts.cors);
122
+ }
123
+ }
124
+ get _opts() {
125
+ return this.opts;
126
+ }
127
+ serveClient(v) {
128
+ if (!arguments.length)
129
+ return this._serveClient;
130
+ this._serveClient = v;
131
+ return this;
132
+ }
133
+ /**
134
+ * Executes the middleware for an incoming namespace not already created on the server.
135
+ *
136
+ * @param name - name of incoming namespace
137
+ * @param auth - the auth parameters
138
+ * @param fn - callback
139
+ *
140
+ * @private
141
+ */
142
+ _checkNamespace(name, auth, fn) {
143
+ if (this.parentNsps.size === 0)
144
+ return fn(false);
145
+ const keysIterator = this.parentNsps.keys();
146
+ const run = () => {
147
+ const nextFn = keysIterator.next();
148
+ if (nextFn.done) {
149
+ return fn(false);
150
+ }
151
+ nextFn.value(name, auth, (err, allow) => {
152
+ if (err || !allow) {
153
+ return run();
154
+ }
155
+ if (this._nsps.has(name)) {
156
+ // the namespace was created in the meantime
157
+ debug("dynamic namespace %s already exists", name);
158
+ return fn(this._nsps.get(name));
159
+ }
160
+ const namespace = this.parentNsps.get(nextFn.value).createChild(name);
161
+ debug("dynamic namespace %s was created", name);
162
+ fn(namespace);
163
+ });
164
+ };
165
+ run();
166
+ }
167
+ path(v) {
168
+ if (!arguments.length)
169
+ return this._path;
170
+ this._path = v.replace(/\/$/, "");
171
+ const escapedPath = this._path.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
172
+ this.clientPathRegex = new RegExp("^" +
173
+ escapedPath +
174
+ "/socket\\.io(\\.msgpack|\\.esm)?(\\.min)?\\.js(\\.map)?(?:\\?|$)");
175
+ return this;
176
+ }
177
+ connectTimeout(v) {
178
+ if (v === undefined)
179
+ return this._connectTimeout;
180
+ this._connectTimeout = v;
181
+ return this;
182
+ }
183
+ adapter(v) {
184
+ if (!arguments.length)
185
+ return this._adapter;
186
+ this._adapter = v;
187
+ for (const nsp of this._nsps.values()) {
188
+ nsp._initAdapter();
189
+ }
190
+ return this;
191
+ }
192
+ /**
193
+ * Attaches socket.io to a server or port.
194
+ *
195
+ * @param srv - server or port
196
+ * @param opts - options passed to engine.io
197
+ * @return self
198
+ */
199
+ listen(srv, opts = {}) {
200
+ return this.attach(srv, opts);
201
+ }
202
+ /**
203
+ * Attaches socket.io to a server or port.
204
+ *
205
+ * @param srv - server or port
206
+ * @param opts - options passed to engine.io
207
+ * @return self
208
+ */
209
+ attach(srv, opts = {}) {
210
+ if ("function" == typeof srv) {
211
+ const msg = "You are trying to attach socket.io to an express " +
212
+ "request handler function. Please pass a http.Server instance.";
213
+ throw new Error(msg);
214
+ }
215
+ // handle a port as a string
216
+ if (Number(srv) == srv) {
217
+ srv = Number(srv);
218
+ }
219
+ if ("number" == typeof srv) {
220
+ debug("creating http server and binding to %d", srv);
221
+ const port = srv;
222
+ srv = http_1.default.createServer((req, res) => {
223
+ res.writeHead(404);
224
+ res.end();
225
+ });
226
+ srv.listen(port);
227
+ }
228
+ // merge the options passed to the Socket.IO server
229
+ Object.assign(opts, this.opts);
230
+ // set engine.io path to `/socket.io`
231
+ opts.path = opts.path || this._path;
232
+ this.initEngine(srv, opts);
233
+ return this;
234
+ }
235
+ /**
236
+ * Attaches socket.io to a uWebSockets.js app.
237
+ * @param app
238
+ * @param opts
239
+ */
240
+ attachApp(app /*: TemplatedApp */, opts = {}) {
241
+ // merge the options passed to the Socket.IO server
242
+ Object.assign(opts, this.opts);
243
+ // set engine.io path to `/socket.io`
244
+ opts.path = opts.path || this._path;
245
+ // initialize engine
246
+ debug("creating uWebSockets.js-based engine with opts %j", opts);
247
+ const engine = new engine_io_1.uServer(opts);
248
+ engine.attach(app, opts);
249
+ // bind to engine events
250
+ this.bind(engine);
251
+ if (this._serveClient) {
252
+ // attach static file serving
253
+ app.get(`${this._path}/*`, (res, req) => {
254
+ if (!this.clientPathRegex.test(req.getUrl())) {
255
+ req.setYield(true);
256
+ return;
257
+ }
258
+ const filename = req
259
+ .getUrl()
260
+ .replace(this._path, "")
261
+ .replace(/\?.*$/, "")
262
+ .replace(/^\//, "");
263
+ const isMap = dotMapRegex.test(filename);
264
+ const type = isMap ? "map" : "source";
265
+ // Per the standard, ETags must be quoted:
266
+ // https://tools.ietf.org/html/rfc7232#section-2.3
267
+ const expectedEtag = '"' + clientVersion + '"';
268
+ const weakEtag = "W/" + expectedEtag;
269
+ const etag = req.getHeader("if-none-match");
270
+ if (etag) {
271
+ if (expectedEtag === etag || weakEtag === etag) {
272
+ debug("serve client %s 304", type);
273
+ res.writeStatus("304 Not Modified");
274
+ res.end();
275
+ return;
276
+ }
277
+ }
278
+ debug("serve client %s", type);
279
+ res.writeHeader("cache-control", "public, max-age=0");
280
+ res.writeHeader("content-type", "application/" + (isMap ? "json" : "javascript") + "; charset=utf-8");
281
+ res.writeHeader("etag", expectedEtag);
282
+ const filepath = path.join(__dirname, "../client-dist/", filename);
283
+ (0, uws_1.serveFile)(res, filepath);
284
+ });
285
+ }
286
+ (0, uws_1.patchAdapter)(app);
287
+ }
288
+ /**
289
+ * Initialize engine
290
+ *
291
+ * @param srv - the server to attach to
292
+ * @param opts - options passed to engine.io
293
+ * @private
294
+ */
295
+ initEngine(srv, opts) {
296
+ // initialize engine
297
+ debug("creating engine.io instance with opts %j", opts);
298
+ this.eio = (0, engine_io_1.attach)(srv, opts);
299
+ // attach static file serving
300
+ if (this._serveClient)
301
+ this.attachServe(srv);
302
+ // Export http server
303
+ this.httpServer = srv;
304
+ // bind to engine events
305
+ this.bind(this.eio);
306
+ }
307
+ /**
308
+ * Attaches the static file serving.
309
+ *
310
+ * @param srv http server
311
+ * @private
312
+ */
313
+ attachServe(srv) {
314
+ debug("attaching client serving req handler");
315
+ const evs = srv.listeners("request").slice(0);
316
+ srv.removeAllListeners("request");
317
+ srv.on("request", (req, res) => {
318
+ if (this.clientPathRegex.test(req.url)) {
319
+ if (this._corsMiddleware) {
320
+ this._corsMiddleware(req, res, () => {
321
+ this.serve(req, res);
322
+ });
323
+ }
324
+ else {
325
+ this.serve(req, res);
326
+ }
327
+ }
328
+ else {
329
+ for (let i = 0; i < evs.length; i++) {
330
+ evs[i].call(srv, req, res);
331
+ }
332
+ }
333
+ });
334
+ }
335
+ /**
336
+ * Handles a request serving of client source and map
337
+ *
338
+ * @param req
339
+ * @param res
340
+ * @private
341
+ */
342
+ serve(req, res) {
343
+ const filename = req.url.replace(this._path, "").replace(/\?.*$/, "");
344
+ const isMap = dotMapRegex.test(filename);
345
+ const type = isMap ? "map" : "source";
346
+ // Per the standard, ETags must be quoted:
347
+ // https://tools.ietf.org/html/rfc7232#section-2.3
348
+ const expectedEtag = '"' + clientVersion + '"';
349
+ const weakEtag = "W/" + expectedEtag;
350
+ const etag = req.headers["if-none-match"];
351
+ if (etag) {
352
+ if (expectedEtag === etag || weakEtag === etag) {
353
+ debug("serve client %s 304", type);
354
+ res.writeHead(304);
355
+ res.end();
356
+ return;
357
+ }
358
+ }
359
+ debug("serve client %s", type);
360
+ res.setHeader("Cache-Control", "public, max-age=0");
361
+ res.setHeader("Content-Type", "application/" + (isMap ? "json" : "javascript") + "; charset=utf-8");
362
+ res.setHeader("ETag", expectedEtag);
363
+ Server.sendFile(filename, req, res);
364
+ }
365
+ /**
366
+ * @param filename
367
+ * @param req
368
+ * @param res
369
+ * @private
370
+ */
371
+ static sendFile(filename, req, res) {
372
+ const readStream = (0, fs_1.createReadStream)(path.join(__dirname, "../client-dist/", filename));
373
+ const encoding = accepts(req).encodings(["br", "gzip", "deflate"]);
374
+ const onError = (err) => {
375
+ if (err) {
376
+ res.end();
377
+ }
378
+ };
379
+ switch (encoding) {
380
+ case "br":
381
+ res.writeHead(200, { "content-encoding": "br" });
382
+ (0, stream_1.pipeline)(readStream, (0, zlib_1.createBrotliCompress)(), res, onError);
383
+ break;
384
+ case "gzip":
385
+ res.writeHead(200, { "content-encoding": "gzip" });
386
+ (0, stream_1.pipeline)(readStream, (0, zlib_1.createGzip)(), res, onError);
387
+ break;
388
+ case "deflate":
389
+ res.writeHead(200, { "content-encoding": "deflate" });
390
+ (0, stream_1.pipeline)(readStream, (0, zlib_1.createDeflate)(), res, onError);
391
+ break;
392
+ default:
393
+ res.writeHead(200);
394
+ (0, stream_1.pipeline)(readStream, res, onError);
395
+ }
396
+ }
397
+ /**
398
+ * Binds socket.io to an engine.io instance.
399
+ *
400
+ * @param engine engine.io (or compatible) server
401
+ * @return self
402
+ */
403
+ bind(engine) {
404
+ // TODO apply strict types to the engine: "connection" event, `close()` and a method to serve static content
405
+ // this would allow to provide any custom engine, like one based on Deno or Bun built-in HTTP server
406
+ this.engine = engine;
407
+ this.engine.on("connection", this.onconnection.bind(this));
408
+ return this;
409
+ }
410
+ /**
411
+ * Called with each incoming transport connection.
412
+ *
413
+ * @param {engine.Socket} conn
414
+ * @return self
415
+ * @private
416
+ */
417
+ onconnection(conn) {
418
+ // @ts-expect-error use of private
419
+ debug("incoming connection with id %s", conn.id);
420
+ const client = new client_1.Client(this, conn);
421
+ if (conn.protocol === 3) {
422
+ // @ts-expect-error use of private
423
+ client.connect("/");
424
+ }
425
+ return this;
426
+ }
427
+ /**
428
+ * Looks up a namespace.
429
+ *
430
+ * @example
431
+ * // with a simple string
432
+ * const myNamespace = io.of("/my-namespace");
433
+ *
434
+ * // with a regex
435
+ * const dynamicNsp = io.of(/^\/dynamic-\d+$/).on("connection", (socket) => {
436
+ * const namespace = socket.nsp; // newNamespace.name === "/dynamic-101"
437
+ *
438
+ * // broadcast to all clients in the given sub-namespace
439
+ * namespace.emit("hello");
440
+ * });
441
+ *
442
+ * @param name - nsp name
443
+ * @param fn optional, nsp `connection` ev handler
444
+ */
445
+ of(name, fn) {
446
+ if (typeof name === "function" || name instanceof RegExp) {
447
+ const parentNsp = new parent_namespace_1.ParentNamespace(this);
448
+ debug("initializing parent namespace %s", parentNsp.name);
449
+ if (typeof name === "function") {
450
+ this.parentNsps.set(name, parentNsp);
451
+ }
452
+ else {
453
+ this.parentNsps.set((nsp, conn, next) => next(null, name.test(nsp)), parentNsp);
454
+ this.parentNamespacesFromRegExp.set(name, parentNsp);
455
+ }
456
+ if (fn) {
457
+ // @ts-ignore
458
+ parentNsp.on("connect", fn);
459
+ }
460
+ return parentNsp;
461
+ }
462
+ if (String(name)[0] !== "/")
463
+ name = "/" + name;
464
+ let nsp = this._nsps.get(name);
465
+ if (!nsp) {
466
+ for (const [regex, parentNamespace] of this.parentNamespacesFromRegExp) {
467
+ if (regex.test(name)) {
468
+ debug("attaching namespace %s to parent namespace %s", name, regex);
469
+ return parentNamespace.createChild(name);
470
+ }
471
+ }
472
+ debug("initializing namespace %s", name);
473
+ nsp = new namespace_1.Namespace(this, name);
474
+ this._nsps.set(name, nsp);
475
+ if (name !== "/") {
476
+ // @ts-ignore
477
+ this.sockets.emitReserved("new_namespace", nsp);
478
+ }
479
+ }
480
+ if (fn)
481
+ nsp.on("connect", fn);
482
+ return nsp;
483
+ }
484
+ /**
485
+ * Closes server connection
486
+ *
487
+ * @param [fn] optional, called as `fn([err])` on error OR all conns closed
488
+ */
489
+ async close(fn) {
490
+ await Promise.allSettled([...this._nsps.values()].map(async (nsp) => {
491
+ nsp.sockets.forEach((socket) => {
492
+ socket._onclose("server shutting down");
493
+ });
494
+ await nsp.adapter.close();
495
+ }));
496
+ this.engine.close();
497
+ // restore the Adapter prototype, when the Socket.IO server was attached to a uWebSockets.js server
498
+ (0, uws_1.restoreAdapter)();
499
+ if (this.httpServer) {
500
+ return new Promise((resolve) => {
501
+ this.httpServer.close((err) => {
502
+ fn && fn(err);
503
+ if (err) {
504
+ debug("server was not running");
505
+ }
506
+ resolve();
507
+ });
508
+ });
509
+ }
510
+ else {
511
+ fn && fn();
512
+ }
513
+ }
514
+ /**
515
+ * Registers a middleware, which is a function that gets executed for every incoming {@link Socket}.
516
+ *
517
+ * @example
518
+ * io.use((socket, next) => {
519
+ * // ...
520
+ * next();
521
+ * });
522
+ *
523
+ * @param fn - the middleware function
524
+ */
525
+ use(fn) {
526
+ this.sockets.use(fn);
527
+ return this;
528
+ }
529
+ /**
530
+ * Targets a room when emitting.
531
+ *
532
+ * @example
533
+ * // the “foo” event will be broadcast to all connected clients in the “room-101” room
534
+ * io.to("room-101").emit("foo", "bar");
535
+ *
536
+ * // with an array of rooms (a client will be notified at most once)
537
+ * io.to(["room-101", "room-102"]).emit("foo", "bar");
538
+ *
539
+ * // with multiple chained calls
540
+ * io.to("room-101").to("room-102").emit("foo", "bar");
541
+ *
542
+ * @param room - a room, or an array of rooms
543
+ * @return a new {@link BroadcastOperator} instance for chaining
544
+ */
545
+ to(room) {
546
+ return this.sockets.to(room);
547
+ }
548
+ /**
549
+ * Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
550
+ *
551
+ * @example
552
+ * // disconnect all clients in the "room-101" room
553
+ * io.in("room-101").disconnectSockets();
554
+ *
555
+ * @param room - a room, or an array of rooms
556
+ * @return a new {@link BroadcastOperator} instance for chaining
557
+ */
558
+ in(room) {
559
+ return this.sockets.in(room);
560
+ }
561
+ /**
562
+ * Excludes a room when emitting.
563
+ *
564
+ * @example
565
+ * // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
566
+ * io.except("room-101").emit("foo", "bar");
567
+ *
568
+ * // with an array of rooms
569
+ * io.except(["room-101", "room-102"]).emit("foo", "bar");
570
+ *
571
+ * // with multiple chained calls
572
+ * io.except("room-101").except("room-102").emit("foo", "bar");
573
+ *
574
+ * @param room - a room, or an array of rooms
575
+ * @return a new {@link BroadcastOperator} instance for chaining
576
+ */
577
+ except(room) {
578
+ return this.sockets.except(room);
579
+ }
580
+ /**
581
+ * Sends a `message` event to all clients.
582
+ *
583
+ * This method mimics the WebSocket.send() method.
584
+ *
585
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
586
+ *
587
+ * @example
588
+ * io.send("hello");
589
+ *
590
+ * // this is equivalent to
591
+ * io.emit("message", "hello");
592
+ *
593
+ * @return self
594
+ */
595
+ send(...args) {
596
+ // This type-cast is needed because EmitEvents likely doesn't have `message` as a key.
597
+ // if you specify the EmitEvents, the type of args will be never.
598
+ this.sockets.emit("message", ...args);
599
+ return this;
600
+ }
601
+ /**
602
+ * Sends a `message` event to all clients. Alias of {@link send}.
603
+ *
604
+ * @return self
605
+ */
606
+ write(...args) {
607
+ // This type-cast is needed because EmitEvents likely doesn't have `message` as a key.
608
+ // if you specify the EmitEvents, the type of args will be never.
609
+ this.sockets.emit("message", ...args);
610
+ return this;
611
+ }
612
+ /**
613
+ * Sends a message to the other Socket.IO servers of the cluster.
614
+ *
615
+ * @example
616
+ * io.serverSideEmit("hello", "world");
617
+ *
618
+ * io.on("hello", (arg1) => {
619
+ * console.log(arg1); // prints "world"
620
+ * });
621
+ *
622
+ * // acknowledgements (without binary content) are supported too:
623
+ * io.serverSideEmit("ping", (err, responses) => {
624
+ * if (err) {
625
+ * // some servers did not acknowledge the event in the given delay
626
+ * } else {
627
+ * console.log(responses); // one response per server (except the current one)
628
+ * }
629
+ * });
630
+ *
631
+ * io.on("ping", (cb) => {
632
+ * cb("pong");
633
+ * });
634
+ *
635
+ * @param ev - the event name
636
+ * @param args - an array of arguments, which may include an acknowledgement callback at the end
637
+ */
638
+ serverSideEmit(ev, ...args) {
639
+ return this.sockets.serverSideEmit(ev, ...args);
640
+ }
641
+ /**
642
+ * Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.
643
+ *
644
+ * @example
645
+ * try {
646
+ * const responses = await io.serverSideEmitWithAck("ping");
647
+ * console.log(responses); // one response per server (except the current one)
648
+ * } catch (e) {
649
+ * // some servers did not acknowledge the event in the given delay
650
+ * }
651
+ *
652
+ * @param ev - the event name
653
+ * @param args - an array of arguments
654
+ *
655
+ * @return a Promise that will be fulfilled when all servers have acknowledged the event
656
+ */
657
+ serverSideEmitWithAck(ev, ...args) {
658
+ return this.sockets.serverSideEmitWithAck(ev, ...args);
659
+ }
660
+ /**
661
+ * Gets a list of socket ids.
662
+ *
663
+ * @deprecated this method will be removed in the next major release, please use {@link Server#serverSideEmit} or
664
+ * {@link Server#fetchSockets} instead.
665
+ */
666
+ allSockets() {
667
+ return this.sockets.allSockets();
668
+ }
669
+ /**
670
+ * Sets the compress flag.
671
+ *
672
+ * @example
673
+ * io.compress(false).emit("hello");
674
+ *
675
+ * @param compress - if `true`, compresses the sending data
676
+ * @return a new {@link BroadcastOperator} instance for chaining
677
+ */
678
+ compress(compress) {
679
+ return this.sockets.compress(compress);
680
+ }
681
+ /**
682
+ * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
683
+ * receive messages (because of network slowness or other issues, or because they’re connected through long polling
684
+ * and is in the middle of a request-response cycle).
685
+ *
686
+ * @example
687
+ * io.volatile.emit("hello"); // the clients may or may not receive it
688
+ *
689
+ * @return a new {@link BroadcastOperator} instance for chaining
690
+ */
691
+ get volatile() {
692
+ return this.sockets.volatile;
693
+ }
694
+ /**
695
+ * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
696
+ *
697
+ * @example
698
+ * // the “foo” event will be broadcast to all connected clients on this node
699
+ * io.local.emit("foo", "bar");
700
+ *
701
+ * @return a new {@link BroadcastOperator} instance for chaining
702
+ */
703
+ get local() {
704
+ return this.sockets.local;
705
+ }
706
+ /**
707
+ * Adds a timeout in milliseconds for the next operation.
708
+ *
709
+ * @example
710
+ * io.timeout(1000).emit("some-event", (err, responses) => {
711
+ * if (err) {
712
+ * // some clients did not acknowledge the event in the given delay
713
+ * } else {
714
+ * console.log(responses); // one response per client
715
+ * }
716
+ * });
717
+ *
718
+ * @param timeout
719
+ */
720
+ timeout(timeout) {
721
+ return this.sockets.timeout(timeout);
722
+ }
723
+ /**
724
+ * Returns the matching socket instances.
725
+ *
726
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
727
+ *
728
+ * @example
729
+ * // return all Socket instances
730
+ * const sockets = await io.fetchSockets();
731
+ *
732
+ * // return all Socket instances in the "room1" room
733
+ * const sockets = await io.in("room1").fetchSockets();
734
+ *
735
+ * for (const socket of sockets) {
736
+ * console.log(socket.id);
737
+ * console.log(socket.handshake);
738
+ * console.log(socket.rooms);
739
+ * console.log(socket.data);
740
+ *
741
+ * socket.emit("hello");
742
+ * socket.join("room1");
743
+ * socket.leave("room2");
744
+ * socket.disconnect();
745
+ * }
746
+ */
747
+ fetchSockets() {
748
+ return this.sockets.fetchSockets();
749
+ }
750
+ /**
751
+ * Makes the matching socket instances join the specified rooms.
752
+ *
753
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
754
+ *
755
+ * @example
756
+ *
757
+ * // make all socket instances join the "room1" room
758
+ * io.socketsJoin("room1");
759
+ *
760
+ * // make all socket instances in the "room1" room join the "room2" and "room3" rooms
761
+ * io.in("room1").socketsJoin(["room2", "room3"]);
762
+ *
763
+ * @param room - a room, or an array of rooms
764
+ */
765
+ socketsJoin(room) {
766
+ return this.sockets.socketsJoin(room);
767
+ }
768
+ /**
769
+ * Makes the matching socket instances leave the specified rooms.
770
+ *
771
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
772
+ *
773
+ * @example
774
+ * // make all socket instances leave the "room1" room
775
+ * io.socketsLeave("room1");
776
+ *
777
+ * // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
778
+ * io.in("room1").socketsLeave(["room2", "room3"]);
779
+ *
780
+ * @param room - a room, or an array of rooms
781
+ */
782
+ socketsLeave(room) {
783
+ return this.sockets.socketsLeave(room);
784
+ }
785
+ /**
786
+ * Makes the matching socket instances disconnect.
787
+ *
788
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
789
+ *
790
+ * @example
791
+ * // make all socket instances disconnect (the connections might be kept alive for other namespaces)
792
+ * io.disconnectSockets();
793
+ *
794
+ * // make all socket instances in the "room1" room disconnect and close the underlying connections
795
+ * io.in("room1").disconnectSockets(true);
796
+ *
797
+ * @param close - whether to close the underlying connection
798
+ */
799
+ disconnectSockets(close = false) {
800
+ return this.sockets.disconnectSockets(close);
801
+ }
802
+ }
803
+ exports.Server = Server;
804
+ /**
805
+ * Expose main namespace (/).
806
+ */
807
+ const emitterMethods = Object.keys(events_1.EventEmitter.prototype).filter(function (key) {
808
+ return typeof events_1.EventEmitter.prototype[key] === "function";
809
+ });
810
+ emitterMethods.forEach(function (fn) {
811
+ Server.prototype[fn] = function () {
812
+ return this.sockets[fn].apply(this.sockets, arguments);
813
+ };
814
+ });
815
+ module.exports = (srv, opts) => new Server(srv, opts);
816
+ module.exports.Server = Server;
817
+ module.exports.Namespace = namespace_1.Namespace;
818
+ module.exports.Socket = socket_1.Socket;