UNPKG

@danidoble/webserial

Version:
1,594 lines 110 kB
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((n) => { S[m[n]] = n; }); const D = { type: "error", data: "parser error" }, te = typeof Blob == "function" || typeof Blob < "u" && Object.prototype.toString.call(Blob) === "[object BlobConstructor]", se = typeof ArrayBuffer == "function", ne = (n) => typeof ArrayBuffer.isView == "function" ? ArrayBuffer.isView(n) : n && n.buffer instanceof ArrayBuffer, H = ({ type: n, data: e }, t, s) => te && e instanceof Blob ? t ? s(e) : J(e, s) : se && (e instanceof ArrayBuffer || ne(e)) ? t ? s(e) : J(new Blob([e]), s) : s(m[n] + (e || "")), J = (n, e) => { const t = new FileReader(); return t.onload = function() { const s = t.result.split(",")[1]; e("b" + (s || "")); }, t.readAsDataURL(n); }; function Q(n) { return n instanceof Uint8Array ? n : n instanceof ArrayBuffer ? new Uint8Array(n) : new Uint8Array(n.buffer, n.byteOffset, n.byteLength); } let P; function de(n, e) { if (te && n.data instanceof Blob) return n.data.arrayBuffer().then(Q).then(e); if (se && (n.data instanceof ArrayBuffer || ne(n.data))) return e(Q(n.data)); H(n, !1, (t) => { P || (P = new TextEncoder()), e(P.encode(t)); }); } const X = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", k = typeof Uint8Array > "u" ? [] : new Uint8Array(256); for (let n = 0; n < X.length; n++) k[X.charCodeAt(n)] = n; const ye = (n) => { let e = n.length * 0.75, t = n.length, s, i = 0, r, o, l, c; n[n.length - 1] === "=" && (e--, n[n.length - 2] === "=" && e--); const f = new ArrayBuffer(e), u = new Uint8Array(f); for (s = 0; s < t; s += 4) r = k[n.charCodeAt(s)], o = k[n.charCodeAt(s + 1)], l = k[n.charCodeAt(s + 2)], c = k[n.charCodeAt(s + 3)], u[i++] = r << 2 | o >> 4, u[i++] = (o & 15) << 4 | l >> 2, u[i++] = (l & 3) << 6 | c & 63; return f; }, ge = typeof ArrayBuffer == "function", W = (n, e) => { if (typeof n != "string") return { type: "message", data: ie(n, e) }; const t = n.charAt(0); return t === "b" ? { type: "message", data: me(n.substring(1), e) } : S[t] ? n.length > 1 ? { type: S[t], data: n.substring(1) } : { type: S[t] } : D; }, me = (n, e) => { if (ge) { const t = ye(n); return ie(t, e); } else return { base64: !0, data: n }; }, ie = (n, e) => { switch (e) { case "blob": return n instanceof Blob ? n : new Blob([n]); case "arraybuffer": default: return n instanceof ArrayBuffer ? n : n.buffer; } }, re = "", be = (n, e) => { const t = n.length, s = new Array(t); let i = 0; n.forEach((r, o) => { H(r, !1, (l) => { s[o] = l, ++i === t && e(s.join(re)); }); }); }, we = (n, e) => { const t = n.split(re), s = []; for (let i = 0; i < t.length; i++) { const r = W(t[i], e); if (s.push(r), r.type === "error") break; } return s; }; function ve() { return new TransformStream({ transform(n, e) { de(n, (t) => { const s = t.length; let i; if (s < 126) i = new Uint8Array(1), new DataView(i.buffer).setUint8(0, s); else if (s < 65536) { i = new Uint8Array(3); const r = new DataView(i.buffer); r.setUint8(0, 126), r.setUint16(1, s); } else { i = new Uint8Array(9); const r = new DataView(i.buffer); r.setUint8(0, 127), r.setBigUint64(1, BigInt(s)); } n.data && typeof n.data != "string" && (i[0] |= 128), e.enqueue(i), e.enqueue(t); }); } }); } let N; function C(n) { return n.reduce((e, t) => e + t.length, 0); } function T(n, e) { if (n[0].length === e) return n.shift(); const t = new Uint8Array(e); let s = 0; for (let i = 0; i < e; i++) t[i] = n[0][s++], s === n[0].length && (n.shift(), s = 0); return n.length && s < n[0].length && (n[0] = n[0].slice(s)), t; } function Ee(n, e) { N || (N = new TextDecoder()); const t = []; let s = 0, i = -1, r = !1; return new TransformStream({ transform(o, l) { for (t.push(o); ; ) { if (s === 0) { if (C(t) < 1) break; const c = T(t, 1); r = (c[0] & 128) === 128, i = c[0] & 127, i < 126 ? s = 3 : i === 126 ? s = 1 : s = 2; } else if (s === 1) { if (C(t) < 2) break; const c = T(t, 2); i = new DataView(c.buffer, c.byteOffset, c.length).getUint16(0), s = 3; } else if (s === 2) { if (C(t) < 8) break; const c = T(t, 8), f = new DataView(c.buffer, c.byteOffset, c.length), u = f.getUint32(0); if (u > Math.pow(2, 21) - 1) { l.enqueue(D); break; } i = u * Math.pow(2, 32) + f.getUint32(4), s = 3; } else { if (C(t) < i) break; const c = T(t, i); l.enqueue(W(r ? c : N.decode(c), e)), s = 0; } if (i === 0 || i > n) { l.enqueue(D); break; } } } }); } const oe = 4; function _(n) { if (n) return ke(n); } function ke(n) { for (var e in _.prototype) n[e] = _.prototype[e]; return n; } _.prototype.on = _.prototype.addEventListener = function(n, e) { return this._callbacks = this._callbacks || {}, (this._callbacks["$" + n] = this._callbacks["$" + n] || []).push(e), this; }; _.prototype.once = function(n, e) { function t() { this.off(n, t), e.apply(this, arguments); } return t.fn = e, this.on(n, t), this; }; _.prototype.off = _.prototype.removeListener = _.prototype.removeAllListeners = _.prototype.removeEventListener = function(n, e) { if (this._callbacks = this._callbacks || {}, arguments.length == 0) return this._callbacks = {}, this; var t = this._callbacks["$" + n]; if (!t) return this; if (arguments.length == 1) return delete this._callbacks["$" + n], this; for (var s, i = 0; i < t.length; i++) if (s = t[i], s === e || s.fn === e) { t.splice(i, 1); break; } return t.length === 0 && delete this._callbacks["$" + n], this; }; _.prototype.emit = function(n) { this._callbacks = this._callbacks || {}; for (var e = new Array(arguments.length - 1), t = this._callbacks["$" + n], s = 1; s < arguments.length; s++) e[s - 1] = arguments[s]; if (t) { t = t.slice(0); for (var s = 0, i = t.length; s < i; ++s) t[s].apply(this, e); } return this; }; _.prototype.emitReserved = _.prototype.emit; _.prototype.listeners = function(n) { return this._callbacks = this._callbacks || {}, this._callbacks["$" + n] || []; }; _.prototype.hasListeners = function(n) { return !!this.listeners(n).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 ae(n, ...e) { return e.reduce((t, s) => (n.hasOwnProperty(s) && (t[s] = n[s]), t), {}); } const Te = d.setTimeout, Ae = d.clearTimeout; function L(n, e) { e.useNativeTimers ? (n.setTimeoutFn = Te.bind(d), n.clearTimeoutFn = Ae.bind(d)) : (n.setTimeoutFn = d.setTimeout.bind(d), n.clearTimeoutFn = d.clearTimeout.bind(d)); } const Se = 1.33; function xe(n) { return typeof n == "string" ? Re(n) : Math.ceil((n.byteLength || n.size) * Se); } function Re(n) { let e = 0, t = 0; for (let s = 0, i = n.length; s < i; s++) e = n.charCodeAt(s), e < 128 ? t += 1 : e < 2048 ? t += 2 : e < 55296 || e >= 57344 ? t += 3 : (s++, t += 4); return t; } function ce() { return Date.now().toString(36).substring(3) + Math.random().toString(36).substring(2, 5); } function Be(n) { let e = ""; for (let t in n) n.hasOwnProperty(t) && (e.length && (e += "&"), e += encodeURIComponent(t) + "=" + encodeURIComponent(n[t])); return e; } function Oe(n) { let e = {}, t = n.split("&"); for (let s = 0, i = t.length; s < i; 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 _ { /** * 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] = ce()), !this.supportsBinary && !t.sid && (t.b64 = 1), this.createUri(e, t); } } let le = !1; try { le = typeof XMLHttpRequest < "u" && "withCredentials" in new XMLHttpRequest(); } catch { } const Ne = le; 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", (i, r) => { this.onError("xhr post error", i, 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 _ { /** * 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 = ae(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 i in this._opts.extraHeaders) this._opts.extraHeaders.hasOwnProperty(i) && s.setRequestHeader(i, this._opts.extraHeaders[i]); } } 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 i; s.readyState === 3 && ((i = this._opts.cookieJar) === null || i === void 0 || i.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 (i) { this.setTimeoutFn(() => { this._onError(i); }, 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", j); else if (typeof addEventListener == "function") { const n = "onpagehide" in d ? "pagehide" : "unload"; addEventListener(n, j, !1); } } function j() { for (let n in g.requests) g.requests.hasOwnProperty(n) && g.requests[n].abort(); } const De = function() { const n = he({ xdomain: !1 }); return n && n.responseType !== null; }(); class Ue extends qe { constructor(e) { super(e); const t = e && e.forceBase64; this.supportsBinary = De && !t; } request(e = {}) { return Object.assign(e, { xd: this.xd }, this.opts), new g(he, this.uri(), e); } } function he(n) { const e = n.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 ue = typeof navigator < "u" && typeof navigator.product == "string" && navigator.product.toLowerCase() === "reactnative"; class Me extends K { get name() { return "websocket"; } doOpen() { const e = this.uri(), t = this.opts.protocols, s = ue ? {} : ae(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 (i) { return this.emitReserved("error", i); } 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], i = t === e.length - 1; H(s, this.supportsBinary, (r) => { try { this.doWrite(s, r); } catch { } i && 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] = ce()), this.supportsBinary || (t.b64 = 1), this.createUri(e, t); } } const I = d.WebSocket || d.MozWebSocket; class Fe extends Me { createSocket(e, t, s) { return ue ? 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(), i = ve(); i.readable.pipeTo(e.writable), this._writer = i.writable.getWriter(); const r = () => { s.read().then(({ done: l, value: c }) => { l || (this.onPacket(c), r()); }).catch((l) => { }); }; 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], i = t === e.length - 1; this._writer.write(s).then(() => { i && O(() => { this.writable = !0, this.emitReserved("drain"); }, this.setTimeoutFn); }); } } doClose() { var e; (e = this._transport) === null || e === void 0 || e.close(); } } const Ve = { websocket: Fe, webtransport: $e, polling: Ue }, 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 U(n) { if (n.length > 8e3) throw "URI too long"; const e = n, t = n.indexOf("["), s = n.indexOf("]"); t != -1 && s != -1 && (n = n.substring(0, t) + n.substring(t, s).replace(/:/g, ";") + n.substring(s, n.length)); let i = He.exec(n || ""), r = {}, o = 14; for (; o--; ) r[We[o]] = i[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(n, 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(n, e) { const t = {}; return e.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function(s, i, r) { i && (t[i] = r); }), t; } const M = typeof addEventListener == "function" && typeof removeEventListener == "function", x = []; M && addEventListener("offline", () => { x.forEach((n) => n()); }, !1); class b extends _ { /** * 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 = U(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 = U(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 i = s.prototype.name; this.transports.push(i), this._transportsByName[i] = 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)), M && (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 = oe, 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 && b.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", b.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 i = this.writeBuffer[s].data; if (i && (t += xe(i)), 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, i) { if (typeof t == "function" && (i = t, t = void 0), typeof s == "function" && (i = 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), i && this.once("flush", i), 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 (b.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(), M && (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; } } } b.protocol = oe; class Ye extends b { 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; b.priorWebsocketSuccess = !1; const i = () => { 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; b.priorWebsocketSuccess = t.name === "websocket", this.transport.pause(() => { s || this.readyState !== "closed" && (u(), this.setTransport(t), t.send([{ type: "upgrade" }]), this.emitReserved("upgrade", t), t = null, this.upgrading = !1, this.flush()); }); } else { const v = new Error("probe error"); v.transport = t.name, this.emitReserved("upgradeError", v); } })); }; function r() { s || (s = !0, u(), t.close(), t = null); } const o = (p) => { const v = new Error("probe error: " + p); v.transport = t.name, r(), this.emitReserved("upgradeError", v); }; function l() { o("transport closed"); } function c() { o("socket closed"); } function f(p) { t && p.name !== t.name && r(); } const u = () => { t.removeListener("open", i), t.removeListener("error", o), t.removeListener("close", l), this.off("close", c), this.off("upgrading", f); }; t.once("open", i), t.once("error", o), t.once("close", l), this.once("close", c), this.once("upgrading", f), 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((i) => Ve[i]).filter((i) => !!i)), super(e, s); } }; function Qe(n, e = "", t) { let s = n; t = t || typeof location < "u" && location, n == null && (n = t.protocol + "//" + t.host), typeof n == "string" && (n.charAt(0) === "/" && (n.charAt(1) === "/" ? n = t.protocol + n : n = t.host + n), /^(https?|wss?):\/\//.test(n) || (typeof t < "u" ? n = t.protocol + "//" + n : n = "https://" + n), s = U(n)), 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 = (n) => typeof ArrayBuffer.isView == "function" ? ArrayBuffer.isView(n) : n.buffer instanceof ArrayBuffer, _e = Object.prototype.toString, Ge = typeof Blob == "function" || typeof Blob < "u" && _e.call(Blob) === "[object BlobConstructor]", Ze = typeof File == "function" || typeof File < "u" && _e.call(File) === "[object FileConstructor]"; function z(n) { return Xe && (n instanceof ArrayBuffer || je(n)) || Ge && n instanceof Blob || Ze && n instanceof File; } function R(n, e) { if (!n || typeof n != "object") return !1; if (Array.isArray(n)) { for (let t = 0, s = n.length; t < s; t++) if (R(n[t])) return !0; return !1; } if (z(n)) return !0; if (n.toJSON && typeof n.toJSON == "function" && arguments.length === 1) return R(n.toJSON(), !0); for (const t in n) if (Object.prototype.hasOwnProperty.call(n, t) && R(n[t])) return !0; return !1; } function et(n) { const e = [], t = n.data, s = n; return s.data = F(t, e), s.attachments = e.length, { packet: s, buffers: e }; } function F(n, e) { if (!n) return n; if (z(n)) { const t = { _placeholder: !0, num: e.length }; return e.push(n), t; } else if (Array.isArray(n)) { const t = new Array(n.length); for (let s = 0; s < n.length; s++) t[s] = F(n[s], e); return t; } else if (typeof n == "object" && !(n instanceof Date)) { const t = {}; for (const s in n) Object.prototype.hasOwnProperty.call(n, s) && (t[s] = F(n[s], e)); return t; } return n; } function tt(n, e) { return n.data = $(n.data, e), delete n.attachments, n; } function $(n, e) { if (!n) return n; if (n && n._placeholder === !0) { if (typeof n.num == "number" && n.num >= 0 && n.num < e.length) return e[n.num]; throw new Error("illegal attachments"); } else if (Array.isArray(n)) for (let t = 0; t < n.length; t++) n[t] = $(n[t], e); else if (typeof n == "object") for (const t in n) Object.prototype.hasOwnProperty.call(n, t) && (n[t] = $(n[t], e)); return n; } const st = [ "connect", "connect_error", "disconnect", "disconnecting", "newListener", "removeListener" // used by the Node.js EventEmitter ], nt = 5; var h; (function(n) { n[n.CONNECT = 0] = "CONNECT", n[n.DISCONNECT = 1] = "DISCONNECT", n[n.EVENT = 2] = "EVENT", n[n.ACK = 3] = "ACK", n[n.CONNECT_ERROR = 4] = "CONNECT_ERROR", n[n.BINARY_EVENT = 5] = "BINARY_EVENT", n[n.BINARY_ACK = 6] = "BINARY_ACK"; })(h || (h = {})); class it { /** * 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 === h.EVENT || e.type === h.ACK) && R(e) ? this.encodeAsBinary({ type: e.type === h.EVENT ? h.BINARY_EVENT : h.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 === h.BINARY_EVENT || e.type === h.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), i = t.buffers; return i.unshift(s), i; } } function G(n) { return Object.prototype.toString.call(n) === "[object Object]"; } class Y extends _ { /** * 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 === h.BINARY_EVENT; s || t.type === h.BINARY_ACK ? (t.type = s ? h.EVENT : h.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 (h[s.type] === void 0) throw new Error("unknown packet type " + s.type); if (s.type === h.BINARY_EVENT || s.type === h.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 i = e.charAt(t + 1); if (i !== "" && Number(i) == i) { 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 h.CONNECT: return G(t); case h.DISCONNECT: return t === void 0; case h.CONNECT_ERROR: return typeof t == "string" || G(t); case h.EVENT: case h.BINARY_EVENT: return Array.isArray(t) && (typeof t[0] == "number" || typeof t[0] == "string" && st.indexOf(t[0]) === -1); case h.ACK: case h.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: it, get PacketType() { return h; }, protocol: nt }, Symbol.toStringTag, { value: "Module" })); function y(n, e, t) { return n.on(e, t), function() { n.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 }); class fe extends _ { /** * `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; } /** * Subscribe to open, close and packet events * * @private */ subEvents() { if (this.subs) return; const e = this.io; this.subs = [ y(e, "open", this.onopen.bind(this)), y(e, "packet", this.onpacket.bind(this)), y(e, "error", this.onerror.bind(this)), y(e, "close", this.onclose.bind(this)) ]; } /** * Whether the Socket will try to reconnect when its Manager connects or reconnects. * * @example * const socket = io(); * * console.log(socket.active); // true * * socket.on("disconnect", (reason) => { * if (reason === "io server disconnect") { * // the disconnection was initiated by the server, you need to manually reconnect * console.log(socket.active); // false * } * // else the socket will automatically try to reconnect * console.log(socket.active); // true * }); */ get active() { return !!this.subs; } /** * "Opens" the socket. * * @example * const socket = io({ * autoConnect: false * }); * * socket.connect(); */ connect() { return this.connected ? this : (this.subEvents(), this.io._reconnecting || this.io.open(), this.io._readyState === "open" && this.onopen(), this); } /** * Alias for {@link connect()}. */ open() { return this.connect(); } /** * Sends a `message` event. * * This method mimics the WebSocket.send() method. * * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send * * @example * socket.send("hello"); * * // this is equivalent to * socket.emit("message", "hello"); * * @return self */ send(...e) { return e.unshift("message"), this.emit.apply(this, e), this; } /** * Override `emit`. * If the event is in `events`, it's emitted normally. * * @example * socket.emit("hello", "world"); * * // all serializable datastructures are supported (no need to call JSON.stringify) * socket.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) }); * * // with an acknowledgement from the server * socket.emit("hello", "world", (val) => { * // ... * }); * * @return self */ emit(e, ...t) { var s, i, r; if (at.hasOwnProperty(e)) throw new Error('"' + e.toString() + '" is a reserved event name'); if (t.unshift(e), this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) return this._addToQueue(t), this; const o = { type: h.EVENT, data: t }; if (o.options = {}, o.options.compress = this.flags.compress !== !1, typeof t[t.length - 1] == "function") { const u = this.ids++, p = t.pop(); this._registerAckCallback(u, p), o.id = u; } const l = (i = (s = this.io.engine) === null || s === void 0 ? void 0 : s.transport) === null || i === void 0 ? void 0 : i.writable, c = this.connected && !(!((r = this.io.engine) === null || r === void 0) && r._hasPingExpired()); return this.flags.volatile && !l || (c ? (this.notifyOutgoingListeners(o), this.packet(o)) : this.sendBuffer.push(o)), this.flags = {}, this; } /** * @private */ _registerAckCallback(e, t) { var s; const i = (s = this.flags.timeout) !== null && s !== void 0 ? s : this._opts.ackTimeout; if (i === void 0) { this.acks[e] = t; return; } const r = this.io.setTimeoutFn(() => { delete this.acks[e]; for (let l = 0; l < this.sendBuffer.length; l++) this.sendBuffer[l].id === e && this.sendBuffer.splice(l, 1); t.call(this, new Error("operation has timed out")); }, i), o = (...l) => { this.io.clearTimeoutFn(r), t.apply(this, l); }; o.withError = !0, this.acks[e] = o; } /** * Emits an event and waits for an acknowledgement * * @example * // without timeout * const response = await socket.emitWithAck("hello", "world"); * * // with a specific timeout * try { * const response = await socket.timeout(1000).emitWithAck("hello", "world"); * } catch (err) { * // the server did not acknowledge the event in the given delay * } * * @return a Promise that will be fulfilled when the server acknowledges the event */ emitWithAck(e, ...t) { return new