diff --git a/lib/index.ts b/lib/index.ts index 0962d1b6ea..81259dad2e 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -7,11 +7,7 @@ import path = require("path"); import engine = require("engine.io"); import { Client } from "./client"; import { EventEmitter } from "events"; -import { - ExtendedError, - Namespace, - NamespaceReservedEventsMap, -} from "./namespace"; +import { ExtendedError, Namespace, ServerReservedEventsMap } from "./namespace"; import { ParentNamespace } from "./parent-namespace"; import { Adapter, Room, SocketId } from "socket.io-adapter"; import * as parser from "socket.io-parser"; @@ -176,7 +172,7 @@ export class Server< > extends StrictEventEmitter< ServerSideEvents, EmitEvents, - NamespaceReservedEventsMap + ServerReservedEventsMap > { public readonly sockets: Namespace< ListenEvents, @@ -306,7 +302,12 @@ export class Server< if (err || !allow) { run(); } else { - fn(this.parentNsps.get(nextFn.value)!.createChild(name)); + const namespace = this.parentNsps + .get(nextFn.value)! + .createChild(name); + // @ts-ignore + this.sockets.emitReserved("new_namespace", namespace); + fn(namespace); } }); }; @@ -627,6 +628,10 @@ export class Server< debug("initializing namespace %s", name); nsp = new Namespace(this, name); this._nsps.set(name, nsp); + if (name !== "/") { + // @ts-ignore + this.sockets.emitReserved("new_namespace", nsp); + } } if (fn) nsp.on("connect", fn); return nsp; diff --git a/lib/namespace.ts b/lib/namespace.ts index 1eae5318fc..4e472c1d4f 100644 --- a/lib/namespace.ts +++ b/lib/namespace.ts @@ -29,9 +29,23 @@ export interface NamespaceReservedEventsMap< ) => void; } +export interface ServerReservedEventsMap< + ListenEvents, + EmitEvents, + ServerSideEvents +> extends NamespaceReservedEventsMap< + ListenEvents, + EmitEvents, + ServerSideEvents + > { + new_namespace: ( + namespace: Namespace + ) => void; +} + export const RESERVED_EVENTS: ReadonlySet = new Set< - keyof NamespaceReservedEventsMap ->(["connect", "connection"]); + keyof ServerReservedEventsMap +>(["connect", "connection", "new_namespace"]); export class Namespace< ListenEvents extends EventsMap = DefaultEventsMap, diff --git a/test/socket.io.ts b/test/socket.io.ts index 84c57d1acb..88bf1adae3 100644 --- a/test/socket.io.ts +++ b/test/socket.io.ts @@ -812,7 +812,7 @@ describe("socket.io", () => { }); }); - it("should close a client without namespace", (done) => { + it("should close a client without namespace (2)", (done) => { const srv = createServer(); const sio = new Server(srv, { connectTimeout: 100, @@ -886,6 +886,17 @@ describe("socket.io", () => { }); }); + it("should emit an 'new_namespace' event", (done) => { + const sio = new Server(); + + sio.on("new_namespace", (namespace) => { + expect(namespace.name).to.eql("/nsp"); + done(); + }); + + sio.of("/nsp"); + }); + describe("dynamic namespaces", () => { it("should allow connections to dynamic namespaces with a regex", (done) => { const srv = createServer(); @@ -942,6 +953,24 @@ describe("socket.io", () => { }); }); }); + + it("should emit an 'new_namespace' event for a dynamic namespace", (done) => { + const srv = createServer(); + const sio = new Server(srv); + srv.listen(() => { + sio.of(/^\/dynamic-\d+$/); + + sio.on("new_namespace", (namespace) => { + expect(namespace.name).to.be("/dynamic-101"); + + socket.disconnect(); + srv.close(); + done(); + }); + + const socket = client(srv, "/dynamic-101"); + }); + }); }); });