Showing
6 changed files
with
82 additions
and
66 deletions
1 | import { Socket } from "socket.io"; | 1 | import { Socket } from "socket.io"; |
2 | -import { MessageHandlerRegistry } from "../message/MessageHandlerRegistry"; | 2 | +import { ServerOutboundMessageMap } from "../../common"; |
3 | -import { Message } from "../message/types"; | 3 | +import { loginHandler } from "../message/handler/loginHandler"; |
4 | +import { MessageHandlerChain } from "../message/MessageHandlerChain"; | ||
4 | import { Room } from "../room/Room"; | 5 | import { Room } from "../room/Room"; |
5 | import { User } from "../user/User"; | 6 | import { User } from "../user/User"; |
6 | 7 | ||
... | @@ -9,17 +10,21 @@ export class Connection { | ... | @@ -9,17 +10,21 @@ export class Connection { |
9 | 10 | ||
10 | public user?: User; | 11 | public user?: User; |
11 | 12 | ||
13 | + private messageHandlerChain: MessageHandlerChain; | ||
14 | + | ||
12 | constructor(socket: Socket) { | 15 | constructor(socket: Socket) { |
13 | this.socket = socket; | 16 | this.socket = socket; |
14 | - | 17 | + this.messageHandlerChain = new MessageHandlerChain(this); |
15 | - MessageHandlerRegistry.registerHandlers(this); | ||
16 | } | 18 | } |
17 | 19 | ||
18 | public get authenticated(): boolean { | 20 | public get authenticated(): boolean { |
19 | return this.user !== undefined; | 21 | return this.user !== undefined; |
20 | } | 22 | } |
21 | 23 | ||
22 | - public send(message: Message) { | 24 | + public send<T extends keyof ServerOutboundMessageMap>( |
23 | - this.socket.emit(message.type, message); | 25 | + type: T, |
26 | + message: ServerOutboundMessageMap[T] | ||
27 | + ) { | ||
28 | + this.socket.emit(type as string, message); | ||
24 | } | 29 | } |
25 | } | 30 | } | ... | ... |
server/message/MessageHandler.ts
0 → 100644
1 | +import { Connection } from "../connection/Connection"; | ||
2 | +import { ServerInboundMessageMap, ServerResponse } from "../../common/index"; | ||
3 | + | ||
4 | +type ServerHandlerMap<T> = { | ||
5 | + [Key in keyof ServerInboundMessageMap]?: ( | ||
6 | + connection: Connection, | ||
7 | + message: Omit<ServerInboundMessageMap[Key], "result">, | ||
8 | + scope: T | ||
9 | + ) => ServerResponse< | ||
10 | + "result" extends keyof ServerInboundMessageMap[Key] | ||
11 | + ? ServerInboundMessageMap[Key]["result"] | ||
12 | + : undefined | ||
13 | + >; | ||
14 | +}; | ||
15 | + | ||
16 | +export class HandlerMap<T> { | ||
17 | + private scope: T; | ||
18 | + private handlers: ServerHandlerMap<T>; | ||
19 | + | ||
20 | + constructor(scope: T, handlers: ServerHandlerMap<T>) { | ||
21 | + this.scope = scope; | ||
22 | + this.handlers = handlers; | ||
23 | + } | ||
24 | + | ||
25 | + public handle( | ||
26 | + type: keyof ServerInboundMessageMap, | ||
27 | + connection: Connection, | ||
28 | + message: any, | ||
29 | + callback: Function | ||
30 | + ): boolean { | ||
31 | + const handler = this.handlers[type]; | ||
32 | + if (!handler) return false; | ||
33 | + const response = handler(connection, message, this.scope); | ||
34 | + callback(response); | ||
35 | + return true; | ||
36 | + } | ||
37 | +} |
server/message/MessageHandlerChain.ts
0 → 100644
1 | +import { Connection } from "../connection/Connection"; | ||
2 | +import { ServerInboundMessageMap, ServerResponse } from "../../common/index"; | ||
3 | +import { keys } from "ts-transformer-keys"; | ||
4 | + | ||
5 | +export class MessageHandlerChain { | ||
6 | + connection: Connection; | ||
7 | + | ||
8 | + constructor(connection: Connection) { | ||
9 | + this.connection = connection; | ||
10 | + | ||
11 | + for (const key in keys<ServerInboundMessageMap>()) { | ||
12 | + const type = key as keyof ServerInboundMessageMap; | ||
13 | + this.connection.socket.on(key, (message: any, callback: Function) => { | ||
14 | + if ( | ||
15 | + connection?.user && | ||
16 | + connection.user.handler.handle( | ||
17 | + type, | ||
18 | + connection, | ||
19 | + message.data, | ||
20 | + callback | ||
21 | + ) | ||
22 | + ) | ||
23 | + return; | ||
24 | + | ||
25 | + // TODO: Add more handlers | ||
26 | + }); | ||
27 | + } | ||
28 | + } | ||
29 | +} |
1 | -import { Connection } from "../connection/Connection"; | ||
2 | -import { User } from "../user/User"; | ||
3 | -import { loginHandler } from "./handler/loginHandler"; | ||
4 | -import { roomChatHandler } from "./handler/roomChatHandler"; | ||
5 | -import { roomJoinHandler } from "./handler/roomJoinHandler"; | ||
6 | -import { roomLeaveHandler } from "./handler/roomLeaveHandler"; | ||
7 | -import { roomListRequestHandler } from "./handler/roomListRequestHandler"; | ||
8 | -import { Message, MessageResponse, MessageType } from "./types"; | ||
9 | - | ||
10 | -export class MessageHandlerRegistry { | ||
11 | - static registerHandlers(connection: Connection) { | ||
12 | - this.registerHandler(connection, MessageType.LOGIN, loginHandler); | ||
13 | - this.registerHandlerAuthed( | ||
14 | - connection, | ||
15 | - MessageType.ROOM_LIST_REQUEST, | ||
16 | - roomListRequestHandler | ||
17 | - ); | ||
18 | - this.registerHandlerAuthed( | ||
19 | - connection, | ||
20 | - MessageType.ROOM_JOIN, | ||
21 | - roomJoinHandler | ||
22 | - ); | ||
23 | - this.registerHandlerAuthed( | ||
24 | - connection, | ||
25 | - MessageType.ROOM_LEAVE, | ||
26 | - roomLeaveHandler | ||
27 | - ); | ||
28 | - this.registerHandlerAuthed( | ||
29 | - connection, | ||
30 | - MessageType.ROOM_CHAT, | ||
31 | - roomChatHandler | ||
32 | - ); | ||
33 | - } | ||
34 | - | ||
35 | - private static registerHandler<T extends Message, S>( | ||
36 | - connection: Connection, | ||
37 | - typeName: string, | ||
38 | - handler: (connection: Connection, message: T) => MessageResponse<S> | ||
39 | - ) { | ||
40 | - connection.socket.on(typeName, (message: T, callback: Function) => { | ||
41 | - const response = handler(connection, message); | ||
42 | - callback(response); | ||
43 | - }); | ||
44 | - } | ||
45 | - | ||
46 | - private static registerHandlerAuthed<T extends Message, S>( | ||
47 | - connection: Connection, | ||
48 | - typeName: string, | ||
49 | - handler: (user: User, message: T) => MessageResponse<S> | ||
50 | - ) { | ||
51 | - connection.socket.on(typeName, (message: T, callback: Function) => { | ||
52 | - if (connection.user !== undefined) { | ||
53 | - const response = handler(connection.user, message); | ||
54 | - callback(response); | ||
55 | - } else { | ||
56 | - callback({ ok: false }); | ||
57 | - } | ||
58 | - }); | ||
59 | - } | ||
60 | -} |
1 | import { Connection } from "../connection/Connection"; | 1 | import { Connection } from "../connection/Connection"; |
2 | +import { HandlerMap } from "../message/MessageHandler"; | ||
2 | import { Room } from "../room/Room"; | 3 | import { Room } from "../room/Room"; |
3 | import { UserData } from "./types"; | 4 | import { UserData } from "./types"; |
4 | 5 | ||
... | @@ -9,9 +10,12 @@ export class User { | ... | @@ -9,9 +10,12 @@ export class User { |
9 | 10 | ||
10 | public room?: Room; | 11 | public room?: Room; |
11 | 12 | ||
13 | + public handler: HandlerMap<User>; | ||
14 | + | ||
12 | constructor(username: string, connection: Connection) { | 15 | constructor(username: string, connection: Connection) { |
13 | this.username = username; | 16 | this.username = username; |
14 | this.connection = connection; | 17 | this.connection = connection; |
18 | + this.handler = new HandlerMap<User>(this, {}); | ||
15 | } | 19 | } |
16 | 20 | ||
17 | public getData(): UserData { | 21 | public getData(): UserData { | ... | ... |
-
Please register or login to post a comment