//// // The terminal communicates with the shell via websockets. import type { Message } from "../shared/types" import { sessionId } from "./session" import { dispatchMessage } from "./dispatch" import { addErrorMessage } from "./scrollback" const MAX_RETRIES = 5 let retries = 0 let connected = false let msgQueue: Omit[] = [] let ws: WebSocket | null = null // open our websocket connection export function startConnection() { const url = new URL(`/ws?session=${sessionId}`, location.href) url.protocol = url.protocol.replace('http', 'ws') ws = new WebSocket(url) ws.onmessage = receive ws.onclose = retryConnection ws.onerror = () => ws?.close() ws.onopen = () => { connected = true msgQueue.forEach(msg => send(msg)) msgQueue.length = 0 } } // send any message export function send(msg: Omit) { if (!connected) { msgQueue.push(msg) startConnection() return } if (!(msg as any).session) (msg as any).session = sessionId ws?.readyState === 1 && ws.send(JSON.stringify(msg)) console.log("-> send", msg) } async function receive(e: MessageEvent) { const data = JSON.parse(e.data) as Message console.log("<- receive", data) await dispatchMessage(data) } // close it... plz don't do this, though export function close() { ws?.close(1000, 'bye') } function retryConnection() { connected = false if (retries >= MAX_RETRIES) { addErrorMessage(`Failed to reconnect ${retries} times. Server is down.`) if (ws) ws.onclose = () => { } return } retries++ addErrorMessage(`Connection lost. Retrying...`) setTimeout(startConnection, 2000) }