feat: setup project
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { PROTOCOL_VERSION, type ClientMessage, type ServerMessage } from '@idle/shared';
|
||||
|
||||
export type Snapshot = Extract<ServerMessage, { t: 'snapshot' }>;
|
||||
export type NetStatus = 'connecting' | 'online' | 'reconnecting';
|
||||
|
||||
export function wsUrl(): string {
|
||||
const fromEnv = import.meta.env.VITE_WS_URL;
|
||||
if (typeof fromEnv === 'string' && fromEnv.length > 0) return fromEnv;
|
||||
// сборка раздаётся самим сервером — тот же origin
|
||||
const scheme = location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
return `${scheme}://${location.host}/ws`;
|
||||
}
|
||||
|
||||
export interface ConnectHandlers {
|
||||
onStatus: (status: NetStatus) => void;
|
||||
onSnapshot: (snap: Snapshot) => void;
|
||||
}
|
||||
|
||||
/** Подключение к миру с автопереподключением; возвращает функцию закрытия. */
|
||||
export function connectWorld(handlers: ConnectHandlers): () => void {
|
||||
let ws: WebSocket | null = null;
|
||||
let disposed = false;
|
||||
let attempt = 0;
|
||||
|
||||
const open = (): void => {
|
||||
if (disposed) return;
|
||||
handlers.onStatus(attempt === 0 ? 'connecting' : 'reconnecting');
|
||||
ws = new WebSocket(wsUrl());
|
||||
|
||||
ws.onopen = () => {
|
||||
attempt = 0;
|
||||
const hello: ClientMessage = { t: 'hello', v: PROTOCOL_VERSION };
|
||||
ws?.send(JSON.stringify(hello));
|
||||
};
|
||||
ws.onmessage = (ev) => {
|
||||
let msg: ServerMessage;
|
||||
try {
|
||||
msg = JSON.parse(String(ev.data)) as ServerMessage;
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
if (msg.t === 'welcome') {
|
||||
handlers.onStatus('online');
|
||||
} else if (msg.t === 'snapshot') {
|
||||
handlers.onSnapshot(msg);
|
||||
}
|
||||
};
|
||||
ws.onclose = () => {
|
||||
if (disposed) return;
|
||||
attempt += 1;
|
||||
setTimeout(open, Math.min(500 * 2 ** Math.min(attempt, 4), 8000));
|
||||
};
|
||||
ws.onerror = () => ws?.close();
|
||||
};
|
||||
|
||||
open();
|
||||
return () => {
|
||||
disposed = true;
|
||||
ws?.close();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user