anvilsign in

collin/anvil

main / crates / anvil-web / assets / wterm / core / transport.js
1export class WebSocketTransport {
2 constructor(options = {}) {
3 this._ws = null;
4 this._reconnectTimer = null;
5 this._reconnectDelay = 1000;
6 this._closed = false;
7 this._buffer = [];
8 this.url = options.url ?? null;
9 this.reconnect = options.reconnect !== false;
10 this.maxReconnectDelay = options.maxReconnectDelay ?? 30000;
11 this.onData = options.onData ?? null;
12 this.onOpen = options.onOpen ?? null;
13 this.onClose = options.onClose ?? null;
14 this.onError = options.onError ?? null;
15 }
16 connect(url) {
17 if (url)
18 this.url = url;
19 if (!this.url)
20 throw new Error("No WebSocket URL provided");
21 this._closed = false;
22 this._ws = new WebSocket(this.url);
23 this._ws.binaryType = "arraybuffer";
24 this._ws.onopen = () => {
25 this._reconnectDelay = 1000;
26 this._flushBuffer();
27 if (this.onOpen)
28 this.onOpen();
29 };
30 this._ws.onmessage = (event) => {
31 if (this.onData) {
32 if (event.data instanceof ArrayBuffer) {
33 this.onData(new Uint8Array(event.data));
34 }
35 else {
36 this.onData(event.data);
37 }
38 }
39 };
40 this._ws.onclose = () => {
41 if (this.onClose)
42 this.onClose();
43 if (this.reconnect && !this._closed)
44 this._scheduleReconnect();
45 };
46 this._ws.onerror = (event) => {
47 if (this.onError)
48 this.onError(event);
49 this._ws?.close();
50 };
51 }
52 send(data) {
53 if (this._ws && this._ws.readyState === WebSocket.OPEN) {
54 if (typeof data === "string") {
55 this._ws.send(new TextEncoder().encode(data));
56 }
57 else {
58 this._ws.send(data);
59 }
60 }
61 else {
62 this._buffer.push(data);
63 }
64 }
65 close() {
66 this._closed = true;
67 if (this._reconnectTimer)
68 clearTimeout(this._reconnectTimer);
69 if (this._ws)
70 this._ws.close();
71 }
72 get connected() {
73 return this._ws !== null && this._ws.readyState === WebSocket.OPEN;
74 }
75 _flushBuffer() {
76 const items = this._buffer.splice(0);
77 for (const item of items) {
78 this.send(item);
79 }
80 }
81 _scheduleReconnect() {
82 this._reconnectTimer = setTimeout(() => {
83 this.connect();
84 }, this._reconnectDelay);
85 this._reconnectDelay = Math.min(this._reconnectDelay * 2, this.maxReconnectDelay);
86 }
87}