@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,584 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Namespace = exports.RESERVED_EVENTS = void 0;
7
+ const socket_1 = require("./socket");
8
+ const typed_events_1 = require("./typed-events");
9
+ const debug_1 = __importDefault(require("debug"));
10
+ const broadcast_operator_1 = require("./broadcast-operator");
11
+ const debug = (0, debug_1.default)("socket.io:namespace");
12
+ exports.RESERVED_EVENTS = new Set(["connect", "connection", "new_namespace"]);
13
+ /**
14
+ * A Namespace is a communication channel that allows you to split the logic of your application over a single shared
15
+ * connection.
16
+ *
17
+ * Each namespace has its own:
18
+ *
19
+ * - event handlers
20
+ *
21
+ * ```
22
+ * io.of("/orders").on("connection", (socket) => {
23
+ * socket.on("order:list", () => {});
24
+ * socket.on("order:create", () => {});
25
+ * });
26
+ *
27
+ * io.of("/users").on("connection", (socket) => {
28
+ * socket.on("user:list", () => {});
29
+ * });
30
+ * ```
31
+ *
32
+ * - rooms
33
+ *
34
+ * ```
35
+ * const orderNamespace = io.of("/orders");
36
+ *
37
+ * orderNamespace.on("connection", (socket) => {
38
+ * socket.join("room1");
39
+ * orderNamespace.to("room1").emit("hello");
40
+ * });
41
+ *
42
+ * const userNamespace = io.of("/users");
43
+ *
44
+ * userNamespace.on("connection", (socket) => {
45
+ * socket.join("room1"); // distinct from the room in the "orders" namespace
46
+ * userNamespace.to("room1").emit("holà");
47
+ * });
48
+ * ```
49
+ *
50
+ * - middlewares
51
+ *
52
+ * ```
53
+ * const orderNamespace = io.of("/orders");
54
+ *
55
+ * orderNamespace.use((socket, next) => {
56
+ * // ensure the socket has access to the "orders" namespace
57
+ * });
58
+ *
59
+ * const userNamespace = io.of("/users");
60
+ *
61
+ * userNamespace.use((socket, next) => {
62
+ * // ensure the socket has access to the "users" namespace
63
+ * });
64
+ * ```
65
+ */
66
+ class Namespace extends typed_events_1.StrictEventEmitter {
67
+ /**
68
+ * Namespace constructor.
69
+ *
70
+ * @param server instance
71
+ * @param name
72
+ */
73
+ constructor(server, name) {
74
+ super();
75
+ /**
76
+ * A map of currently connected sockets.
77
+ */
78
+ this.sockets = new Map();
79
+ /**
80
+ * A map of currently connecting sockets.
81
+ */
82
+ this._preConnectSockets = new Map();
83
+ this._fns = [];
84
+ /** @private */
85
+ this._ids = 0;
86
+ this.server = server;
87
+ this.name = name;
88
+ this._initAdapter();
89
+ }
90
+ /**
91
+ * Initializes the `Adapter` for this nsp.
92
+ * Run upon changing adapter by `Server#adapter`
93
+ * in addition to the constructor.
94
+ *
95
+ * @private
96
+ */
97
+ _initAdapter() {
98
+ // @ts-ignore
99
+ this.adapter = new (this.server.adapter())(this);
100
+ Promise.resolve(this.adapter.init()).catch((err) => {
101
+ debug("error while initializing adapter: %s", err);
102
+ });
103
+ }
104
+ /**
105
+ * Registers a middleware, which is a function that gets executed for every incoming {@link Socket}.
106
+ *
107
+ * @example
108
+ * const myNamespace = io.of("/my-namespace");
109
+ *
110
+ * myNamespace.use((socket, next) => {
111
+ * // ...
112
+ * next();
113
+ * });
114
+ *
115
+ * @param fn - the middleware function
116
+ */
117
+ use(fn) {
118
+ this._fns.push(fn);
119
+ return this;
120
+ }
121
+ /**
122
+ * Executes the middleware for an incoming client.
123
+ *
124
+ * @param socket - the socket that will get added
125
+ * @param fn - last fn call in the middleware
126
+ * @private
127
+ */
128
+ run(socket, fn) {
129
+ if (!this._fns.length)
130
+ return fn();
131
+ const fns = this._fns.slice(0);
132
+ function run(i) {
133
+ fns[i](socket, (err) => {
134
+ // upon error, short-circuit
135
+ if (err)
136
+ return fn(err);
137
+ // if no middleware left, summon callback
138
+ if (!fns[i + 1])
139
+ return fn();
140
+ // go on to next
141
+ run(i + 1);
142
+ });
143
+ }
144
+ run(0);
145
+ }
146
+ /**
147
+ * Targets a room when emitting.
148
+ *
149
+ * @example
150
+ * const myNamespace = io.of("/my-namespace");
151
+ *
152
+ * // the “foo” event will be broadcast to all connected clients in the “room-101” room
153
+ * myNamespace.to("room-101").emit("foo", "bar");
154
+ *
155
+ * // with an array of rooms (a client will be notified at most once)
156
+ * myNamespace.to(["room-101", "room-102"]).emit("foo", "bar");
157
+ *
158
+ * // with multiple chained calls
159
+ * myNamespace.to("room-101").to("room-102").emit("foo", "bar");
160
+ *
161
+ * @param room - a room, or an array of rooms
162
+ * @return a new {@link BroadcastOperator} instance for chaining
163
+ */
164
+ to(room) {
165
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).to(room);
166
+ }
167
+ /**
168
+ * Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:
169
+ *
170
+ * @example
171
+ * const myNamespace = io.of("/my-namespace");
172
+ *
173
+ * // disconnect all clients in the "room-101" room
174
+ * myNamespace.in("room-101").disconnectSockets();
175
+ *
176
+ * @param room - a room, or an array of rooms
177
+ * @return a new {@link BroadcastOperator} instance for chaining
178
+ */
179
+ in(room) {
180
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).in(room);
181
+ }
182
+ /**
183
+ * Excludes a room when emitting.
184
+ *
185
+ * @example
186
+ * const myNamespace = io.of("/my-namespace");
187
+ *
188
+ * // the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
189
+ * myNamespace.except("room-101").emit("foo", "bar");
190
+ *
191
+ * // with an array of rooms
192
+ * myNamespace.except(["room-101", "room-102"]).emit("foo", "bar");
193
+ *
194
+ * // with multiple chained calls
195
+ * myNamespace.except("room-101").except("room-102").emit("foo", "bar");
196
+ *
197
+ * @param room - a room, or an array of rooms
198
+ * @return a new {@link BroadcastOperator} instance for chaining
199
+ */
200
+ except(room) {
201
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).except(room);
202
+ }
203
+ /**
204
+ * Adds a new client.
205
+ *
206
+ * @return {Socket}
207
+ * @private
208
+ */
209
+ async _add(client, auth, fn) {
210
+ var _a;
211
+ debug("adding socket to nsp %s", this.name);
212
+ const socket = await this._createSocket(client, auth);
213
+ this._preConnectSockets.set(socket.id, socket);
214
+ if (
215
+ // @ts-ignore
216
+ ((_a = this.server.opts.connectionStateRecovery) === null || _a === void 0 ? void 0 : _a.skipMiddlewares) &&
217
+ socket.recovered &&
218
+ client.conn.readyState === "open") {
219
+ return this._doConnect(socket, fn);
220
+ }
221
+ this.run(socket, (err) => {
222
+ process.nextTick(() => {
223
+ if ("open" !== client.conn.readyState) {
224
+ debug("next called after client was closed - ignoring socket");
225
+ socket._cleanup();
226
+ return;
227
+ }
228
+ if (err) {
229
+ debug("middleware error, sending CONNECT_ERROR packet to the client");
230
+ socket._cleanup();
231
+ if (client.conn.protocol === 3) {
232
+ return socket._error(err.data || err.message);
233
+ }
234
+ else {
235
+ return socket._error({
236
+ message: err.message,
237
+ data: err.data,
238
+ });
239
+ }
240
+ }
241
+ this._doConnect(socket, fn);
242
+ });
243
+ });
244
+ }
245
+ async _createSocket(client, auth) {
246
+ const sessionId = auth.pid;
247
+ const offset = auth.offset;
248
+ if (
249
+ // @ts-ignore
250
+ this.server.opts.connectionStateRecovery &&
251
+ typeof sessionId === "string" &&
252
+ typeof offset === "string") {
253
+ let session;
254
+ try {
255
+ session = await this.adapter.restoreSession(sessionId, offset);
256
+ }
257
+ catch (e) {
258
+ debug("error while restoring session: %s", e);
259
+ }
260
+ if (session) {
261
+ debug("connection state recovered for sid %s", session.sid);
262
+ return new socket_1.Socket(this, client, auth, session);
263
+ }
264
+ }
265
+ return new socket_1.Socket(this, client, auth);
266
+ }
267
+ _doConnect(socket, fn) {
268
+ this._preConnectSockets.delete(socket.id);
269
+ this.sockets.set(socket.id, socket);
270
+ // it's paramount that the internal `onconnect` logic
271
+ // fires before user-set events to prevent state order
272
+ // violations (such as a disconnection before the connection
273
+ // logic is complete)
274
+ socket._onconnect();
275
+ if (fn)
276
+ fn(socket);
277
+ // fire user-set events
278
+ this.emitReserved("connect", socket);
279
+ this.emitReserved("connection", socket);
280
+ }
281
+ /**
282
+ * Removes a client. Called by each `Socket`.
283
+ *
284
+ * @private
285
+ */
286
+ _remove(socket) {
287
+ this.sockets.delete(socket.id) || this._preConnectSockets.delete(socket.id);
288
+ }
289
+ /**
290
+ * Emits to all connected clients.
291
+ *
292
+ * @example
293
+ * const myNamespace = io.of("/my-namespace");
294
+ *
295
+ * myNamespace.emit("hello", "world");
296
+ *
297
+ * // all serializable datastructures are supported (no need to call JSON.stringify)
298
+ * myNamespace.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) });
299
+ *
300
+ * // with an acknowledgement from the clients
301
+ * myNamespace.timeout(1000).emit("some-event", (err, responses) => {
302
+ * if (err) {
303
+ * // some clients did not acknowledge the event in the given delay
304
+ * } else {
305
+ * console.log(responses); // one response per client
306
+ * }
307
+ * });
308
+ *
309
+ * @return Always true
310
+ */
311
+ emit(ev, ...args) {
312
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).emit(ev, ...args);
313
+ }
314
+ /**
315
+ * Sends a `message` event to all clients.
316
+ *
317
+ * This method mimics the WebSocket.send() method.
318
+ *
319
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
320
+ *
321
+ * @example
322
+ * const myNamespace = io.of("/my-namespace");
323
+ *
324
+ * myNamespace.send("hello");
325
+ *
326
+ * // this is equivalent to
327
+ * myNamespace.emit("message", "hello");
328
+ *
329
+ * @return self
330
+ */
331
+ send(...args) {
332
+ // This type-cast is needed because EmitEvents likely doesn't have `message` as a key.
333
+ // if you specify the EmitEvents, the type of args will be never.
334
+ this.emit("message", ...args);
335
+ return this;
336
+ }
337
+ /**
338
+ * Sends a `message` event to all clients. Sends a `message` event. Alias of {@link send}.
339
+ *
340
+ * @return self
341
+ */
342
+ write(...args) {
343
+ // This type-cast is needed because EmitEvents likely doesn't have `message` as a key.
344
+ // if you specify the EmitEvents, the type of args will be never.
345
+ this.emit("message", ...args);
346
+ return this;
347
+ }
348
+ /**
349
+ * Sends a message to the other Socket.IO servers of the cluster.
350
+ *
351
+ * @example
352
+ * const myNamespace = io.of("/my-namespace");
353
+ *
354
+ * myNamespace.serverSideEmit("hello", "world");
355
+ *
356
+ * myNamespace.on("hello", (arg1) => {
357
+ * console.log(arg1); // prints "world"
358
+ * });
359
+ *
360
+ * // acknowledgements (without binary content) are supported too:
361
+ * myNamespace.serverSideEmit("ping", (err, responses) => {
362
+ * if (err) {
363
+ * // some servers did not acknowledge the event in the given delay
364
+ * } else {
365
+ * console.log(responses); // one response per server (except the current one)
366
+ * }
367
+ * });
368
+ *
369
+ * myNamespace.on("ping", (cb) => {
370
+ * cb("pong");
371
+ * });
372
+ *
373
+ * @param ev - the event name
374
+ * @param args - an array of arguments, which may include an acknowledgement callback at the end
375
+ */
376
+ serverSideEmit(ev, ...args) {
377
+ if (exports.RESERVED_EVENTS.has(ev)) {
378
+ throw new Error(`"${String(ev)}" is a reserved event name`);
379
+ }
380
+ args.unshift(ev);
381
+ this.adapter.serverSideEmit(args);
382
+ return true;
383
+ }
384
+ /**
385
+ * Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.
386
+ *
387
+ * @example
388
+ * const myNamespace = io.of("/my-namespace");
389
+ *
390
+ * try {
391
+ * const responses = await myNamespace.serverSideEmitWithAck("ping");
392
+ * console.log(responses); // one response per server (except the current one)
393
+ * } catch (e) {
394
+ * // some servers did not acknowledge the event in the given delay
395
+ * }
396
+ *
397
+ * @param ev - the event name
398
+ * @param args - an array of arguments
399
+ *
400
+ * @return a Promise that will be fulfilled when all servers have acknowledged the event
401
+ */
402
+ serverSideEmitWithAck(ev, ...args) {
403
+ return new Promise((resolve, reject) => {
404
+ args.push((err, responses) => {
405
+ if (err) {
406
+ err.responses = responses;
407
+ return reject(err);
408
+ }
409
+ else {
410
+ return resolve(responses);
411
+ }
412
+ });
413
+ this.serverSideEmit(ev, ...args);
414
+ });
415
+ }
416
+ /**
417
+ * Called when a packet is received from another Socket.IO server
418
+ *
419
+ * @param args - an array of arguments, which may include an acknowledgement callback at the end
420
+ *
421
+ * @private
422
+ */
423
+ _onServerSideEmit(args) {
424
+ super.emitUntyped.apply(this, args);
425
+ }
426
+ /**
427
+ * Gets a list of clients.
428
+ *
429
+ * @deprecated this method will be removed in the next major release, please use {@link Namespace#serverSideEmit} or
430
+ * {@link Namespace#fetchSockets} instead.
431
+ */
432
+ allSockets() {
433
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).allSockets();
434
+ }
435
+ /**
436
+ * Sets the compress flag.
437
+ *
438
+ * @example
439
+ * const myNamespace = io.of("/my-namespace");
440
+ *
441
+ * myNamespace.compress(false).emit("hello");
442
+ *
443
+ * @param compress - if `true`, compresses the sending data
444
+ * @return self
445
+ */
446
+ compress(compress) {
447
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).compress(compress);
448
+ }
449
+ /**
450
+ * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
451
+ * receive messages (because of network slowness or other issues, or because they’re connected through long polling
452
+ * and is in the middle of a request-response cycle).
453
+ *
454
+ * @example
455
+ * const myNamespace = io.of("/my-namespace");
456
+ *
457
+ * myNamespace.volatile.emit("hello"); // the clients may or may not receive it
458
+ *
459
+ * @return self
460
+ */
461
+ get volatile() {
462
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).volatile;
463
+ }
464
+ /**
465
+ * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
466
+ *
467
+ * @example
468
+ * const myNamespace = io.of("/my-namespace");
469
+ *
470
+ * // the “foo” event will be broadcast to all connected clients on this node
471
+ * myNamespace.local.emit("foo", "bar");
472
+ *
473
+ * @return a new {@link BroadcastOperator} instance for chaining
474
+ */
475
+ get local() {
476
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).local;
477
+ }
478
+ /**
479
+ * Adds a timeout in milliseconds for the next operation.
480
+ *
481
+ * @example
482
+ * const myNamespace = io.of("/my-namespace");
483
+ *
484
+ * myNamespace.timeout(1000).emit("some-event", (err, responses) => {
485
+ * if (err) {
486
+ * // some clients did not acknowledge the event in the given delay
487
+ * } else {
488
+ * console.log(responses); // one response per client
489
+ * }
490
+ * });
491
+ *
492
+ * @param timeout
493
+ */
494
+ timeout(timeout) {
495
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).timeout(timeout);
496
+ }
497
+ /**
498
+ * Returns the matching socket instances.
499
+ *
500
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
501
+ *
502
+ * @example
503
+ * const myNamespace = io.of("/my-namespace");
504
+ *
505
+ * // return all Socket instances
506
+ * const sockets = await myNamespace.fetchSockets();
507
+ *
508
+ * // return all Socket instances in the "room1" room
509
+ * const sockets = await myNamespace.in("room1").fetchSockets();
510
+ *
511
+ * for (const socket of sockets) {
512
+ * console.log(socket.id);
513
+ * console.log(socket.handshake);
514
+ * console.log(socket.rooms);
515
+ * console.log(socket.data);
516
+ *
517
+ * socket.emit("hello");
518
+ * socket.join("room1");
519
+ * socket.leave("room2");
520
+ * socket.disconnect();
521
+ * }
522
+ */
523
+ fetchSockets() {
524
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).fetchSockets();
525
+ }
526
+ /**
527
+ * Makes the matching socket instances join the specified rooms.
528
+ *
529
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
530
+ *
531
+ * @example
532
+ * const myNamespace = io.of("/my-namespace");
533
+ *
534
+ * // make all socket instances join the "room1" room
535
+ * myNamespace.socketsJoin("room1");
536
+ *
537
+ * // make all socket instances in the "room1" room join the "room2" and "room3" rooms
538
+ * myNamespace.in("room1").socketsJoin(["room2", "room3"]);
539
+ *
540
+ * @param room - a room, or an array of rooms
541
+ */
542
+ socketsJoin(room) {
543
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).socketsJoin(room);
544
+ }
545
+ /**
546
+ * Makes the matching socket instances leave the specified rooms.
547
+ *
548
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
549
+ *
550
+ * @example
551
+ * const myNamespace = io.of("/my-namespace");
552
+ *
553
+ * // make all socket instances leave the "room1" room
554
+ * myNamespace.socketsLeave("room1");
555
+ *
556
+ * // make all socket instances in the "room1" room leave the "room2" and "room3" rooms
557
+ * myNamespace.in("room1").socketsLeave(["room2", "room3"]);
558
+ *
559
+ * @param room - a room, or an array of rooms
560
+ */
561
+ socketsLeave(room) {
562
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).socketsLeave(room);
563
+ }
564
+ /**
565
+ * Makes the matching socket instances disconnect.
566
+ *
567
+ * Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible {@link Adapter}.
568
+ *
569
+ * @example
570
+ * const myNamespace = io.of("/my-namespace");
571
+ *
572
+ * // make all socket instances disconnect (the connections might be kept alive for other namespaces)
573
+ * myNamespace.disconnectSockets();
574
+ *
575
+ * // make all socket instances in the "room1" room disconnect and close the underlying connections
576
+ * myNamespace.in("room1").disconnectSockets(true);
577
+ *
578
+ * @param close - whether to close the underlying connection
579
+ */
580
+ disconnectSockets(close = false) {
581
+ return new broadcast_operator_1.BroadcastOperator(this.adapter).disconnectSockets(close);
582
+ }
583
+ }
584
+ exports.Namespace = Namespace;
@@ -0,0 +1,30 @@
1
+ import { Namespace } from "./namespace";
2
+ import type { Server, RemoteSocket } from "./index";
3
+ import type { EventParams, EventsMap, DefaultEventsMap, EventNamesWithoutAck } from "./typed-events";
4
+ /**
5
+ * A parent namespace is a special {@link Namespace} that holds a list of child namespaces which were created either
6
+ * with a regular expression or with a function.
7
+ *
8
+ * @example
9
+ * const parentNamespace = io.of(/\/dynamic-\d+/);
10
+ *
11
+ * parentNamespace.on("connection", (socket) => {
12
+ * const childNamespace = socket.nsp;
13
+ * }
14
+ *
15
+ * // will reach all the clients that are in one of the child namespaces, like "/dynamic-101"
16
+ * parentNamespace.emit("hello", "world");
17
+ *
18
+ */
19
+ export declare class ParentNamespace<ListenEvents extends EventsMap = DefaultEventsMap, EmitEvents extends EventsMap = ListenEvents, ServerSideEvents extends EventsMap = DefaultEventsMap, SocketData = any> extends Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData> {
20
+ private static count;
21
+ private readonly children;
22
+ constructor(server: Server<ListenEvents, EmitEvents, ServerSideEvents, SocketData>);
23
+ /**
24
+ * @private
25
+ */
26
+ _initAdapter(): void;
27
+ emit<Ev extends EventNamesWithoutAck<EmitEvents>>(ev: Ev, ...args: EventParams<EmitEvents, Ev>): boolean;
28
+ createChild(name: string): Namespace<ListenEvents, EmitEvents, ServerSideEvents, SocketData>;
29
+ fetchSockets(): Promise<RemoteSocket<EmitEvents, SocketData>[]>;
30
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ParentNamespace = void 0;
7
+ const namespace_1 = require("./namespace");
8
+ const socket_io_adapter_1 = require("socket.io-adapter");
9
+ const debug_1 = __importDefault(require("debug"));
10
+ const debug = (0, debug_1.default)("socket.io:parent-namespace");
11
+ /**
12
+ * A parent namespace is a special {@link Namespace} that holds a list of child namespaces which were created either
13
+ * with a regular expression or with a function.
14
+ *
15
+ * @example
16
+ * const parentNamespace = io.of(/\/dynamic-\d+/);
17
+ *
18
+ * parentNamespace.on("connection", (socket) => {
19
+ * const childNamespace = socket.nsp;
20
+ * }
21
+ *
22
+ * // will reach all the clients that are in one of the child namespaces, like "/dynamic-101"
23
+ * parentNamespace.emit("hello", "world");
24
+ *
25
+ */
26
+ class ParentNamespace extends namespace_1.Namespace {
27
+ constructor(server) {
28
+ super(server, "/_" + ParentNamespace.count++);
29
+ this.children = new Set();
30
+ }
31
+ /**
32
+ * @private
33
+ */
34
+ _initAdapter() {
35
+ this.adapter = new ParentBroadcastAdapter(this);
36
+ }
37
+ emit(ev, ...args) {
38
+ this.children.forEach((nsp) => {
39
+ nsp.emit(ev, ...args);
40
+ });
41
+ return true;
42
+ }
43
+ createChild(name) {
44
+ debug("creating child namespace %s", name);
45
+ const namespace = new namespace_1.Namespace(this.server, name);
46
+ this["_fns"].forEach((fn) => namespace.use(fn));
47
+ this.listeners("connect").forEach((listener) => namespace.on("connect", listener));
48
+ this.listeners("connection").forEach((listener) => namespace.on("connection", listener));
49
+ this.children.add(namespace);
50
+ if (this.server._opts.cleanupEmptyChildNamespaces) {
51
+ const remove = namespace._remove;
52
+ namespace._remove = (socket) => {
53
+ remove.call(namespace, socket);
54
+ if (namespace.sockets.size === 0) {
55
+ debug("closing child namespace %s", name);
56
+ namespace.adapter.close();
57
+ this.server._nsps.delete(namespace.name);
58
+ this.children.delete(namespace);
59
+ }
60
+ };
61
+ }
62
+ this.server._nsps.set(name, namespace);
63
+ // @ts-ignore
64
+ this.server.sockets.emitReserved("new_namespace", namespace);
65
+ return namespace;
66
+ }
67
+ fetchSockets() {
68
+ // note: we could make the fetchSockets() method work for dynamic namespaces created with a regex (by sending the
69
+ // regex to the other Socket.IO servers, and returning the sockets of each matching namespace for example), but
70
+ // the behavior for namespaces created with a function is less clear
71
+ // note²: we cannot loop over each children namespace, because with multiple Socket.IO servers, a given namespace
72
+ // may exist on one node but not exist on another (since it is created upon client connection)
73
+ throw new Error("fetchSockets() is not supported on parent namespaces");
74
+ }
75
+ }
76
+ exports.ParentNamespace = ParentNamespace;
77
+ ParentNamespace.count = 0;
78
+ /**
79
+ * A dummy adapter that only supports broadcasting to child (concrete) namespaces.
80
+ * @private file
81
+ */
82
+ class ParentBroadcastAdapter extends socket_io_adapter_1.Adapter {
83
+ broadcast(packet, opts) {
84
+ this.nsp.children.forEach((nsp) => {
85
+ nsp.adapter.broadcast(packet, opts);
86
+ });
87
+ }
88
+ }