UNPKG

webserial-core

Version:

Webserial Core to easy connections with serial devices

1,572 lines (1,571 loc) 109 kB
class J extends CustomEvent { constructor(e, t) { super(e, t); } } class te extends EventTarget { __listeners__ = { debug: !1 }; __debug__ = !1; __listenersCallbacks__ = []; dispatch(e, t = null) { const s = new J(e, { detail: t }); this.dispatchEvent(s), this.__debug__ && this.dispatchEvent(new J("debug", { detail: { type: e, data: t } })); } dispatchAsync(e, t = null, s = 100) { const n = this; setTimeout(() => { n.dispatch(e, t); }, s); } on(e, t) { typeof this.__listeners__[e] < "u" && !this.__listeners__[e] && (this.__listeners__[e] = !0), this.__listenersCallbacks__.push({ key: e, callback: t }), this.addEventListener(e, t); } off(e, t) { this.__listenersCallbacks__ = this.__listenersCallbacks__.filter((s) => !(s.key === e && s.callback === t)), this.removeEventListener(e, t); } serialRegisterAvailableListener(e) { this.__listeners__[e] || (this.__listeners__[e] = !1); } get availableListeners() { return Object.keys(this.__listeners__).sort().map((t) => ({ type: t, listening: this.__listeners__[t] })); } removeAllListeners() { for (const e of this.__listenersCallbacks__) ["internal:queue"].includes(e.key) || (this.__listenersCallbacks__ = this.__listenersCallbacks__.filter((t) => !(t.key === e.key && t.callback === e.callback)), this.removeEventListener(e.key, e.callback)); for (const e of Object.keys(this.__listeners__)) this.__listeners__[e] = !1; } } class a extends te { static instance; static devices = {}; constructor() { super(), ["change"].forEach((t) => { this.serialRegisterAvailableListener(t); }); } static $dispatchChange(e = null) { e && e.$checkAndDispatchConnection(), a.instance.dispatch("change", { devices: a.devices, dispatcher: e }); } static typeError(e) { const t = new Error(); throw t.message = `Type ${e} is not supported`, t.name = "DeviceTypeError", t; } static registerType(e) { typeof a.devices[e] > "u" && (a.devices = { ...a.devices, [e]: {} }); } static add(e) { const t = e.typeDevice; typeof a.devices[t] > "u" && a.registerType(t); const s = e.uuid; if (typeof a.devices[t] > "u" && a.typeError(t), a.devices[t][s]) throw new Error(`Device with id ${s} already exists`); return a.devices[t][s] = e, a.$dispatchChange(e), Object.keys(a.devices[t]).indexOf(s); } static get(e, t) { return typeof a.devices[e] > "u" && a.registerType(e), typeof a.devices[e] > "u" && a.typeError(e), a.devices[e][t]; } static getAll(e = null) { return e === null ? a.devices : (typeof a.devices[e] > "u" && a.typeError(e), a.devices[e]); } static getList() { return Object.values(a.devices).map((t) => Object.values(t)).flat(); } static getByNumber(e, t) { return typeof a.devices[e] > "u" && a.typeError(e), Object.values(a.devices[e]).find((n) => n.deviceNumber === t) ?? null; } static getCustom(e, t = 1) { return typeof a.devices[e] > "u" && a.typeError(e), Object.values(a.devices[e]).find((n) => n.deviceNumber === t) ?? null; } static async connectToAll() { const e = a.getList(); for (const t of e) t.isConnected || await t.connect().catch(console.warn); return Promise.resolve(a.areAllConnected()); } static async disconnectAll() { const e = a.getList(); for (const t of e) t.isDisconnected || await t.disconnect().catch(console.warn); return Promise.resolve(a.areAllDisconnected()); } static async areAllConnected() { const e = a.getList(); for (const t of e) if (!t.isConnected) return Promise.resolve(!1); return Promise.resolve(!0); } static async areAllDisconnected() { const e = a.getList(); for (const t of e) if (!t.isDisconnected) return Promise.resolve(!1); return Promise.resolve(!0); } static async getAllConnected() { const e = a.getList(); return Promise.resolve(e.filter((t) => t.isConnected)); } static async getAllDisconnected() { const e = a.getList(); return Promise.resolve(e.filter((t) => t.isDisconnected)); } } a.instance || (a.instance = new a()); function Q(i = 100) { return new Promise( (e) => setTimeout(() => e(), i) ); } const m = /* @__PURE__ */ Object.create(null); m.open = "0"; m.close = "1"; m.ping = "2"; m.pong = "3"; m.message = "4"; m.upgrade = "5"; m.noop = "6"; const S = /* @__PURE__ */ Object.create(null); Object.keys(m).forEach((i) => { S[m[i]] = i; }); const U = { type: "error", data: "parser error" }, se = typeof Blob == "function" || typeof Blob < "u" && Object.prototype.toString.call(Blob) === "[object BlobConstructor]", ie = typeof ArrayBuffer == "function", ne = (i) => typeof ArrayBuffer.isView == "function" ? ArrayBuffer.isView(i) : i && i.buffer instanceof ArrayBuffer, H = ({ type: i, data: e }, t, s) => se && e instanceof Blob ? t ? s(e) : X(e, s) : ie && (e instanceof ArrayBuffer || ne(e)) ? t ? s(e) : X(new Blob([e]), s) : s(m[i] + (e || "")), X = (i, e) => { const t = new FileReader(); return t.onload = function() { const s = t.result.split(",")[1]; e("b" + (s || "")); }, t.readAsDataURL(i); }; function j(i) { return i instanceof Uint8Array ? i : i instanceof ArrayBuffer ? new Uint8Array(i) : new Uint8Array(i.buffer, i.byteOffset, i.byteLength); } let P; function de(i, e) { if (se && i.data instanceof Blob) return i.data.arrayBuffer().then(j).then(e); if (ie && (i.data instanceof ArrayBuffer || ne(i.data))) return e(j(i.data)); H(i, !1, (t) => { P || (P = new TextEncoder()), e(P.encode(t)); }); } const G = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", k = typeof Uint8Array > "u" ? [] : new Uint8Array(256); for (let i = 0; i < G.length; i++) k[G.charCodeAt(i)] = i; const ye = (i) => { let e = i.length * 0.75, t = i.length, s, n = 0, r, o, c, h; i[i.length - 1] === "=" && (e--, i[i.length - 2] === "=" && e--); const u = new ArrayBuffer(e), _ = new Uint8Array(u); for (s = 0; s < t; s += 4) r = k[i.charCodeAt(s)], o = k[i.charCodeAt(s + 1)], c = k[i.charCodeAt(s + 2)], h = k[i.charCodeAt(s + 3)], _[n++] = r << 2 | o >> 4, _[n++] = (o & 15) << 4 | c >> 2, _[n++] = (c & 3) << 6 | h & 63; return u; }, ge = typeof ArrayBuffer == "function", W = (i, e) => { if (typeof i != "string") return { type: "message", data: re(i, e) }; const t = i.charAt(0); return t === "b" ? { type: "message", data: me(i.substring(1), e) } : S[t] ? i.length > 1 ? { type: S[t], data: i.substring(1) } : { type: S[t] } : U; }, me = (i, e) => { if (ge) { const t = ye(i); return re(t, e); } else return { base64: !0, data: i }; }, re = (i, e) => { switch (e) { case "blob": return i instanceof Blob ? i : new Blob([i]); case "arraybuffer": default: return i instanceof ArrayBuffer ? i : i.buffer; } }, oe = "", be = (i, e) => { const t = i.length, s = new Array(t); let n = 0; i.forEach((r, o) => { H(r, !1, (c) => { s[o] = c, ++n === t && e(s.join(oe)); }); }); }, we = (i, e) => { const t = i.split(oe), s = []; for (let n = 0; n < t.length; n++) { const r = W(t[n], e); if (s.push(r), r.type === "error") break; } return s; }; function ve() { return new TransformStream({ transform(i, e) { de(i, (t) => { const s = t.length; let n; if (s < 126) n = new Uint8Array(1), new DataView(n.buffer).setUint8(0, s); else if (s < 65536) { n = new Uint8Array(3); const r = new DataView(n.buffer); r.setUint8(0, 126), r.setUint16(1, s); } else { n = new Uint8Array(9); const r = new DataView(n.buffer); r.setUint8(0, 127), r.setBigUint64(1, BigInt(s)); } i.data && typeof i.data != "string" && (n[0] |= 128), e.enqueue(n), e.enqueue(t); }); } }); } let N; function C(i) { return i.reduce((e, t) => e + t.length, 0); } function T(i, e) { if (i[0].length === e) return i.shift(); const t = new Uint8Array(e); let s = 0; for (let n = 0; n < e; n++) t[n] = i[0][s++], s === i[0].length && (i.shift(), s = 0); return i.length && s < i[0].length && (i[0] = i[0].slice(s)), t; } function Ee(i, e) { N || (N = new TextDecoder()); const t = []; let s = 0, n = -1, r = !1; return new TransformStream({ transform(o, c) { for (t.push(o); ; ) { if (s === 0) { if (C(t) < 1) break; const h = T(t, 1); r = (h[0] & 128) === 128, n = h[0] & 127, n < 126 ? s = 3 : n === 126 ? s = 1 : s = 2; } else if (s === 1) { if (C(t) < 2) break; const h = T(t, 2); n = new DataView(h.buffer, h.byteOffset, h.length).getUint16(0), s = 3; } else if (s === 2) { if (C(t) < 8) break; const h = T(t, 8), u = new DataView(h.buffer, h.byteOffset, h.length), _ = u.getUint32(0); if (_ > Math.pow(2, 21) - 1) { c.enqueue(U); break; } n = _ * Math.pow(2, 32) + u.getUint32(4), s = 3; } else { if (C(t) < n) break; const h = T(t, n); c.enqueue(W(r ? h : N.decode(h), e)), s = 0; } if (n === 0 || n > i) { c.enqueue(U); break; } } } }); } const ae = 4; function f(i) { if (i) return ke(i); } function ke(i) { for (var e in f.prototype) i[e] = f.prototype[e]; return i; } f.prototype.on = f.prototype.addEventListener = function(i, e) { return this._callbacks = this._callbacks || {}, (this._callbacks["$" + i] = this._callbacks["$" + i] || []).push(e), this; }; f.prototype.once = function(i, e) { function t() { this.off(i, t), e.apply(this, arguments); } return t.fn = e, this.on(i, t), this; }; f.prototype.off = f.prototype.removeListener = f.prototype.removeAllListeners = f.prototype.removeEventListener = function(i, e) { if (this._callbacks = this._callbacks || {}, arguments.length == 0) return this._callbacks = {}, this; var t = this._callbacks["$" + i]; if (!t) return this; if (arguments.length == 1) return delete this._callbacks["$" + i], this; for (var s, n = 0; n < t.length; n++) if (s = t[n], s === e || s.fn === e) { t.splice(n, 1); break; } return t.length === 0 && delete this._callbacks["$" + i], this; }; f.prototype.emit = function(i) { this._callbacks = this._callbacks || {}; for (var e = new Array(arguments.length - 1), t = this._callbacks["$" + i], s = 1; s < arguments.length; s++) e[s - 1] = arguments[s]; if (t) { t = t.slice(0); for (var s = 0, n = t.length; s < n; ++s) t[s].apply(this, e); } return this; }; f.prototype.emitReserved = f.prototype.emit; f.prototype.listeners = function(i) { return this._callbacks = this._callbacks || {}, this._callbacks["$" + i] || []; }; f.prototype.hasListeners = function(i) { return !!this.listeners(i).length; }; const O = typeof Promise == "function" && typeof Promise.resolve == "function" ? (e) => Promise.resolve().then(e) : (e, t) => t(e, 0), d = typeof self < "u" ? self : typeof window < "u" ? window : Function("return this")(), Ce = "arraybuffer"; function ce(i, ...e) { return e.reduce((t, s) => (i.hasOwnProperty(s) && (t[s] = i[s]), t), {}); } const Te = d.setTimeout, Ae = d.clearTimeout; function L(i, e) { e.useNativeTimers ? (i.setTimeoutFn = Te.bind(d), i.clearTimeoutFn = Ae.bind(d)) : (i.setTimeoutFn = d.setTimeout.bind(d), i.clearTimeoutFn = d.clearTimeout.bind(d)); } const Se = 1.33; function xe(i) { return typeof i == "string" ? Re(i) : Math.ceil((i.byteLength || i.size) * Se); } function Re(i) { let e = 0, t = 0; for (let s = 0, n = i.length; s < n; s++) e = i.charCodeAt(s), e < 128 ? t += 1 : e < 2048 ? t += 2 : e < 55296 || e >= 57344 ? t += 3 : (s++, t += 4); return t; } function le() { return Date.now().toString(36).substring(3) + Math.random().toString(36).substring(2, 5); } function Be(i) { let e = ""; for (let t in i) i.hasOwnProperty(t) && (e.length && (e += "&"), e += encodeURIComponent(t) + "=" + encodeURIComponent(i[t])); return e; } function Oe(i) { let e = {}, t = i.split("&"); for (let s = 0, n = t.length; s < n; s++) { let r = t[s].split("="); e[decodeURIComponent(r[0])] = decodeURIComponent(r[1]); } return e; } class Le extends Error { constructor(e, t, s) { super(e), this.description = t, this.context = s, this.type = "TransportError"; } } class K extends f { /** * Transport abstract constructor. * * @param {Object} opts - options * @protected */ constructor(e) { super(), this.writable = !1, L(this, e), this.opts = e, this.query = e.query, this.socket = e.socket, this.supportsBinary = !e.forceBase64; } /** * Emits an error. * * @param {String} reason * @param description * @param context - the error context * @return {Transport} for chaining * @protected */ onError(e, t, s) { return super.emitReserved("error", new Le(e, t, s)), this; } /** * Opens the transport. */ open() { return this.readyState = "opening", this.doOpen(), this; } /** * Closes the transport. */ close() { return (this.readyState === "opening" || this.readyState === "open") && (this.doClose(), this.onClose()), this; } /** * Sends multiple packets. * * @param {Array} packets */ send(e) { this.readyState === "open" && this.write(e); } /** * Called upon open * * @protected */ onOpen() { this.readyState = "open", this.writable = !0, super.emitReserved("open"); } /** * Called with data. * * @param {String} data * @protected */ onData(e) { const t = W(e, this.socket.binaryType); this.onPacket(t); } /** * Called with a decoded packet. * * @protected */ onPacket(e) { super.emitReserved("packet", e); } /** * Called upon close. * * @protected */ onClose(e) { this.readyState = "closed", super.emitReserved("close", e); } /** * Pauses the transport, in order not to lose packets during an upgrade. * * @param onPause */ pause(e) { } createUri(e, t = {}) { return e + "://" + this._hostname() + this._port() + this.opts.path + this._query(t); } _hostname() { const e = this.opts.hostname; return e.indexOf(":") === -1 ? e : "[" + e + "]"; } _port() { return this.opts.port && (this.opts.secure && +(this.opts.port !== 443) || !this.opts.secure && Number(this.opts.port) !== 80) ? ":" + this.opts.port : ""; } _query(e) { const t = Be(e); return t.length ? "?" + t : ""; } } class Pe extends K { constructor() { super(...arguments), this._polling = !1; } get name() { return "polling"; } /** * Opens the socket (triggers polling). We write a PING message to determine * when the transport is open. * * @protected */ doOpen() { this._poll(); } /** * Pauses polling. * * @param {Function} onPause - callback upon buffers are flushed and transport is paused * @package */ pause(e) { this.readyState = "pausing"; const t = () => { this.readyState = "paused", e(); }; if (this._polling || !this.writable) { let s = 0; this._polling && (s++, this.once("pollComplete", function() { --s || t(); })), this.writable || (s++, this.once("drain", function() { --s || t(); })); } else t(); } /** * Starts polling cycle. * * @private */ _poll() { this._polling = !0, this.doPoll(), this.emitReserved("poll"); } /** * Overloads onData to detect payloads. * * @protected */ onData(e) { const t = (s) => { if (this.readyState === "opening" && s.type === "open" && this.onOpen(), s.type === "close") return this.onClose({ description: "transport closed by the server" }), !1; this.onPacket(s); }; we(e, this.socket.binaryType).forEach(t), this.readyState !== "closed" && (this._polling = !1, this.emitReserved("pollComplete"), this.readyState === "open" && this._poll()); } /** * For polling, send a close packet. * * @protected */ doClose() { const e = () => { this.write([{ type: "close" }]); }; this.readyState === "open" ? e() : this.once("open", e); } /** * Writes a packets payload. * * @param {Array} packets - data packets * @protected */ write(e) { this.writable = !1, be(e, (t) => { this.doWrite(t, () => { this.writable = !0, this.emitReserved("drain"); }); }); } /** * Generates uri for connection. * * @private */ uri() { const e = this.opts.secure ? "https" : "http", t = this.query || {}; return this.opts.timestampRequests !== !1 && (t[this.opts.timestampParam] = le()), !this.supportsBinary && !t.sid && (t.b64 = 1), this.createUri(e, t); } } let he = !1; try { he = typeof XMLHttpRequest < "u" && "withCredentials" in new XMLHttpRequest(); } catch { } const Ne = he; function Ie() { } class qe extends Pe { /** * XHR Polling constructor. * * @param {Object} opts * @package */ constructor(e) { if (super(e), typeof location < "u") { const t = location.protocol === "https:"; let s = location.port; s || (s = t ? "443" : "80"), this.xd = typeof location < "u" && e.hostname !== location.hostname || s !== e.port; } } /** * Sends data. * * @param {String} data to send. * @param {Function} called upon flush. * @private */ doWrite(e, t) { const s = this.request({ method: "POST", data: e }); s.on("success", t), s.on("error", (n, r) => { this.onError("xhr post error", n, r); }); } /** * Starts a poll cycle. * * @private */ doPoll() { const e = this.request(); e.on("data", this.onData.bind(this)), e.on("error", (t, s) => { this.onError("xhr poll error", t, s); }), this.pollXhr = e; } } class g extends f { /** * Request constructor * * @param {Object} options * @package */ constructor(e, t, s) { super(), this.createRequest = e, L(this, s), this._opts = s, this._method = s.method || "GET", this._uri = t, this._data = s.data !== void 0 ? s.data : null, this._create(); } /** * Creates the XHR object and sends the request. * * @private */ _create() { var e; const t = ce(this._opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref"); t.xdomain = !!this._opts.xd; const s = this._xhr = this.createRequest(t); try { s.open(this._method, this._uri, !0); try { if (this._opts.extraHeaders) { s.setDisableHeaderCheck && s.setDisableHeaderCheck(!0); for (let n in this._opts.extraHeaders) this._opts.extraHeaders.hasOwnProperty(n) && s.setRequestHeader(n, this._opts.extraHeaders[n]); } } catch { } if (this._method === "POST") try { s.setRequestHeader("Content-type", "text/plain;charset=UTF-8"); } catch { } try { s.setRequestHeader("Accept", "*/*"); } catch { } (e = this._opts.cookieJar) === null || e === void 0 || e.addCookies(s), "withCredentials" in s && (s.withCredentials = this._opts.withCredentials), this._opts.requestTimeout && (s.timeout = this._opts.requestTimeout), s.onreadystatechange = () => { var n; s.readyState === 3 && ((n = this._opts.cookieJar) === null || n === void 0 || n.parseCookies( // @ts-ignore s.getResponseHeader("set-cookie") )), s.readyState === 4 && (s.status === 200 || s.status === 1223 ? this._onLoad() : this.setTimeoutFn(() => { this._onError(typeof s.status == "number" ? s.status : 0); }, 0)); }, s.send(this._data); } catch (n) { this.setTimeoutFn(() => { this._onError(n); }, 0); return; } typeof document < "u" && (this._index = g.requestsCount++, g.requests[this._index] = this); } /** * Called upon error. * * @private */ _onError(e) { this.emitReserved("error", e, this._xhr), this._cleanup(!0); } /** * Cleans up house. * * @private */ _cleanup(e) { if (!(typeof this._xhr > "u" || this._xhr === null)) { if (this._xhr.onreadystatechange = Ie, e) try { this._xhr.abort(); } catch { } typeof document < "u" && delete g.requests[this._index], this._xhr = null; } } /** * Called upon load. * * @private */ _onLoad() { const e = this._xhr.responseText; e !== null && (this.emitReserved("data", e), this.emitReserved("success"), this._cleanup()); } /** * Aborts the request. * * @package */ abort() { this._cleanup(); } } g.requestsCount = 0; g.requests = {}; if (typeof document < "u") { if (typeof attachEvent == "function") attachEvent("onunload", Z); else if (typeof addEventListener == "function") { const i = "onpagehide" in d ? "pagehide" : "unload"; addEventListener(i, Z, !1); } } function Z() { for (let i in g.requests) g.requests.hasOwnProperty(i) && g.requests[i].abort(); } const Ue = function() { const i = ue({ xdomain: !1 }); return i && i.responseType !== null; }(); class De extends qe { constructor(e) { super(e); const t = e && e.forceBase64; this.supportsBinary = Ue && !t; } request(e = {}) { return Object.assign(e, { xd: this.xd }, this.opts), new g(ue, this.uri(), e); } } function ue(i) { const e = i.xdomain; try { if (typeof XMLHttpRequest < "u" && (!e || Ne)) return new XMLHttpRequest(); } catch { } if (!e) try { return new d[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP"); } catch { } } const _e = typeof navigator < "u" && typeof navigator.product == "string" && navigator.product.toLowerCase() === "reactnative"; class Fe extends K { get name() { return "websocket"; } doOpen() { const e = this.uri(), t = this.opts.protocols, s = _e ? {} : ce(this.opts, "agent", "perMessageDeflate", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "localAddress", "protocolVersion", "origin", "maxPayload", "family", "checkServerIdentity"); this.opts.extraHeaders && (s.headers = this.opts.extraHeaders); try { this.ws = this.createSocket(e, t, s); } catch (n) { return this.emitReserved("error", n); } this.ws.binaryType = this.socket.binaryType, this.addEventListeners(); } /** * Adds event listeners to the socket * * @private */ addEventListeners() { this.ws.onopen = () => { this.opts.autoUnref && this.ws._socket.unref(), this.onOpen(); }, this.ws.onclose = (e) => this.onClose({ description: "websocket connection closed", context: e }), this.ws.onmessage = (e) => this.onData(e.data), this.ws.onerror = (e) => this.onError("websocket error", e); } write(e) { this.writable = !1; for (let t = 0; t < e.length; t++) { const s = e[t], n = t === e.length - 1; H(s, this.supportsBinary, (r) => { try { this.doWrite(s, r); } catch { } n && O(() => { this.writable = !0, this.emitReserved("drain"); }, this.setTimeoutFn); }); } } doClose() { typeof this.ws < "u" && (this.ws.onerror = () => { }, this.ws.close(), this.ws = null); } /** * Generates uri for connection. * * @private */ uri() { const e = this.opts.secure ? "wss" : "ws", t = this.query || {}; return this.opts.timestampRequests && (t[this.opts.timestampParam] = le()), this.supportsBinary || (t.b64 = 1), this.createUri(e, t); } } const I = d.WebSocket || d.MozWebSocket; class Me extends Fe { createSocket(e, t, s) { return _e ? new I(e, t, s) : t ? new I(e, t) : new I(e); } doWrite(e, t) { this.ws.send(t); } } class $e extends K { get name() { return "webtransport"; } doOpen() { try { this._transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]); } catch (e) { return this.emitReserved("error", e); } this._transport.closed.then(() => { this.onClose(); }).catch((e) => { this.onError("webtransport error", e); }), this._transport.ready.then(() => { this._transport.createBidirectionalStream().then((e) => { const t = Ee(Number.MAX_SAFE_INTEGER, this.socket.binaryType), s = e.readable.pipeThrough(t).getReader(), n = ve(); n.readable.pipeTo(e.writable), this._writer = n.writable.getWriter(); const r = () => { s.read().then(({ done: c, value: h }) => { c || (this.onPacket(h), r()); }).catch((c) => { }); }; r(); const o = { type: "open" }; this.query.sid && (o.data = `{"sid":"${this.query.sid}"}`), this._writer.write(o).then(() => this.onOpen()); }); }); } write(e) { this.writable = !1; for (let t = 0; t < e.length; t++) { const s = e[t], n = t === e.length - 1; this._writer.write(s).then(() => { n && O(() => { this.writable = !0, this.emitReserved("drain"); }, this.setTimeoutFn); }); } } doClose() { var e; (e = this._transport) === null || e === void 0 || e.close(); } } const Ve = { websocket: Me, webtransport: $e, polling: De }, He = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/, We = [ "source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor" ]; function D(i) { if (i.length > 8e3) throw "URI too long"; const e = i, t = i.indexOf("["), s = i.indexOf("]"); t != -1 && s != -1 && (i = i.substring(0, t) + i.substring(t, s).replace(/:/g, ";") + i.substring(s, i.length)); let n = He.exec(i || ""), r = {}, o = 14; for (; o--; ) r[We[o]] = n[o] || ""; return t != -1 && s != -1 && (r.source = e, r.host = r.host.substring(1, r.host.length - 1).replace(/;/g, ":"), r.authority = r.authority.replace("[", "").replace("]", "").replace(/;/g, ":"), r.ipv6uri = !0), r.pathNames = Ke(r, r.path), r.queryKey = ze(r, r.query), r; } function Ke(i, e) { const t = /\/{2,9}/g, s = e.replace(t, "/").split("/"); return (e.slice(0, 1) == "/" || e.length === 0) && s.splice(0, 1), e.slice(-1) == "/" && s.splice(s.length - 1, 1), s; } function ze(i, e) { const t = {}; return e.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function(s, n, r) { n && (t[n] = r); }), t; } const F = typeof addEventListener == "function" && typeof removeEventListener == "function", x = []; F && addEventListener("offline", () => { x.forEach((i) => i()); }, !1); class w extends f { /** * Socket constructor. * * @param {String|Object} uri - uri or options * @param {Object} opts - options */ constructor(e, t) { if (super(), this.binaryType = Ce, this.writeBuffer = [], this._prevBufferLen = 0, this._pingInterval = -1, this._pingTimeout = -1, this._maxPayload = -1, this._pingTimeoutTime = 1 / 0, e && typeof e == "object" && (t = e, e = null), e) { const s = D(e); t.hostname = s.host, t.secure = s.protocol === "https" || s.protocol === "wss", t.port = s.port, s.query && (t.query = s.query); } else t.host && (t.hostname = D(t.host).host); L(this, t), this.secure = t.secure != null ? t.secure : typeof location < "u" && location.protocol === "https:", t.hostname && !t.port && (t.port = this.secure ? "443" : "80"), this.hostname = t.hostname || (typeof location < "u" ? location.hostname : "localhost"), this.port = t.port || (typeof location < "u" && location.port ? location.port : this.secure ? "443" : "80"), this.transports = [], this._transportsByName = {}, t.transports.forEach((s) => { const n = s.prototype.name; this.transports.push(n), this._transportsByName[n] = s; }), this.opts = Object.assign({ path: "/engine.io", agent: !1, withCredentials: !1, upgrade: !0, timestampParam: "t", rememberUpgrade: !1, addTrailingSlash: !0, rejectUnauthorized: !0, perMessageDeflate: { threshold: 1024 }, transportOptions: {}, closeOnBeforeunload: !1 }, t), this.opts.path = this.opts.path.replace(/\/$/, "") + (this.opts.addTrailingSlash ? "/" : ""), typeof this.opts.query == "string" && (this.opts.query = Oe(this.opts.query)), F && (this.opts.closeOnBeforeunload && (this._beforeunloadEventListener = () => { this.transport && (this.transport.removeAllListeners(), this.transport.close()); }, addEventListener("beforeunload", this._beforeunloadEventListener, !1)), this.hostname !== "localhost" && (this._offlineEventListener = () => { this._onClose("transport close", { description: "network connection lost" }); }, x.push(this._offlineEventListener))), this.opts.withCredentials && (this._cookieJar = void 0), this._open(); } /** * Creates transport of the given type. * * @param {String} name - transport name * @return {Transport} * @private */ createTransport(e) { const t = Object.assign({}, this.opts.query); t.EIO = ae, t.transport = e, this.id && (t.sid = this.id); const s = Object.assign({}, this.opts, { query: t, socket: this, hostname: this.hostname, secure: this.secure, port: this.port }, this.opts.transportOptions[e]); return new this._transportsByName[e](s); } /** * Initializes transport to use and starts probe. * * @private */ _open() { if (this.transports.length === 0) { this.setTimeoutFn(() => { this.emitReserved("error", "No transports available"); }, 0); return; } const e = this.opts.rememberUpgrade && w.priorWebsocketSuccess && this.transports.indexOf("websocket") !== -1 ? "websocket" : this.transports[0]; this.readyState = "opening"; const t = this.createTransport(e); t.open(), this.setTransport(t); } /** * Sets the current transport. Disables the existing one (if any). * * @private */ setTransport(e) { this.transport && this.transport.removeAllListeners(), this.transport = e, e.on("drain", this._onDrain.bind(this)).on("packet", this._onPacket.bind(this)).on("error", this._onError.bind(this)).on("close", (t) => this._onClose("transport close", t)); } /** * Called when connection is deemed open. * * @private */ onOpen() { this.readyState = "open", w.priorWebsocketSuccess = this.transport.name === "websocket", this.emitReserved("open"), this.flush(); } /** * Handles a packet. * * @private */ _onPacket(e) { if (this.readyState === "opening" || this.readyState === "open" || this.readyState === "closing") switch (this.emitReserved("packet", e), this.emitReserved("heartbeat"), e.type) { case "open": this.onHandshake(JSON.parse(e.data)); break; case "ping": this._sendPacket("pong"), this.emitReserved("ping"), this.emitReserved("pong"), this._resetPingTimeout(); break; case "error": const t = new Error("server error"); t.code = e.data, this._onError(t); break; case "message": this.emitReserved("data", e.data), this.emitReserved("message", e.data); break; } } /** * Called upon handshake completion. * * @param {Object} data - handshake obj * @private */ onHandshake(e) { this.emitReserved("handshake", e), this.id = e.sid, this.transport.query.sid = e.sid, this._pingInterval = e.pingInterval, this._pingTimeout = e.pingTimeout, this._maxPayload = e.maxPayload, this.onOpen(), this.readyState !== "closed" && this._resetPingTimeout(); } /** * Sets and resets ping timeout timer based on server pings. * * @private */ _resetPingTimeout() { this.clearTimeoutFn(this._pingTimeoutTimer); const e = this._pingInterval + this._pingTimeout; this._pingTimeoutTime = Date.now() + e, this._pingTimeoutTimer = this.setTimeoutFn(() => { this._onClose("ping timeout"); }, e), this.opts.autoUnref && this._pingTimeoutTimer.unref(); } /** * Called on `drain` event * * @private */ _onDrain() { this.writeBuffer.splice(0, this._prevBufferLen), this._prevBufferLen = 0, this.writeBuffer.length === 0 ? this.emitReserved("drain") : this.flush(); } /** * Flush write buffers. * * @private */ flush() { if (this.readyState !== "closed" && this.transport.writable && !this.upgrading && this.writeBuffer.length) { const e = this._getWritablePackets(); this.transport.send(e), this._prevBufferLen = e.length, this.emitReserved("flush"); } } /** * Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP * long-polling) * * @private */ _getWritablePackets() { if (!(this._maxPayload && this.transport.name === "polling" && this.writeBuffer.length > 1)) return this.writeBuffer; let t = 1; for (let s = 0; s < this.writeBuffer.length; s++) { const n = this.writeBuffer[s].data; if (n && (t += xe(n)), s > 0 && t > this._maxPayload) return this.writeBuffer.slice(0, s); t += 2; } return this.writeBuffer; } /** * Checks whether the heartbeat timer has expired but the socket has not yet been notified. * * Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the * `write()` method then the message would not be buffered by the Socket.IO client. * * @return {boolean} * @private */ /* private */ _hasPingExpired() { if (!this._pingTimeoutTime) return !0; const e = Date.now() > this._pingTimeoutTime; return e && (this._pingTimeoutTime = 0, O(() => { this._onClose("ping timeout"); }, this.setTimeoutFn)), e; } /** * Sends a message. * * @param {String} msg - message. * @param {Object} options. * @param {Function} fn - callback function. * @return {Socket} for chaining. */ write(e, t, s) { return this._sendPacket("message", e, t, s), this; } /** * Sends a message. Alias of {@link Socket#write}. * * @param {String} msg - message. * @param {Object} options. * @param {Function} fn - callback function. * @return {Socket} for chaining. */ send(e, t, s) { return this._sendPacket("message", e, t, s), this; } /** * Sends a packet. * * @param {String} type: packet type. * @param {String} data. * @param {Object} options. * @param {Function} fn - callback function. * @private */ _sendPacket(e, t, s, n) { if (typeof t == "function" && (n = t, t = void 0), typeof s == "function" && (n = s, s = null), this.readyState === "closing" || this.readyState === "closed") return; s = s || {}, s.compress = s.compress !== !1; const r = { type: e, data: t, options: s }; this.emitReserved("packetCreate", r), this.writeBuffer.push(r), n && this.once("flush", n), this.flush(); } /** * Closes the connection. */ close() { const e = () => { this._onClose("forced close"), this.transport.close(); }, t = () => { this.off("upgrade", t), this.off("upgradeError", t), e(); }, s = () => { this.once("upgrade", t), this.once("upgradeError", t); }; return (this.readyState === "opening" || this.readyState === "open") && (this.readyState = "closing", this.writeBuffer.length ? this.once("drain", () => { this.upgrading ? s() : e(); }) : this.upgrading ? s() : e()), this; } /** * Called upon transport error * * @private */ _onError(e) { if (w.priorWebsocketSuccess = !1, this.opts.tryAllTransports && this.transports.length > 1 && this.readyState === "opening") return this.transports.shift(), this._open(); this.emitReserved("error", e), this._onClose("transport error", e); } /** * Called upon transport close. * * @private */ _onClose(e, t) { if (this.readyState === "opening" || this.readyState === "open" || this.readyState === "closing") { if (this.clearTimeoutFn(this._pingTimeoutTimer), this.transport.removeAllListeners("close"), this.transport.close(), this.transport.removeAllListeners(), F && (this._beforeunloadEventListener && removeEventListener("beforeunload", this._beforeunloadEventListener, !1), this._offlineEventListener)) { const s = x.indexOf(this._offlineEventListener); s !== -1 && x.splice(s, 1); } this.readyState = "closed", this.id = null, this.emitReserved("close", e, t), this.writeBuffer = [], this._prevBufferLen = 0; } } } w.protocol = ae; class Ye extends w { constructor() { super(...arguments), this._upgrades = []; } onOpen() { if (super.onOpen(), this.readyState === "open" && this.opts.upgrade) for (let e = 0; e < this._upgrades.length; e++) this._probe(this._upgrades[e]); } /** * Probes a transport. * * @param {String} name - transport name * @private */ _probe(e) { let t = this.createTransport(e), s = !1; w.priorWebsocketSuccess = !1; const n = () => { s || (t.send([{ type: "ping", data: "probe" }]), t.once("packet", (p) => { if (!s) if (p.type === "pong" && p.data === "probe") { if (this.upgrading = !0, this.emitReserved("upgrading", t), !t) return; w.priorWebsocketSuccess = t.name === "websocket", this.transport.pause(() => { s || this.readyState !== "closed" && (_(), this.setTransport(t), t.send([{ type: "upgrade" }]), this.emitReserved("upgrade", t), t = null, this.upgrading = !1, this.flush()); }); } else { const b = new Error("probe error"); b.transport = t.name, this.emitReserved("upgradeError", b); } })); }; function r() { s || (s = !0, _(), t.close(), t = null); } const o = (p) => { const b = new Error("probe error: " + p); b.transport = t.name, r(), this.emitReserved("upgradeError", b); }; function c() { o("transport closed"); } function h() { o("socket closed"); } function u(p) { t && p.name !== t.name && r(); } const _ = () => { t.removeListener("open", n), t.removeListener("error", o), t.removeListener("close", c), this.off("close", h), this.off("upgrading", u); }; t.once("open", n), t.once("error", o), t.once("close", c), this.once("close", h), this.once("upgrading", u), this._upgrades.indexOf("webtransport") !== -1 && e !== "webtransport" ? this.setTimeoutFn(() => { s || t.open(); }, 200) : t.open(); } onHandshake(e) { this._upgrades = this._filterUpgrades(e.upgrades), super.onHandshake(e); } /** * Filters upgrades, returning only those matching client transports. * * @param {Array} upgrades - server upgrades * @private */ _filterUpgrades(e) { const t = []; for (let s = 0; s < e.length; s++) ~this.transports.indexOf(e[s]) && t.push(e[s]); return t; } } let Je = class extends Ye { constructor(e, t = {}) { const s = typeof e == "object" ? e : t; (!s.transports || s.transports && typeof s.transports[0] == "string") && (s.transports = (s.transports || ["polling", "websocket", "webtransport"]).map((n) => Ve[n]).filter((n) => !!n)), super(e, s); } }; function Qe(i, e = "", t) { let s = i; t = t || typeof location < "u" && location, i == null && (i = t.protocol + "//" + t.host), typeof i == "string" && (i.charAt(0) === "/" && (i.charAt(1) === "/" ? i = t.protocol + i : i = t.host + i), /^(https?|wss?):\/\//.test(i) || (typeof t < "u" ? i = t.protocol + "//" + i : i = "https://" + i), s = D(i)), s.port || (/^(http|ws)$/.test(s.protocol) ? s.port = "80" : /^(http|ws)s$/.test(s.protocol) && (s.port = "443")), s.path = s.path || "/"; const r = s.host.indexOf(":") !== -1 ? "[" + s.host + "]" : s.host; return s.id = s.protocol + "://" + r + ":" + s.port + e, s.href = s.protocol + "://" + r + (t && t.port === s.port ? "" : ":" + s.port), s; } const Xe = typeof ArrayBuffer == "function", je = (i) => typeof ArrayBuffer.isView == "function" ? ArrayBuffer.isView(i) : i.buffer instanceof ArrayBuffer, fe = Object.prototype.toString, Ge = typeof Blob == "function" || typeof Blob < "u" && fe.call(Blob) === "[object BlobConstructor]", Ze = typeof File == "function" || typeof File < "u" && fe.call(File) === "[object FileConstructor]"; function z(i) { return Xe && (i instanceof ArrayBuffer || je(i)) || Ge && i instanceof Blob || Ze && i instanceof File; } function R(i, e) { if (!i || typeof i != "object") return !1; if (Array.isArray(i)) { for (let t = 0, s = i.length; t < s; t++) if (R(i[t])) return !0; return !1; } if (z(i)) return !0; if (i.toJSON && typeof i.toJSON == "function" && arguments.length === 1) return R(i.toJSON(), !0); for (const t in i) if (Object.prototype.hasOwnProperty.call(i, t) && R(i[t])) return !0; return !1; } function et(i) { const e = [], t = i.data, s = i; return s.data = M(t, e), s.attachments = e.length, { packet: s, buffers: e }; } function M(i, e) { if (!i) return i; if (z(i)) { const t = { _placeholder: !0, num: e.length }; return e.push(i), t; } else if (Array.isArray(i)) { const t = new Array(i.length); for (let s = 0; s < i.length; s++) t[s] = M(i[s], e); return t; } else if (typeof i == "object" && !(i instanceof Date)) { const t = {}; for (const s in i) Object.prototype.hasOwnProperty.call(i, s) && (t[s] = M(i[s], e)); return t; } return i; } function tt(i, e) { return i.data = $(i.data, e), delete i.attachments, i; } function $(i, e) { if (!i) return i; if (i && i._placeholder === !0) { if (typeof i.num == "number" && i.num >= 0 && i.num < e.length) return e[i.num]; throw new Error("illegal attachments"); } else if (Array.isArray(i)) for (let t = 0; t < i.length; t++) i[t] = $(i[t], e); else if (typeof i == "object") for (const t in i) Object.prototype.hasOwnProperty.call(i, t) && (i[t] = $(i[t], e)); return i; } const st = [ "connect", "connect_error", "disconnect", "disconnecting", "newListener", "removeListener" // used by the Node.js EventEmitter ], it = 5; var l; (function(i) { i[i.CONNECT = 0] = "CONNECT", i[i.DISCONNECT = 1] = "DISCONNECT", i[i.EVENT = 2] = "EVENT", i[i.ACK = 3] = "ACK", i[i.CONNECT_ERROR = 4] = "CONNECT_ERROR", i[i.BINARY_EVENT = 5] = "BINARY_EVENT", i[i.BINARY_ACK = 6] = "BINARY_ACK"; })(l || (l = {})); class nt { /** * Encoder constructor * * @param {function} replacer - custom replacer to pass down to JSON.parse */ constructor(e) { this.replacer = e; } /** * Encode a packet as a single string if non-binary, or as a * buffer sequence, depending on packet type. * * @param {Object} obj - packet object */ encode(e) { return (e.type === l.EVENT || e.type === l.ACK) && R(e) ? this.encodeAsBinary({ type: e.type === l.EVENT ? l.BINARY_EVENT : l.BINARY_ACK, nsp: e.nsp, data: e.data, id: e.id }) : [this.encodeAsString(e)]; } /** * Encode packet as string. */ encodeAsString(e) { let t = "" + e.type; return (e.type === l.BINARY_EVENT || e.type === l.BINARY_ACK) && (t += e.attachments + "-"), e.nsp && e.nsp !== "/" && (t += e.nsp + ","), e.id != null && (t += e.id), e.data != null && (t += JSON.stringify(e.data, this.replacer)), t; } /** * Encode packet as 'buffer sequence' by removing blobs, and * deconstructing packet into object with placeholders and * a list of buffers. */ encodeAsBinary(e) { const t = et(e), s = this.encodeAsString(t.packet), n = t.buffers; return n.unshift(s), n; } } function ee(i) { return Object.prototype.toString.call(i) === "[object Object]"; } class Y extends f { /** * Decoder constructor * * @param {function} reviver - custom reviver to pass down to JSON.stringify */ constructor(e) { super(), this.reviver = e; } /** * Decodes an encoded packet string into packet JSON. * * @param {String} obj - encoded packet */ add(e) { let t; if (typeof e == "string") { if (this.reconstructor) throw new Error("got plaintext data when reconstructing a packet"); t = this.decodeString(e); const s = t.type === l.BINARY_EVENT; s || t.type === l.BINARY_ACK ? (t.type = s ? l.EVENT : l.ACK, this.reconstructor = new rt(t), t.attachments === 0 && super.emitReserved("decoded", t)) : super.emitReserved("decoded", t); } else if (z(e) || e.base64) if (this.reconstructor) t = this.reconstructor.takeBinaryData(e), t && (this.reconstructor = null, super.emitReserved("decoded", t)); else throw new Error("got binary data when not reconstructing a packet"); else throw new Error("Unknown type: " + e); } /** * Decode a packet String (JSON data) * * @param {String} str * @return {Object} packet */ decodeString(e) { let t = 0; const s = { type: Number(e.charAt(0)) }; if (l[s.type] === void 0) throw new Error("unknown packet type " + s.type); if (s.type === l.BINARY_EVENT || s.type === l.BINARY_ACK) { const r = t + 1; for (; e.charAt(++t) !== "-" && t != e.length; ) ; const o = e.substring(r, t); if (o != Number(o) || e.charAt(t) !== "-") throw new Error("Illegal attachments"); s.attachments = Number(o); } if (e.charAt(t + 1) === "/") { const r = t + 1; for (; ++t && !(e.charAt(t) === "," || t === e.length); ) ; s.nsp = e.substring(r, t); } else s.nsp = "/"; const n = e.charAt(t + 1); if (n !== "" && Number(n) == n) { const r = t + 1; for (; ++t; ) { const o = e.charAt(t); if (o == null || Number(o) != o) { --t; break; } if (t === e.length) break; } s.id = Number(e.substring(r, t + 1)); } if (e.charAt(++t)) { const r = this.tryParse(e.substr(t)); if (Y.isPayloadValid(s.type, r)) s.data = r; else throw new Error("invalid payload"); } return s; } tryParse(e) { try { return JSON.parse(e, this.reviver); } catch { return !1; } } static isPayloadValid(e, t) { switch (e) { case l.CONNECT: return ee(t); case l.DISCONNECT: return t === void 0; case l.CONNECT_ERROR: return typeof t == "string" || ee(t); case l.EVENT: case l.BINARY_EVENT: return Array.isArray(t) && (typeof t[0] == "number" || typeof t[0] == "string" && st.indexOf(t[0]) === -1); case l.ACK: case l.BINARY_ACK: return Array.isArray(t); } } /** * Deallocates a parser's resources */ destroy() { this.reconstructor && (this.reconstructor.finishedReconstruction(), this.reconstructor = null); } } class rt { constructor(e) { this.packet = e, this.buffers = [], this.reconPack = e; } /** * Method to be called when binary data received from connection * after a BINARY_EVENT packet. * * @param {Buffer | ArrayBuffer} binData - the raw binary data received * @return {null | Object} returns null if more binary data is expected or * a reconstructed packet object if all buffers have been received. */ takeBinaryData(e) { if (this.buffers.push(e), this.buffers.length === this.reconPack.attachments) { const t = tt(this.reconPack, this.buffers); return this.finishedReconstruction(), t; } return null; } /** * Cleans up binary packet reconstruction variables. */ finishedReconstruction() { this.reconPack = null, this.buffers = []; } } const ot = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, Decoder: Y, Encoder: nt, get PacketType() { return l; }, protocol: it }, Symbol.toStringTag, { value: "Module" })); function y(i, e, t) { return i.on(e, t), function() { i.off(e, t); }; } const at = Object.freeze({ connect: 1, connect_error: 1, disconnect: 1, disconnecting: 1, // EventEmitter reserved events: https://nodejs.org/api/events.html#events_event_newlistener newListener: 1, removeListener: 1 }); let pe = class extends f { /** * `Socket` constructor. */ constructor(e, t, s) { super(), this.connected = !1, this.recovered = !1, this.receiveBuffer = [], this.sendBuffer = [], this._queue = [], this._queueSeq = 0, this.ids = 0, this.acks = {}, this.flags = {}, this.io = e, this.nsp = t, s && s.auth && (this.auth = s.auth), this._opts = Object.assign({}, s), this.io._autoConnect && this.open(); } /** * Whether the socket is currently disconnected * * @example * const socket = io(); * * socket.on("connect", () => { * console.log(socket.disconnected); // false * }); * * socket.on("disconnect", () => { * console.log(socket.disconnected); // true * }); */ get disconnected() { return !this.connected;