about summary refs log tree commit diff
path: root/assets/src/network/channel/connection.ts
blob: a26f6242adaf393565a28788bbdf803dab2cd720 (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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { Channel, Push, Socket } from "phoenix";
import { get, Readable, writable, Writable } from "svelte/store";
import { RookType } from "../../models/rook_type";
import getShareToken from "../../utils/getShareToken";
import type { AnyMessage } from "./messages/messages";
import {
    MessageHandler,
    routeEventToHandler,
} from "./messages/message_handler";
import {
    connectSocket,
    fetchTokenFromSocket,
    joinRequestChannel,
    joinShareChannel,
} from "./socket";

export enum ConnectionState {
    CONNECTING_SOCKET,
    FETCHING_TOKEN,
    CONNECTING_CHANNEL,

    CONNECTED,
}

export class Connection {
    socket: Socket;
    channel: Channel | null;
    token: string | null;
    state: Writable<ConnectionState>;

    handler: MessageHandler<AnyMessage>;

    constructor() {
        this.socket = new Socket("/socket", {});
        this.channel = null;
        this.token = null;
        this.state = writable(ConnectionState.CONNECTING_SOCKET);
        this.handler = {};
    }

    async start(type: RookType) {
        // Connect to server.
        await connectSocket(this.socket);

        // Fetch token for connection.
        this.updateState(ConnectionState.FETCHING_TOKEN);
        this.token = await fetchTokenFromSocket(this.socket);

        // Connect to the correct channel.
        this.updateState(ConnectionState.CONNECTING_CHANNEL);
        switch (type) {
            case RookType.REQUEST:
                const requestChannel = await joinRequestChannel(
                    this.socket,
                    this.token,
                    getShareToken()
                );
                this.channel = requestChannel;

                break;
            case RookType.SHARE:
                const shareChannel = await joinShareChannel(
                    this.socket,
                    this.token
                );
                this.channel = shareChannel;

                break;
        }

        this.updateState(ConnectionState.CONNECTED);

        // Setup up event handler.
        this.channel.onMessage = (event, payload) => {
            const payloadWithEvent = { ...payload, event_name: event };
            routeEventToHandler(event, payloadWithEvent, this.handler);
            return payload;
        };
    }

    send(event: string, data: any): Push {
        if (get(this.getState()) !== ConnectionState.CONNECTED) {
            throw new Error("There is no connection yet.");
        }

        return this.channel.push(event, data);
    }

    getOwnToken(): string {
        if (get(this.getState()) <= ConnectionState.FETCHING_TOKEN) {
            throw new Error("There is no token yet.");
        }

        return this.token;
    }

    getState(): Writable<ConnectionState> {
        return this.state;
    }

    updateState(state: ConnectionState) {
        this.state.set(state);
    }

    setChannelMessageHandler(handler: MessageHandler<AnyMessage>) {
        this.handler = handler;
    }
}