about summary refs log tree commit diff
path: root/assets/src/network/channel/connection.ts
blob: 59e07e80934b42282d47df1a8ef56b3214f0c18a (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
import { Channel, Push, Socket } from "phoenix";
import { get, Readable, writable, Writable } from "svelte/store";
import {
    Handler,
    Handlers,
    registerTokenHandler,
    UnregisterHandler,
} from "./messages/handler";
import type { AnyMessage } from "./messages/messages";
import { connectSocket, fetchToken } from "./socket";

export enum ConnectionState {
    CONNECTING_SOCKET,
    FETCHING_TOKEN,
    CONNECTING_CHANNEL,

    CONNECTED,
}

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

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

export async function start() {
    await connectSocket(connection.socket);

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

    return connection;
}

export function send(event: string, data: any): Push {
    if (getState() !== 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 (getState() <= ConnectionState.FETCHING_TOKEN) {
        throw new Error("There is no token yet.");
    }

    return connection.token;
}

export function getState(): ConnectionState {
    return get(connection.state);
}

export function updateState(state: ConnectionState) {
    connection.state.set(state);
}

export function getStateStore(): Readable<ConnectionState> {
    return connection.state;
}