about summary refs log tree commit diff
path: root/assets/src/network/channel/connection.ts
blob: e1ed2d15828f3639cccc35990316605835905b15 (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
import { Channel, Push, Socket } from "phoenix";
import {
    Handler,
    Handlers,
    registerTokenHandler,
    UnregisterHandler,
} from "./messages/handler";
import type { AnyMessage } from "./messages/messages";
import { startRequest } from "./request";
import { startShare } from "./share";
import { connectSocket, fetchToken } from "./socket";

export enum Type {
    NONE,
    REQUEST,
    SHARE,
}

enum ConnectionState {
    CONNECTING_SOCKET,
    FETCHING_TOKEN,
    CONNECTING_CHANNEL,

    CONNECTED,
}

export type Connection = {
    socket: Socket;
    channel: Channel | null;
    token: string | null;
    state: ConnectionState;
    handlers: Handlers;
    type: Type;
};

const connection: Connection = {
    socket: new Socket("/socket", {}),
    channel: null,
    token: null,
    state: ConnectionState.CONNECTING_SOCKET,
    handlers: {},
    type: Type.NONE,
};

export async function start(type: Type.REQUEST | Type.SHARE) {
    connection.type = type;

    await connectSocket(connection.socket);

    updateState(ConnectionState.FETCHING_TOKEN);
    connection.token = await fetchToken(connection.socket);

    updateState(ConnectionState.CONNECTING_CHANNEL);
    type === Type.SHARE
        ? await startShare(connection)
        : await startRequest(connection);

    updateState(ConnectionState.CONNECTED)
}

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

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

export function onWithToken<Message extends AnyMessage>(
    event: string,
    token: string | null,
    handler: Handler<Message>
): UnregisterHandler {
    return registerTokenHandler(
        connection.handlers,
        connection.channel,
        event,
        token,
        handler
    );
}

export function on<Message extends AnyMessage>(
    event: string,
    handler: Handler<Message>
): UnregisterHandler {
    return onWithToken(event, null, handler);
}

export function getOwnToken(): string {
    if (connection.state <= ConnectionState.FETCHING_TOKEN) {
        throw new Error("There is no token yet.");
    }

    return connection.token;
}

function updateState(state: ConnectionState) {
    // TODO: Notify state listeners
    connection.state = state;
}