import { EventEmitter } from 'events' import { Client } from './client' import { SocketIO } from './interfaces' import { ServerEvent } from './constants' import { Socket } from './socket' import { Adapter } from './adapter' import { Server } from './index' import { Packet } from './packet' import { PacketTypes, SubPacketTypes } from './types' export class Namespace extends EventEmitter implements SocketIO.Namespace { name: string server: Server sockets: { [id: string]: Socket } connected: { [id: string]: Socket } adapter: SocketIO.Adapter json: SocketIO.Namespace fns: any[] ids: number rooms: string[] flags: { [key: string]: boolean } private events = ['connect', 'connection', 'newListener'] constructor(name: string, server: Server) { super() this.name = name this.server = server this.sockets = {} this.connected = {} this.fns = [] this.ids = 0 this.rooms = [] this.flags = {} this.adapter = new Adapter(this) } initAdapter() { // @ts-ignore this.adapter = new (this.server.adapter())() } add(client: Client, query?: any, callback?: () => void) { // client.conn.request.url(); let socket = new Socket(this, client, {}) this.sockets[client.id] = socket client.nsps[this.name] = socket this.onconnection(socket) return socket } del(client: Client) { let socket = this.sockets[client.id] socket.disconnect() delete this.sockets[client.id] } use(fn: (socket: SocketIO.Socket, fn: (err?: any) => void) => void): SocketIO.Namespace { throw new Error("Method not implemented.") } to(room: string): SocketIO.Namespace { if (!~this.rooms.indexOf(room)) this.rooms.push(room) return this } in(room: string): SocketIO.Namespace { return this.to(room) } send(...args: any[]): SocketIO.Namespace { super.emit('message', ...args) return this } write(...args: any[]): SocketIO.Namespace { return this.send(...args) } emit(event: string, ...args: any[]): boolean { if (~this.events.indexOf(event)) { super.emit(event, ...args) // @ts-ignore return this } // set up packet object var packet = { type: PacketTypes.MESSAGE, sub_type: (this.flags.binary !== undefined ? this.flags.binary : this.hasBin(args)) ? SubPacketTypes.BINARY_EVENT : SubPacketTypes.EVENT, name: event, data: args } if ('function' == typeof args[args.length - 1]) { throw new Error('Callbacks are not supported when broadcasting') } var rooms = this.rooms.slice(0) var flags = Object.assign({}, this.flags) // reset flags this.rooms = [] this.flags = {} this.adapter.broadcast(packet, { rooms: rooms, flags: flags }) // @ts-ignore return this } hasBin(args: any[]) { return false } clients(fn: (sockets: Socket[]) => SocketIO.Namespace): SocketIO.Namespace { return fn(Object.values(this.sockets)) } compress(compress: boolean): SocketIO.Namespace { throw new Error("Method not implemented.") } process(packet: Packet, client: Client) { switch (packet.sub_type) { case SubPacketTypes.CONNECT: this.add(client) break default: this.sockets[client.id].onpacket(packet) break } } remove(socket: Socket) { if (this.sockets.hasOwnProperty(socket.id)) { delete this.sockets[socket.id] } else { // debug('ignoring remove for %s', socket.id); } } close() { this.removeAllListeners('connect') Object.values(this.sockets).forEach(socket => socket.disconnect(false)) } private onconnection(socket: any) { let client = socket as Socket this.sockets[client.id] = client this.emit(ServerEvent.connect, socket) client.onconnect() this.emit(ServerEvent.connection, socket) } }