about summary refs log tree commit diff
path: root/assets/src/network/channel/messages/handler.ts
blob: 5cfe327e05d9cbabc60c53c0428550630f2576ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { getChannel } from "../connection";
import type { AnyMessage } from "./messages";

export type Handlers = {
    [event: string]: EventHandler<unknown>;
};

type EventHandler<Message extends AnyMessage> = {
    tokenHandler: TokenHandler<Message>;
    directHandlers: Handler<Message>[];
};

export type TokenHandler<Message extends AnyMessage> = {
    [token: string]: Handler<Message>;
};

export type Handler<Message extends AnyMessage> = (message?: Message) => void;

export type UnregisterHandler = () => void;

export function registerTokenHandler<Message extends AnyMessage>(
    handlers: Handlers,
    event: string,
    token: string | null,
    handler: Handler<Message>
): UnregisterHandler {
    let eventHandler = handlers[event];

    // If this event did not yet have any handlers registered we have to register it
    if (eventHandler === undefined) {
        eventHandler = {
            tokenHandler: {},
            directHandlers: [],
        };

        handlers[event] = eventHandler;

        registerNewEvent<Message>(eventHandler, event);
    }

    let unregister: UnregisterHandler;

    if (token === null) {
        const directHandlers = eventHandler.directHandlers;
        directHandlers.push(handler);

        unregister = () => {
            const index = directHandlers.findIndex(h => h === handler);
            directHandlers.splice(index, 1);
        };
    } else {
        const tokenHandler = eventHandler.tokenHandler;
        tokenHandler[token] = handler;

        unregister = () => {
            delete tokenHandler[token];
        };
    }

    return unregister;
}

function registerNewEvent<Message extends AnyMessage>(
    eventHandler: EventHandler<Message>,
    event: string
) {
    const callback = (data: Message) => {
        handleEvent<Message>(eventHandler, data);
    };

    getChannel().on(event, callback);
}

function handleEvent<Message extends AnyMessage>(
    eventHandler: EventHandler<Message>,
    message: Message
) {
    if (message["token"] !== undefined) {
        const token = message["token"];

        const handler: Handler<Message> = eventHandler.tokenHandler[token];

        if (handler === undefined) {
            throw new Error("Received message for an unknown token.");
        }

        handler(message);
    }

    for (const handler of eventHandler.directHandlers) {
        handler(message);
    }
}