Cockatrice/webclient/src/websocket/WebClient.ts
2026-04-15 21:48:03 -05:00

84 lines
2.3 KiB
TypeScript

import { App, Enriched } from '@app/types';
import { ProtobufService } from './services/ProtobufService';
import { WebSocketService } from './services/WebSocketService';
import { ping } from './commands/session';
import { IWebClientResponse, IWebClientRequest } from './interfaces';
export class WebClient {
private static _instance: WebClient | null = null;
public static get instance(): WebClient {
if (!WebClient._instance) {
throw new Error(
'WebClient has not been initialized. Instantiate it via `new WebClient(response, request)` before accessing `WebClient.instance`.'
);
}
return WebClient._instance;
}
public socket: WebSocketService;
public protobuf: ProtobufService;
public response: IWebClientResponse;
public request: IWebClientRequest;
public options: Enriched.WebSocketConnectOptions | null = null;
public status: App.StatusEnum;
constructor(response: IWebClientResponse, request: IWebClientRequest) {
if (WebClient._instance) {
throw new Error('WebClient is a singleton and has already been initialized.');
}
this.response = response;
this.request = request;
this.socket = new WebSocketService({
keepAliveFn: (cb) => ping(cb),
response,
onStatusChange: (status, description) => {
this.response.session.updateStatus(status, description);
this.updateStatus(status);
},
});
this.protobuf = new ProtobufService({
send: (data) => this.socket.send(data),
isOpen: () => this.socket.checkReadyState(WebSocket.OPEN),
});
this.socket.message$.subscribe((message: MessageEvent) => {
this.protobuf.handleMessageEvent(message);
});
WebClient._instance = this;
this.response.session.initialized();
if (import.meta.env.MODE !== 'test') {
console.log(this);
}
}
public connect(options: Enriched.WebSocketConnectOptions) {
this.response.session.connectionAttempted();
this.options = options;
this.socket.connect(options);
}
public testConnect(options: Enriched.WebSocketConnectOptions) {
this.socket.testConnect(options);
}
public disconnect() {
this.socket.disconnect();
}
public updateStatus(status: App.StatusEnum) {
this.status = status;
if (status === App.StatusEnum.DISCONNECTED) {
this.protobuf.resetCommands();
}
}
}