diff --git a/packages/core/src/function/websocket.ts b/packages/core/src/function/websocket.ts index b50e02d..6f72e56 100644 --- a/packages/core/src/function/websocket.ts +++ b/packages/core/src/function/websocket.ts @@ -11,8 +11,8 @@ export class Namespace extends interfaces.Namespace { public async connection(socket: io.Socket) { console.log(this.nsp.name, socket.id, 'connection'); - this.defer(socket => console.log(this.nsp.name, socket.id, 'defer', this)) - return `Welcome to Websocket Chat Room Now: ${Date.now()} Your ID: ${socket.id}! \n`; + this.defer(socket, socket => console.log(this.nsp.name, socket.id, 'defer', this)) + return `Welcome to Websocket Chat Room Now: ${Date.now()} Your ID: ${socket.id}! \r\n`; } public async disconnect(socket: io.Socket) { @@ -28,8 +28,7 @@ export class Namespace extends interfaces.Namespace { this.cache[socket.id] = (this.cache[socket.id] || '') + data; if (data == '\r' && this.cache[socket.id] !== "") { let result = new BroadcastMessage(this.cache[socket.id] + '\n') - this.cache[socket.id] = ''; - return result; + return delete this.cache[socket.id] && result; } return data; } diff --git a/packages/ws/src/builder.ts b/packages/ws/src/builder.ts index 1c2bdc4..2d5854c 100644 --- a/packages/ws/src/builder.ts +++ b/packages/ws/src/builder.ts @@ -1,9 +1,9 @@ import "reflect-metadata"; import * as io from 'socket.io' import { Container } from 'inversify' -import { TYPE } from './constants' -import { interfaces, Message, BroadcastMessage } from './interfaces' -import { getNamespaces, getNamespaceMetadata, getNamespaceListenerMetadata } from './utils' +import { TYPE, METADATA_KEY } from './constants' +import { interfaces, Message, BroadcastMessage, EventMessage } from './interfaces' +import { getNamespaces, getNamespaceMetadata, getNamespaceListenerMetadata, getSocketDeferMetadata } from './utils' export function buildWebSocket(container: Container, server: io.Server) { let constructors = getNamespaces(); @@ -12,13 +12,11 @@ export function buildWebSocket(container: Container, server: io.Server) { registryNamespace(container, constructors); // get all namespaces - let namespaces = container.getAll(TYPE.Namespace) + let namespaces = container.getAll(TYPE.Namespace); for (const namespace of namespaces) { let namespaceMetadata = getNamespaceMetadata(namespace); let namespaceEventMetadata = getNamespaceListenerMetadata(namespace); - let ns = server.of(namespaceMetadata.name); - namespace.constructor.prototype.nsp = ns; - applyNamespaceMiddleware(namespaceMetadata, ns); + let ns = initNamespace(server, namespaceMetadata, namespace); ns.on('connection', async (socket: io.Socket) => { let namespaceInstance = container.getNamed(TYPE.Namespace, namespace.constructor.name); await applyEvent(namespaceInstance, socket); @@ -39,6 +37,14 @@ function registryNamespace(container: Container, constructors: any[]) { .whenTargetNamed(name); }); } + +function initNamespace(server: io.Server, namespaceMetadata: interfaces.NamespaceMetadata, namespace: interfaces.Namespace) { + let ns = server.of(namespaceMetadata.name); + namespace.constructor.prototype.nsp = ns; + applyNamespaceMiddleware(namespaceMetadata, ns); + return ns; +} + function applyNamespaceMiddleware(namespaceMetadata: interfaces.NamespaceMetadata, ns: io.Namespace) { for (const middleware of namespaceMetadata.middleware) { ns.use(middleware); @@ -53,6 +59,7 @@ function flatten(arr: Array) { } function applyMiddlewares(namespaceEventMetadata: interfaces.ListenerMetadata[], socket: io.Socket) { + // flatten all event middleware and apply let middlewares = [...new Set(flatten(namespaceEventMetadata.map((data) => data.middleware)))]; for (const middleware of middlewares) { socket.use((packet: io.Packet, next: (err?: any) => void) => { middleware(socket, packet, next); }); @@ -60,14 +67,19 @@ function applyMiddlewares(namespaceEventMetadata: interfaces.ListenerMetadata[], } async function applyEvent(namespaceInstance: interfaces.Namespace, socket: io.Socket) { + // init socket defer array + Reflect.defineMetadata(METADATA_KEY.defer, [], socket); + // apply connection event if (namespaceInstance.connection) { let result = await namespaceInstance.connection(socket); if (result != undefined) { socket.send(result); } } + // apply disconnect event socket.on('disconnect', async () => { - await namespaceInstance.defers.forEach(defer => defer(socket)); + // exec defer function + getSocketDeferMetadata(socket).forEach(defer => defer(socket)); if (namespaceInstance.disconnect) { await namespaceInstance.disconnect(socket); } @@ -79,12 +91,12 @@ function applyListeners(namespaceEventMetadata: interfaces.ListenerMetadata[], s socket.on(event.name, async data => { let result = await namespaceInstance[event.key](socket, data); if (result != undefined) { - if (result instanceof Message) { - if (result instanceof BroadcastMessage) { - socket.broadcast.emit(result.event || event.name, result.message); - } else { - socket.emit(result.event || event.name, result.message); - } + if (result instanceof BroadcastMessage) { + socket.broadcast.emit(result.event || event.name, result.message); + } else if (result instanceof EventMessage) { + socket.emit(result.event || event.name, result.message); + } else if (result instanceof Message) { + socket.emit(result.event || 'message', result.message); } else { socket.emit(event.name, result); } diff --git a/packages/ws/src/constants.ts b/packages/ws/src/constants.ts index 0c63629..5464906 100644 --- a/packages/ws/src/constants.ts +++ b/packages/ws/src/constants.ts @@ -5,5 +5,6 @@ export const TYPE = { export const METADATA_KEY = { namespace: "@cc-server/ws:namespace", - listener: "@cc-server/ws:listener" + listener: "@cc-server/ws:listener", + defer: "@cc-server/ws:defer" }; diff --git a/packages/ws/src/interfaces.ts b/packages/ws/src/interfaces.ts index c70e1b3..042e0d7 100644 --- a/packages/ws/src/interfaces.ts +++ b/packages/ws/src/interfaces.ts @@ -1,23 +1,24 @@ import * as io from 'socket.io' import { injectable } from 'inversify'; +import { getSocketDeferMetadata } from './utils' export class Message { constructor(public message: any, public event?: string) { } } +export class EventMessage extends Message { +} export class BroadcastMessage extends Message { } export namespace interfaces { + export type SocketEvent = ((socket: io.Socket) => void); + @injectable() export class Namespace { /** * @see io.Namespace */ public nsp?: io.Namespace; - /** - * Defer Functions Array - */ - public defers?: ((socket: io.Socket) => void)[] = []; /** * The event fired when we get a new connection * @param socket socket @@ -32,8 +33,8 @@ export namespace interfaces { /** * add disconnect defer function */ - protected defer?(fn: (socket: io.Socket) => void) { - this.defers.push(fn); + protected defer?(socket: io.Socket, fn: SocketEvent) { + getSocketDeferMetadata(socket).unshift(fn); } /** * Event Listener diff --git a/packages/ws/src/utils.ts b/packages/ws/src/utils.ts index 8fc5993..fa96fb3 100644 --- a/packages/ws/src/utils.ts +++ b/packages/ws/src/utils.ts @@ -29,9 +29,18 @@ function getNamespaceListenerMetadata(target: any) { return eventMetadata; } +function getSocketDeferMetadata(target: any) { + let socketDeferMetadata: interfaces.SocketEvent[] = Reflect.getMetadata( + METADATA_KEY.defer, + target + ) || []; + return socketDeferMetadata; +} + export { getNamespaces, getNamespaceMetadata, getNamespacesMetadata, - getNamespaceListenerMetadata + getNamespaceListenerMetadata, + getSocketDeferMetadata }