herdr-remote 0.3.33 → 0.3.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +4 -0
  2. package/README.zh-CN.md +2 -0
  3. package/dist/chunks/{M52LJEES.js → 37NKZLLR.js} +1 -1
  4. package/dist/chunks/{DGUZCGQN.js → 5RGV2MW6.js} +1 -1
  5. package/dist/chunks/{AX4EPJCP.js → 6EGSSNV7.js} +1 -1
  6. package/dist/chunks/{FONUO5O5.js → 6H6NEYX7.js} +1 -1
  7. package/dist/chunks/{MEFDV375.js → 6Z6GROTK.js} +1 -1
  8. package/dist/chunks/{LY2ZGCXN.js → AQY5SQIR.js} +1 -1
  9. package/dist/chunks/BBRYDVMP.js +9 -0
  10. package/dist/chunks/{KGOQKOHH.js → CIIAHGYH.js} +2 -2
  11. package/dist/chunks/CLKCCQKG.js +3 -0
  12. package/dist/chunks/{WY7WHEJ4.js → CUXGXJMW.js} +1 -1
  13. package/dist/chunks/{B76DFI4H.js → CXEZYDSV.js} +1 -1
  14. package/dist/chunks/ENJULI6H.js +6 -0
  15. package/dist/chunks/{H24ZP5D5.js → IONXNA5T.js} +1 -1
  16. package/dist/chunks/{44IGVPMA.js → JBZYXV5K.js} +1 -1
  17. package/dist/chunks/{CVJ4HBMP.js → NMQNEH6L.js} +1 -1
  18. package/dist/chunks/OVCCY2BQ.js +3 -0
  19. package/dist/chunks/QLOMG2U7.js +3 -0
  20. package/dist/chunks/{42KARAL4.js → QOPTXTL7.js} +6 -6
  21. package/dist/chunks/{K5RFPHSF.js → RNFSFKGM.js} +1 -1
  22. package/dist/chunks/{LPR662JH.js → RSLAVKFI.js} +2 -2
  23. package/dist/chunks/{MKAEXKXG.js → S2CKUJLV.js} +1 -1
  24. package/dist/chunks/{O2LNVFUT.js → S4TW5MHM.js} +1 -1
  25. package/dist/chunks/{RMHH3IAX.js → SJIUJN5L.js} +1 -1
  26. package/dist/chunks/SWVUDSHP.js +3 -0
  27. package/dist/chunks/{MCUVFSSK.js → TARBQM5W.js} +1 -1
  28. package/dist/chunks/{VD54DF7R.js → U4MT2N6T.js} +1 -1
  29. package/dist/chunks/{PBRQ3HEG.js → ZAAEQP3M.js} +1 -1
  30. package/dist/chunks/{QCSILMFB.js → ZBDFFRB5.js} +1 -1
  31. package/dist/cli.js +13 -13
  32. package/dist/connector/admin-broker.js +1 -1
  33. package/dist/connector/main.js +14 -14
  34. package/herdr-plugin.toml +2 -2
  35. package/node_modules/herdr-remote-relay/bin/herdr-remote-relay.js +11 -11
  36. package/node_modules/herdr-remote-relay/package.json +1 -1
  37. package/node_modules/herdr-remote-relay/web/dist/assets/index-DMbkU5R6.js +61 -0
  38. package/node_modules/herdr-remote-relay/web/dist/index.html +1 -1
  39. package/package.json +2 -2
  40. package/dist/chunks/3FQAXVGC.js +0 -3
  41. package/dist/chunks/5LZFJ6UZ.js +0 -3
  42. package/dist/chunks/BYGDPZZD.js +0 -3
  43. package/dist/chunks/PBMBFWLQ.js +0 -3
  44. package/node_modules/herdr-remote-relay/web/dist/assets/index-DfycvWFA.js +0 -61
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __herdrCreateRequire } from 'node:module';
3
3
  const require = __herdrCreateRequire(import.meta.url);
4
- var an=Object.create;var is=Object.defineProperty;var ln=Object.getOwnPropertyDescriptor;var cn=Object.getOwnPropertyNames;var fn=Object.getPrototypeOf,un=Object.prototype.hasOwnProperty;var S=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,s)=>(typeof require<"u"?require:e)[s]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var v=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var dn=(t,e,s,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of cn(e))!un.call(t,n)&&n!==s&&is(t,n,{get:()=>e[n],enumerable:!(r=ln(e,n))||r.enumerable});return t};var G=(t,e,s)=>(s=t!=null?an(fn(t)):{},dn(e||!t||!t.__esModule?is(s,"default",{value:t,enumerable:!0}):s,t));var F=v((sa,cs)=>{"use strict";var as=["nodebuffer","arraybuffer","fragments"],ls=typeof Blob<"u";ls&&as.push("blob");cs.exports={BINARY_TYPES:as,CLOSE_TIMEOUT:3e4,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:ls,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}});var Ae=v((ra,Ue)=>{"use strict";var{EMPTY_BUFFER:Tn}=F(),pt=Buffer[Symbol.species];function wn(t,e){if(t.length===0)return Tn;if(t.length===1)return t[0];let s=Buffer.allocUnsafe(e),r=0;for(let n=0;n<t.length;n++){let i=t[n];s.set(i,r),r+=i.length}return r<e?new pt(s.buffer,s.byteOffset,r):s}function fs(t,e,s,r,n){for(let i=0;i<n;i++)s[r+i]=t[i]^e[i&3]}function us(t,e){for(let s=0;s<t.length;s++)t[s]^=e[s&3]}function An(t){return t.length===t.buffer.byteLength?t.buffer:t.buffer.slice(t.byteOffset,t.byteOffset+t.length)}function _t(t){if(_t.readOnly=!0,Buffer.isBuffer(t))return t;let e;return t instanceof ArrayBuffer?e=new pt(t):ArrayBuffer.isView(t)?e=new pt(t.buffer,t.byteOffset,t.byteLength):(e=Buffer.from(t),_t.readOnly=!1),e}Ue.exports={concat:wn,mask:fs,toArrayBuffer:An,toBuffer:_t,unmask:us};if(!process.env.WS_NO_BUFFER_UTIL)try{let t=S("bufferutil");Ue.exports.mask=function(e,s,r,n,i){i<48?fs(e,s,r,n,i):t.mask(e,s,r,n,i)},Ue.exports.unmask=function(e,s){e.length<32?us(e,s):t.unmask(e,s)}}catch{}});var ms=v((na,hs)=>{"use strict";var ds=Symbol("kDone"),yt=Symbol("kRun"),gt=class{constructor(e){this[ds]=()=>{this.pending--,this[yt]()},this.concurrency=e||1/0,this.jobs=[],this.pending=0}add(e){this.jobs.push(e),this[yt]()}[yt](){if(this.pending!==this.concurrency&&this.jobs.length){let e=this.jobs.shift();this.pending++,e(this[ds])}}};hs.exports=gt});var fe=v((ia,gs)=>{"use strict";var ve=S("zlib"),ps=Ae(),vn=ms(),{kStatusCode:_s}=F(),In=Buffer[Symbol.species],On=Buffer.from([0,0,255,255]),He=Symbol("permessage-deflate"),H=Symbol("total-length"),le=Symbol("callback"),j=Symbol("buffers"),ce=Symbol("error"),Fe,St=class{constructor(e){if(this._options=e||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._maxPayload=this._options.maxPayload|0,this._isServer=!!this._options.isServer,this._deflate=null,this._inflate=null,this.params=null,!Fe){let s=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;Fe=new vn(s)}}static get extensionName(){return"permessage-deflate"}offer(){let e={};return this._options.serverNoContextTakeover&&(e.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(e.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(e.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?e.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(e.client_max_window_bits=!0),e}accept(e){return e=this.normalizeParams(e),this.params=this._isServer?this.acceptAsServer(e):this.acceptAsClient(e),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let e=this._deflate[le];this._deflate.close(),this._deflate=null,e&&e(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(e){let s=this._options,r=e.find(n=>!(s.serverNoContextTakeover===!1&&n.server_no_context_takeover||n.server_max_window_bits&&(s.serverMaxWindowBits===!1||typeof s.serverMaxWindowBits=="number"&&s.serverMaxWindowBits>n.server_max_window_bits)||typeof s.clientMaxWindowBits=="number"&&(typeof n.client_max_window_bits=="number"?s.clientMaxWindowBits>n.client_max_window_bits:!n.client_max_window_bits)));if(!r)throw new Error("None of the extension offers can be accepted");return s.serverNoContextTakeover&&(r.server_no_context_takeover=!0),s.clientNoContextTakeover&&(r.client_no_context_takeover=!0),typeof s.serverMaxWindowBits=="number"&&(r.server_max_window_bits=s.serverMaxWindowBits),typeof s.clientMaxWindowBits=="number"?r.client_max_window_bits=s.clientMaxWindowBits:(r.client_max_window_bits===!0||s.clientMaxWindowBits===!1)&&delete r.client_max_window_bits,r}acceptAsClient(e){let s=e[0];if(this._options.clientNoContextTakeover===!1&&s.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!s.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(s.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&s.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return s}normalizeParams(e){return e.forEach(s=>{Object.keys(s).forEach(r=>{let n=s[r];if(n.length>1)throw new Error(`Parameter "${r}" must have only a single value`);if(n=n[0],r==="client_max_window_bits"){if(n!==!0){let i=+n;if(!Number.isInteger(i)||i<8||i>15)throw new TypeError(`Invalid value for parameter "${r}": ${n}`);n=i}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${r}": ${n}`)}else if(r==="server_max_window_bits"){let i=+n;if(!Number.isInteger(i)||i<8||i>15)throw new TypeError(`Invalid value for parameter "${r}": ${n}`);n=i}else if(r==="client_no_context_takeover"||r==="server_no_context_takeover"){if(n!==!0)throw new TypeError(`Invalid value for parameter "${r}": ${n}`)}else throw new Error(`Unknown parameter "${r}"`);s[r]=n})}),e}decompress(e,s,r){Fe.add(n=>{this._decompress(e,s,(i,o)=>{n(),r(i,o)})})}compress(e,s,r){Fe.add(n=>{this._compress(e,s,(i,o)=>{n(),r(i,o)})})}_decompress(e,s,r){let n=this._isServer?"client":"server";if(!this._inflate){let i=`${n}_max_window_bits`,o=typeof this.params[i]!="number"?ve.Z_DEFAULT_WINDOWBITS:this.params[i];this._inflate=ve.createInflateRaw({...this._options.zlibInflateOptions,windowBits:o}),this._inflate[He]=this,this._inflate[H]=0,this._inflate[j]=[],this._inflate.on("error",Pn),this._inflate.on("data",ys)}this._inflate[le]=r,this._inflate.write(e),s&&this._inflate.write(On),this._inflate.flush(()=>{let i=this._inflate[ce];if(i){this._inflate.close(),this._inflate=null,r(i);return}let o=ps.concat(this._inflate[j],this._inflate[H]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[H]=0,this._inflate[j]=[],s&&this.params[`${n}_no_context_takeover`]&&this._inflate.reset()),r(null,o)})}_compress(e,s,r){let n=this._isServer?"server":"client";if(!this._deflate){let i=`${n}_max_window_bits`,o=typeof this.params[i]!="number"?ve.Z_DEFAULT_WINDOWBITS:this.params[i];this._deflate=ve.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:o}),this._deflate[H]=0,this._deflate[j]=[],this._deflate.on("data",Cn)}this._deflate[le]=r,this._deflate.write(e),this._deflate.flush(ve.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let i=ps.concat(this._deflate[j],this._deflate[H]);s&&(i=new In(i.buffer,i.byteOffset,i.length-4)),this._deflate[le]=null,this._deflate[H]=0,this._deflate[j]=[],s&&this.params[`${n}_no_context_takeover`]&&this._deflate.reset(),r(null,i)})}};gs.exports=St;function Cn(t){this[j].push(t),this[H]+=t.length}function ys(t){if(this[H]+=t.length,this[He]._maxPayload<1||this[H]<=this[He]._maxPayload){this[j].push(t);return}this[ce]=new RangeError("Max payload size exceeded"),this[ce].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[ce][_s]=1009,this.removeListener("data",ys),this.reset()}function Pn(t){if(this[He]._inflate=null,this[ce]){this[le](this[ce]);return}t[_s]=1007,this[le](t)}});var ue=v((oa,Ye)=>{"use strict";var{isUtf8:Ss}=S("buffer"),{hasBlob:Rn}=F(),kn=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function Ln(t){return t>=1e3&&t<=1014&&t!==1004&&t!==1005&&t!==1006||t>=3e3&&t<=4999}function xt(t){let e=t.length,s=0;for(;s<e;)if((t[s]&128)===0)s++;else if((t[s]&224)===192){if(s+1===e||(t[s+1]&192)!==128||(t[s]&254)===192)return!1;s+=2}else if((t[s]&240)===224){if(s+2>=e||(t[s+1]&192)!==128||(t[s+2]&192)!==128||t[s]===224&&(t[s+1]&224)===128||t[s]===237&&(t[s+1]&224)===160)return!1;s+=3}else if((t[s]&248)===240){if(s+3>=e||(t[s+1]&192)!==128||(t[s+2]&192)!==128||(t[s+3]&192)!==128||t[s]===240&&(t[s+1]&240)===128||t[s]===244&&t[s+1]>143||t[s]>244)return!1;s+=4}else return!1;return!0}function Nn(t){return Rn&&typeof t=="object"&&typeof t.arrayBuffer=="function"&&typeof t.type=="string"&&typeof t.stream=="function"&&(t[Symbol.toStringTag]==="Blob"||t[Symbol.toStringTag]==="File")}Ye.exports={isBlob:Nn,isValidStatusCode:Ln,isValidUTF8:xt,tokenChars:kn};if(Ss)Ye.exports.isValidUTF8=function(t){return t.length<24?xt(t):Ss(t)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let t=S("utf-8-validate");Ye.exports.isValidUTF8=function(e){return e.length<32?xt(e):t(e)}}catch{}});var At=v((aa,vs)=>{"use strict";var{Writable:Mn}=S("stream"),xs=fe(),{BINARY_TYPES:Dn,EMPTY_BUFFER:Es,kStatusCode:Bn,kWebSocket:Un}=F(),{concat:Et,toArrayBuffer:Fn,unmask:Hn}=Ae(),{isValidStatusCode:Yn,isValidUTF8:bs}=ue(),$e=Buffer[Symbol.species],P=0,Ts=1,ws=2,As=3,bt=4,Tt=5,We=6,wt=class extends Mn{constructor(e={}){super(),this._allowSynchronousEvents=e.allowSynchronousEvents!==void 0?e.allowSynchronousEvents:!0,this._binaryType=e.binaryType||Dn[0],this._extensions=e.extensions||{},this._isServer=!!e.isServer,this._maxBufferedChunks=e.maxBufferedChunks|0,this._maxFragments=e.maxFragments|0,this._maxPayload=e.maxPayload|0,this._skipUTF8Validation=!!e.skipUTF8Validation,this[Un]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._numFragments=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=P}_write(e,s,r){if(this._opcode===8&&this._state==P)return r();if(this._maxBufferedChunks>0&&this._buffers.length>=this._maxBufferedChunks){r(this.createError(RangeError,"Too many buffered chunks",!1,1008,"WS_ERR_TOO_MANY_BUFFERED_PARTS"));return}this._bufferedBytes+=e.length,this._buffers.push(e),this.startLoop(r)}consume(e){if(this._bufferedBytes-=e,e===this._buffers[0].length)return this._buffers.shift();if(e<this._buffers[0].length){let r=this._buffers[0];return this._buffers[0]=new $e(r.buffer,r.byteOffset+e,r.length-e),new $e(r.buffer,r.byteOffset,e)}let s=Buffer.allocUnsafe(e);do{let r=this._buffers[0],n=s.length-e;e>=r.length?s.set(this._buffers.shift(),n):(s.set(new Uint8Array(r.buffer,r.byteOffset,e),n),this._buffers[0]=new $e(r.buffer,r.byteOffset+e,r.length-e)),e-=r.length}while(e>0);return s}startLoop(e){this._loop=!0;do switch(this._state){case P:this.getInfo(e);break;case Ts:this.getPayloadLength16(e);break;case ws:this.getPayloadLength64(e);break;case As:this.getMask();break;case bt:this.getData(e);break;case Tt:case We:this._loop=!1;return}while(this._loop);this._errored||e()}getInfo(e){if(this._bufferedBytes<2){this._loop=!1;return}let s=this.consume(2);if((s[0]&48)!==0){let n=this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3");e(n);return}let r=(s[0]&64)===64;if(r&&!this._extensions[xs.extensionName]){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(n);return}if(this._fin=(s[0]&128)===128,this._opcode=s[0]&15,this._payloadLength=s[1]&127,this._opcode===0){if(r){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(n);return}if(!this._fragmented){let n=this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE");e(n);return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(n);return}this._compressed=r}else if(this._opcode>7&&this._opcode<11){if(!this._fin){let n=this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN");e(n);return}if(r){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(n);return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){let n=this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH");e(n);return}}else{let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(n);return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(s[1]&128)===128,this._isServer){if(!this._masked){let n=this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK");e(n);return}}else if(this._masked){let n=this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK");e(n);return}this._payloadLength===126?this._state=Ts:this._payloadLength===127?this._state=ws:this.haveLength(e)}getPayloadLength16(e){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(e)}getPayloadLength64(e){if(this._bufferedBytes<8){this._loop=!1;return}let s=this.consume(8),r=s.readUInt32BE(0);if(r>Math.pow(2,21)-1){let n=this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH");e(n);return}this._payloadLength=r*Math.pow(2,32)+s.readUInt32BE(4),this.haveLength(e)}haveLength(e){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){let s=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");e(s);return}this._masked?this._state=As:this._state=bt}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=bt}getData(e){let s=Es;if(this._payloadLength){if(this._bufferedBytes<this._payloadLength){this._loop=!1;return}s=this.consume(this._payloadLength),this._masked&&(this._mask[0]|this._mask[1]|this._mask[2]|this._mask[3])!==0&&Hn(s,this._mask)}if(this._opcode>7){this.controlMessage(s,e);return}if(this._maxFragments>0&&++this._numFragments>this._maxFragments){let r=this.createError(RangeError,"Too many message fragments",!1,1008,"WS_ERR_TOO_MANY_BUFFERED_PARTS");e(r);return}if(this._compressed){this._state=Tt,this.decompress(s,e);return}s.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(s)),this.dataMessage(e)}decompress(e,s){this._extensions[xs.extensionName].decompress(e,this._fin,(n,i)=>{if(n)return s(n);if(i.length){if(this._messageLength+=i.length,this._messageLength>this._maxPayload&&this._maxPayload>0){let o=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");s(o);return}this._fragments.push(i)}this.dataMessage(s),this._state===P&&this.startLoop(s)})}dataMessage(e){if(!this._fin){this._state=P;return}let s=this._messageLength,r=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._numFragments=0,this._fragments=[],this._opcode===2){let n;this._binaryType==="nodebuffer"?n=Et(r,s):this._binaryType==="arraybuffer"?n=Fn(Et(r,s)):this._binaryType==="blob"?n=new Blob(r):n=r,this._allowSynchronousEvents?(this.emit("message",n,!0),this._state=P):(this._state=We,setImmediate(()=>{this.emit("message",n,!0),this._state=P,this.startLoop(e)}))}else{let n=Et(r,s);if(!this._skipUTF8Validation&&!bs(n)){let i=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");e(i);return}this._state===Tt||this._allowSynchronousEvents?(this.emit("message",n,!1),this._state=P):(this._state=We,setImmediate(()=>{this.emit("message",n,!1),this._state=P,this.startLoop(e)}))}}controlMessage(e,s){if(this._opcode===8){if(e.length===0)this._loop=!1,this.emit("conclude",1005,Es),this.end();else{let r=e.readUInt16BE(0);if(!Yn(r)){let i=this.createError(RangeError,`invalid status code ${r}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");s(i);return}let n=new $e(e.buffer,e.byteOffset+2,e.length-2);if(!this._skipUTF8Validation&&!bs(n)){let i=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");s(i);return}this._loop=!1,this.emit("conclude",r,n),this.end()}this._state=P;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?"ping":"pong",e),this._state=P):(this._state=We,setImmediate(()=>{this.emit(this._opcode===9?"ping":"pong",e),this._state=P,this.startLoop(s)}))}createError(e,s,r,n,i){this._loop=!1,this._errored=!0;let o=new e(r?`Invalid WebSocket frame: ${s}`:s);return Error.captureStackTrace(o,this.createError),o.code=i,o[Bn]=n,o}};vs.exports=wt});var Ot=v((ca,Cs)=>{"use strict";var{Duplex:la}=S("stream"),{randomFillSync:$n}=S("crypto"),{types:{isUint8Array:Wn}}=S("util"),Is=fe(),{EMPTY_BUFFER:Gn,kWebSocket:jn,NOOP:Vn}=F(),{isBlob:de,isValidStatusCode:qn}=ue(),{mask:Os,toBuffer:K}=Ae(),R=Symbol("kByteLength"),zn=Buffer.alloc(4),Ge=8*1024,J,he=Ge,L=0,Xn=1,Kn=2,vt=class t{constructor(e,s,r){this._extensions=s||{},r&&(this._generateMask=r,this._maskBuffer=Buffer.alloc(4)),this._socket=e,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=L,this.onerror=Vn,this[jn]=void 0}static frame(e,s){let r,n=!1,i=2,o=!1;s.mask&&(r=s.maskBuffer||zn,s.generateMask?s.generateMask(r):(he===Ge&&(J===void 0&&(J=Buffer.alloc(Ge)),$n(J,0,Ge),he=0),r[0]=J[he++],r[1]=J[he++],r[2]=J[he++],r[3]=J[he++]),o=(r[0]|r[1]|r[2]|r[3])===0,i=6);let a;typeof e=="string"?(!s.mask||o)&&s[R]!==void 0?a=s[R]:(e=Buffer.from(e),a=e.length):(a=e.length,n=s.mask&&s.readOnly&&!o);let l=a;a>=65536?(i+=8,l=127):a>125&&(i+=2,l=126);let c=Buffer.allocUnsafe(n?a+i:i);return c[0]=s.fin?s.opcode|128:s.opcode,s.rsv1&&(c[0]|=64),c[1]=l,l===126?c.writeUInt16BE(a,2):l===127&&(c[2]=c[3]=0,c.writeUIntBE(a,4,6)),s.mask?(c[1]|=128,c[i-4]=r[0],c[i-3]=r[1],c[i-2]=r[2],c[i-1]=r[3],o?[c,e]:n?(Os(e,r,c,i,a),[c]):(Os(e,r,e,0,a),[c,e])):[c,e]}close(e,s,r,n){let i;if(e===void 0)i=Gn;else{if(typeof e!="number"||!qn(e))throw new TypeError("First argument must be a valid error code number");if(s===void 0||!s.length)i=Buffer.allocUnsafe(2),i.writeUInt16BE(e,0);else{let a=Buffer.byteLength(s);if(a>123)throw new RangeError("The message must not be greater than 123 bytes");if(i=Buffer.allocUnsafe(2+a),i.writeUInt16BE(e,0),typeof s=="string")i.write(s,2);else if(Wn(s))i.set(s,2);else throw new TypeError("Second argument must be a string or a Uint8Array")}}let o={[R]:i.length,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state!==L?this.enqueue([this.dispatch,i,!1,o,n]):this.sendFrame(t.frame(i,o),n)}ping(e,s,r){let n,i;if(typeof e=="string"?(n=Buffer.byteLength(e),i=!1):de(e)?(n=e.size,i=!1):(e=K(e),n=e.length,i=K.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[R]:n,fin:!0,generateMask:this._generateMask,mask:s,maskBuffer:this._maskBuffer,opcode:9,readOnly:i,rsv1:!1};de(e)?this._state!==L?this.enqueue([this.getBlobData,e,!1,o,r]):this.getBlobData(e,!1,o,r):this._state!==L?this.enqueue([this.dispatch,e,!1,o,r]):this.sendFrame(t.frame(e,o),r)}pong(e,s,r){let n,i;if(typeof e=="string"?(n=Buffer.byteLength(e),i=!1):de(e)?(n=e.size,i=!1):(e=K(e),n=e.length,i=K.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[R]:n,fin:!0,generateMask:this._generateMask,mask:s,maskBuffer:this._maskBuffer,opcode:10,readOnly:i,rsv1:!1};de(e)?this._state!==L?this.enqueue([this.getBlobData,e,!1,o,r]):this.getBlobData(e,!1,o,r):this._state!==L?this.enqueue([this.dispatch,e,!1,o,r]):this.sendFrame(t.frame(e,o),r)}send(e,s,r){let n=this._extensions[Is.extensionName],i=s.binary?2:1,o=s.compress,a,l;typeof e=="string"?(a=Buffer.byteLength(e),l=!1):de(e)?(a=e.size,l=!1):(e=K(e),a=e.length,l=K.readOnly),this._firstFragment?(this._firstFragment=!1,o&&n&&n.params[n._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(o=a>=n._threshold),this._compress=o):(o=!1,i=0),s.fin&&(this._firstFragment=!0);let c={[R]:a,fin:s.fin,generateMask:this._generateMask,mask:s.mask,maskBuffer:this._maskBuffer,opcode:i,readOnly:l,rsv1:o};de(e)?this._state!==L?this.enqueue([this.getBlobData,e,this._compress,c,r]):this.getBlobData(e,this._compress,c,r):this._state!==L?this.enqueue([this.dispatch,e,this._compress,c,r]):this.dispatch(e,this._compress,c,r)}getBlobData(e,s,r,n){this._bufferedBytes+=r[R],this._state=Kn,e.arrayBuffer().then(i=>{if(this._socket.destroyed){let a=new Error("The socket was closed while the blob was being read");process.nextTick(It,this,a,n);return}this._bufferedBytes-=r[R];let o=K(i);s?this.dispatch(o,s,r,n):(this._state=L,this.sendFrame(t.frame(o,r),n),this.dequeue())}).catch(i=>{process.nextTick(Jn,this,i,n)})}dispatch(e,s,r,n){if(!s){this.sendFrame(t.frame(e,r),n);return}let i=this._extensions[Is.extensionName];this._bufferedBytes+=r[R],this._state=Xn,i.compress(e,r.fin,(o,a)=>{if(this._socket.destroyed){let l=new Error("The socket was closed while data was being compressed");It(this,l,n);return}this._bufferedBytes-=r[R],this._state=L,r.readOnly=!1,this.sendFrame(t.frame(a,r),n),this.dequeue()})}dequeue(){for(;this._state===L&&this._queue.length;){let e=this._queue.shift();this._bufferedBytes-=e[3][R],Reflect.apply(e[0],this,e.slice(1))}}enqueue(e){this._bufferedBytes+=e[3][R],this._queue.push(e)}sendFrame(e,s){e.length===2?(this._socket.cork(),this._socket.write(e[0]),this._socket.write(e[1],s),this._socket.uncork()):this._socket.write(e[0],s)}};Cs.exports=vt;function It(t,e,s){typeof s=="function"&&s(e);for(let r=0;r<t._queue.length;r++){let n=t._queue[r],i=n[n.length-1];typeof i=="function"&&i(e)}}function Jn(t,e,s){It(t,e,s),t.onerror(e)}});var Us=v((fa,Bs)=>{"use strict";var{kForOnEventAttribute:Ie,kListener:Ct}=F(),Ps=Symbol("kCode"),Rs=Symbol("kData"),ks=Symbol("kError"),Ls=Symbol("kMessage"),Ns=Symbol("kReason"),me=Symbol("kTarget"),Ms=Symbol("kType"),Ds=Symbol("kWasClean"),Y=class{constructor(e){this[me]=null,this[Ms]=e}get target(){return this[me]}get type(){return this[Ms]}};Object.defineProperty(Y.prototype,"target",{enumerable:!0});Object.defineProperty(Y.prototype,"type",{enumerable:!0});var Z=class extends Y{constructor(e,s={}){super(e),this[Ps]=s.code===void 0?0:s.code,this[Ns]=s.reason===void 0?"":s.reason,this[Ds]=s.wasClean===void 0?!1:s.wasClean}get code(){return this[Ps]}get reason(){return this[Ns]}get wasClean(){return this[Ds]}};Object.defineProperty(Z.prototype,"code",{enumerable:!0});Object.defineProperty(Z.prototype,"reason",{enumerable:!0});Object.defineProperty(Z.prototype,"wasClean",{enumerable:!0});var pe=class extends Y{constructor(e,s={}){super(e),this[ks]=s.error===void 0?null:s.error,this[Ls]=s.message===void 0?"":s.message}get error(){return this[ks]}get message(){return this[Ls]}};Object.defineProperty(pe.prototype,"error",{enumerable:!0});Object.defineProperty(pe.prototype,"message",{enumerable:!0});var Oe=class extends Y{constructor(e,s={}){super(e),this[Rs]=s.data===void 0?null:s.data}get data(){return this[Rs]}};Object.defineProperty(Oe.prototype,"data",{enumerable:!0});var Zn={addEventListener(t,e,s={}){for(let n of this.listeners(t))if(!s[Ie]&&n[Ct]===e&&!n[Ie])return;let r;if(t==="message")r=function(i,o){let a=new Oe("message",{data:o?i:i.toString()});a[me]=this,je(e,this,a)};else if(t==="close")r=function(i,o){let a=new Z("close",{code:i,reason:o.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});a[me]=this,je(e,this,a)};else if(t==="error")r=function(i){let o=new pe("error",{error:i,message:i.message});o[me]=this,je(e,this,o)};else if(t==="open")r=function(){let i=new Y("open");i[me]=this,je(e,this,i)};else return;r[Ie]=!!s[Ie],r[Ct]=e,s.once?this.once(t,r):this.on(t,r)},removeEventListener(t,e){for(let s of this.listeners(t))if(s[Ct]===e&&!s[Ie]){this.removeListener(t,s);break}}};Bs.exports={CloseEvent:Z,ErrorEvent:pe,Event:Y,EventTarget:Zn,MessageEvent:Oe};function je(t,e,s){typeof t=="object"&&t.handleEvent?t.handleEvent.call(t,s):t.call(e,s)}});var Ve=v((ua,Fs)=>{"use strict";var{tokenChars:Ce}=ue();function D(t,e,s){t[e]===void 0?t[e]=[s]:t[e].push(s)}function Qn(t){let e=Object.create(null),s=Object.create(null),r=!1,n=!1,i=!1,o,a,l=-1,c=-1,f=-1,d=0;for(;d<t.length;d++)if(c=t.charCodeAt(d),o===void 0)if(f===-1&&Ce[c]===1)l===-1&&(l=d);else if(d!==0&&(c===32||c===9))f===-1&&l!==-1&&(f=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d);let h=t.slice(l,f);c===44?(D(e,h,s),s=Object.create(null)):o=h,l=f=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);else if(a===void 0)if(f===-1&&Ce[c]===1)l===-1&&(l=d);else if(c===32||c===9)f===-1&&l!==-1&&(f=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d),D(s,t.slice(l,f),!0),c===44&&(D(e,o,s),s=Object.create(null),o=void 0),l=f=-1}else if(c===61&&l!==-1&&f===-1)a=t.slice(l,d),l=f=-1;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(n){if(Ce[c]!==1)throw new SyntaxError(`Unexpected character at index ${d}`);l===-1?l=d:r||(r=!0),n=!1}else if(i)if(Ce[c]===1)l===-1&&(l=d);else if(c===34&&l!==-1)i=!1,f=d;else if(c===92)n=!0;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(c===34&&t.charCodeAt(d-1)===61)i=!0;else if(f===-1&&Ce[c]===1)l===-1&&(l=d);else if(l!==-1&&(c===32||c===9))f===-1&&(f=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d);let h=t.slice(l,f);r&&(h=h.replace(/\\/g,""),r=!1),D(s,a,h),c===44&&(D(e,o,s),s=Object.create(null),o=void 0),a=void 0,l=f=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);if(l===-1||i||c===32||c===9)throw new SyntaxError("Unexpected end of input");f===-1&&(f=d);let u=t.slice(l,f);return o===void 0?D(e,u,s):(a===void 0?D(s,u,!0):r?D(s,a,u.replace(/\\/g,"")):D(s,a,u),D(e,o,s)),e}function ei(t){return Object.keys(t).map(e=>{let s=t[e];return Array.isArray(s)||(s=[s]),s.map(r=>[e].concat(Object.keys(r).map(n=>{let i=r[n];return Array.isArray(i)||(i=[i]),i.map(o=>o===!0?n:`${n}=${o}`).join("; ")})).join("; ")).join(", ")}).join(", ")}Fs.exports={format:ei,parse:Qn}});var Ke=v((ma,Js)=>{"use strict";var ti=S("events"),si=S("https"),ri=S("http"),$s=S("net"),ni=S("tls"),{randomBytes:ii,createHash:oi}=S("crypto"),{Duplex:da,Readable:ha}=S("stream"),{URL:Pt}=S("url"),V=fe(),ai=At(),li=Ot(),{isBlob:ci}=ue(),{BINARY_TYPES:Hs,CLOSE_TIMEOUT:fi,EMPTY_BUFFER:qe,GUID:ui,kForOnEventAttribute:Rt,kListener:di,kStatusCode:hi,kWebSocket:E,NOOP:Ws}=F(),{EventTarget:{addEventListener:mi,removeEventListener:pi}}=Us(),{format:_i,parse:yi}=Ve(),{toBuffer:gi}=Ae(),Gs=Symbol("kAborted"),kt=[8,13],$=["CONNECTING","OPEN","CLOSING","CLOSED"],Si=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,g=class t extends ti{constructor(e,s,r){super(),this._binaryType=Hs[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=qe,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=t.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,e!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,s===void 0?s=[]:Array.isArray(s)||(typeof s=="object"&&s!==null?(r=s,s=[]):s=[s]),js(this,e,s,r)):(this._autoPong=r.autoPong,this._closeTimeout=r.closeTimeout,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(e){Hs.includes(e)&&(this._binaryType=e,this._receiver&&(this._receiver._binaryType=e))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(e,s,r){let n=new ai({allowSynchronousEvents:r.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxBufferedChunks:r.maxBufferedChunks,maxFragments:r.maxFragments,maxPayload:r.maxPayload,skipUTF8Validation:r.skipUTF8Validation}),i=new li(e,this._extensions,r.generateMask);this._receiver=n,this._sender=i,this._socket=e,n[E]=this,i[E]=this,e[E]=this,n.on("conclude",bi),n.on("drain",Ti),n.on("error",wi),n.on("message",Ai),n.on("ping",vi),n.on("pong",Ii),i.onerror=Oi,e.setTimeout&&e.setTimeout(0),e.setNoDelay&&e.setNoDelay(),s.length>0&&e.unshift(s),e.on("close",zs),e.on("data",Xe),e.on("end",Xs),e.on("error",Ks),this._readyState=t.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=t.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[V.extensionName]&&this._extensions[V.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=t.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(e,s){if(this.readyState!==t.CLOSED){if(this.readyState===t.CONNECTING){O(this,this._req,"WebSocket was closed before the connection was established");return}if(this.readyState===t.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=t.CLOSING,this._sender.close(e,s,!this._isServer,r=>{r||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),qs(this)}}pause(){this.readyState===t.CONNECTING||this.readyState===t.CLOSED||(this._paused=!0,this._socket.pause())}ping(e,s,r){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(r=e,e=s=void 0):typeof s=="function"&&(r=s,s=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){Lt(this,e,r);return}s===void 0&&(s=!this._isServer),this._sender.ping(e||qe,s,r)}pong(e,s,r){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(r=e,e=s=void 0):typeof s=="function"&&(r=s,s=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){Lt(this,e,r);return}s===void 0&&(s=!this._isServer),this._sender.pong(e||qe,s,r)}resume(){this.readyState===t.CONNECTING||this.readyState===t.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(e,s,r){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof s=="function"&&(r=s,s={}),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){Lt(this,e,r);return}let n={binary:typeof e!="string",mask:!this._isServer,compress:!0,fin:!0,...s};this._extensions[V.extensionName]||(n.compress=!1),this._sender.send(e||qe,n,r)}terminate(){if(this.readyState!==t.CLOSED){if(this.readyState===t.CONNECTING){O(this,this._req,"WebSocket was closed before the connection was established");return}this._socket&&(this._readyState=t.CLOSING,this._socket.destroy())}}};Object.defineProperty(g,"CONNECTING",{enumerable:!0,value:$.indexOf("CONNECTING")});Object.defineProperty(g.prototype,"CONNECTING",{enumerable:!0,value:$.indexOf("CONNECTING")});Object.defineProperty(g,"OPEN",{enumerable:!0,value:$.indexOf("OPEN")});Object.defineProperty(g.prototype,"OPEN",{enumerable:!0,value:$.indexOf("OPEN")});Object.defineProperty(g,"CLOSING",{enumerable:!0,value:$.indexOf("CLOSING")});Object.defineProperty(g.prototype,"CLOSING",{enumerable:!0,value:$.indexOf("CLOSING")});Object.defineProperty(g,"CLOSED",{enumerable:!0,value:$.indexOf("CLOSED")});Object.defineProperty(g.prototype,"CLOSED",{enumerable:!0,value:$.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(t=>{Object.defineProperty(g.prototype,t,{enumerable:!0})});["open","error","close","message"].forEach(t=>{Object.defineProperty(g.prototype,`on${t}`,{enumerable:!0,get(){for(let e of this.listeners(t))if(e[Rt])return e[di];return null},set(e){for(let s of this.listeners(t))if(s[Rt]){this.removeListener(t,s);break}typeof e=="function"&&this.addEventListener(t,e,{[Rt]:!0})}})});g.prototype.addEventListener=mi;g.prototype.removeEventListener=pi;Js.exports=g;function js(t,e,s,r){let n={allowSynchronousEvents:!0,autoPong:!0,closeTimeout:fi,protocolVersion:kt[1],maxBufferedChunks:262144,maxFragments:16384,maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...r,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:"GET",host:void 0,path:void 0,port:void 0};if(t._autoPong=n.autoPong,t._closeTimeout=n.closeTimeout,!kt.includes(n.protocolVersion))throw new RangeError(`Unsupported protocol version: ${n.protocolVersion} (supported versions: ${kt.join(", ")})`);let i;if(e instanceof Pt)i=e;else try{i=new Pt(e)}catch{throw new SyntaxError(`Invalid URL: ${e}`)}i.protocol==="http:"?i.protocol="ws:":i.protocol==="https:"&&(i.protocol="wss:"),t._url=i.href;let o=i.protocol==="wss:",a=i.protocol==="ws+unix:",l;if(i.protocol!=="ws:"&&!o&&!a?l=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:a&&!i.pathname?l="The URL's pathname is empty":i.hash&&(l="The URL contains a fragment identifier"),l){let _=new SyntaxError(l);if(t._redirects===0)throw _;ze(t,_);return}let c=o?443:80,f=ii(16).toString("base64"),d=o?si.request:ri.request,u=new Set,h;if(n.createConnection=n.createConnection||(o?Ei:xi),n.defaultPort=n.defaultPort||c,n.port=i.port||c,n.host=i.hostname.startsWith("[")?i.hostname.slice(1,-1):i.hostname,n.headers={...n.headers,"Sec-WebSocket-Version":n.protocolVersion,"Sec-WebSocket-Key":f,Connection:"Upgrade",Upgrade:"websocket"},n.path=i.pathname+i.search,n.timeout=n.handshakeTimeout,n.perMessageDeflate&&(h=new V({...n.perMessageDeflate,isServer:!1,maxPayload:n.maxPayload}),n.headers["Sec-WebSocket-Extensions"]=_i({[V.extensionName]:h.offer()})),s.length){for(let _ of s){if(typeof _!="string"||!Si.test(_)||u.has(_))throw new SyntaxError("An invalid or duplicated subprotocol was specified");u.add(_)}n.headers["Sec-WebSocket-Protocol"]=s.join(",")}if(n.origin&&(n.protocolVersion<13?n.headers["Sec-WebSocket-Origin"]=n.origin:n.headers.Origin=n.origin),(i.username||i.password)&&(n.auth=`${i.username}:${i.password}`),a){let _=n.path.split(":");n.socketPath=_[0],n.path=_[1]}let p;if(n.followRedirects){if(t._redirects===0){t._originalIpc=a,t._originalSecure=o,t._originalHostOrSocketPath=a?n.socketPath:i.host;let _=r&&r.headers;if(r={...r,headers:{}},_)for(let[b,ie]of Object.entries(_))r.headers[b.toLowerCase()]=ie}else if(t.listenerCount("redirect")===0){let _=a?t._originalIpc?n.socketPath===t._originalHostOrSocketPath:!1:t._originalIpc?!1:i.host===t._originalHostOrSocketPath;(!_||t._originalSecure&&!o)&&(delete n.headers.authorization,delete n.headers.cookie,_||delete n.headers.host,n.auth=void 0)}n.auth&&!r.headers.authorization&&(r.headers.authorization="Basic "+Buffer.from(n.auth).toString("base64")),p=t._req=d(n),t._redirects&&t.emit("redirect",t.url,p)}else p=t._req=d(n);n.timeout&&p.on("timeout",()=>{O(t,p,"Opening handshake has timed out")}),p.on("error",_=>{p===null||p[Gs]||(p=t._req=null,ze(t,_))}),p.on("response",_=>{let b=_.headers.location,ie=_.statusCode;if(b&&n.followRedirects&&ie>=300&&ie<400){if(++t._redirects>n.maxRedirects){O(t,p,"Maximum redirects exceeded");return}p.abort();let be;try{be=new Pt(b,e)}catch{let oe=new SyntaxError(`Invalid URL: ${b}`);ze(t,oe);return}js(t,be,s,r)}else t.emit("unexpected-response",p,_)||O(t,p,`Unexpected server response: ${_.statusCode}`)}),p.on("upgrade",(_,b,ie)=>{if(t.emit("upgrade",_),t.readyState!==g.CONNECTING)return;p=t._req=null;let be=_.headers.upgrade;if(be===void 0||be.toLowerCase()!=="websocket"){O(t,b,"Invalid Upgrade header");return}let ss=oi("sha1").update(f+ui).digest("base64");if(_.headers["sec-websocket-accept"]!==ss){O(t,b,"Invalid Sec-WebSocket-Accept header");return}let oe=_.headers["sec-websocket-protocol"],Te;if(oe!==void 0?u.size?u.has(oe)||(Te="Server sent an invalid subprotocol"):Te="Server sent a subprotocol but none was requested":u.size&&(Te="Server sent no subprotocol"),Te){O(t,b,Te);return}oe&&(t._protocol=oe);let rs=_.headers["sec-websocket-extensions"];if(rs!==void 0){if(!h){O(t,b,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let ft;try{ft=yi(rs)}catch{O(t,b,"Invalid Sec-WebSocket-Extensions header");return}let ns=Object.keys(ft);if(ns.length!==1||ns[0]!==V.extensionName){O(t,b,"Server indicated an extension that was not requested");return}try{h.accept(ft[V.extensionName])}catch{O(t,b,"Invalid Sec-WebSocket-Extensions header");return}t._extensions[V.extensionName]=h}t.setSocket(b,ie,{allowSynchronousEvents:n.allowSynchronousEvents,generateMask:n.generateMask,maxBufferedChunks:n.maxBufferedChunks,maxFragments:n.maxFragments,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation})}),n.finishRequest?n.finishRequest(p,t):p.end()}function ze(t,e){t._readyState=g.CLOSING,t._errorEmitted=!0,t.emit("error",e),t.emitClose()}function xi(t){return t.path=t.socketPath,$s.connect(t)}function Ei(t){return t.path=void 0,!t.servername&&t.servername!==""&&(t.servername=$s.isIP(t.host)?"":t.host),ni.connect(t)}function O(t,e,s){t._readyState=g.CLOSING;let r=new Error(s);Error.captureStackTrace(r,O),e.setHeader?(e[Gs]=!0,e.abort(),e.socket&&!e.socket.destroyed&&e.socket.destroy(),process.nextTick(ze,t,r)):(e.destroy(r),e.once("error",t.emit.bind(t,"error")),e.once("close",t.emitClose.bind(t)))}function Lt(t,e,s){if(e){let r=ci(e)?e.size:gi(e).length;t._socket?t._sender._bufferedBytes+=r:t._bufferedAmount+=r}if(s){let r=new Error(`WebSocket is not open: readyState ${t.readyState} (${$[t.readyState]})`);process.nextTick(s,r)}}function bi(t,e){let s=this[E];s._closeFrameReceived=!0,s._closeMessage=e,s._closeCode=t,s._socket[E]!==void 0&&(s._socket.removeListener("data",Xe),process.nextTick(Vs,s._socket),t===1005?s.close():s.close(t,e))}function Ti(){let t=this[E];t.isPaused||t._socket.resume()}function wi(t){let e=this[E];e._socket[E]!==void 0&&(e._socket.removeListener("data",Xe),process.nextTick(Vs,e._socket),e.close(t[hi])),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",t))}function Ys(){this[E].emitClose()}function Ai(t,e){this[E].emit("message",t,e)}function vi(t){let e=this[E];e._autoPong&&e.pong(t,!this._isServer,Ws),e.emit("ping",t)}function Ii(t){this[E].emit("pong",t)}function Vs(t){t.resume()}function Oi(t){let e=this[E];e.readyState!==g.CLOSED&&(e.readyState===g.OPEN&&(e._readyState=g.CLOSING,qs(e)),this._socket.end(),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",t)))}function qs(t){t._closeTimer=setTimeout(t._socket.destroy.bind(t._socket),t._closeTimeout)}function zs(){let t=this[E];if(this.removeListener("close",zs),this.removeListener("data",Xe),this.removeListener("end",Xs),t._readyState=g.CLOSING,!this._readableState.endEmitted&&!t._closeFrameReceived&&!t._receiver._writableState.errorEmitted&&this._readableState.length!==0){let e=this.read(this._readableState.length);t._receiver.write(e)}t._receiver.end(),this[E]=void 0,clearTimeout(t._closeTimer),t._receiver._writableState.finished||t._receiver._writableState.errorEmitted?t.emitClose():(t._receiver.on("error",Ys),t._receiver.on("finish",Ys))}function Xe(t){this[E]._receiver.write(t)||this.pause()}function Xs(){let t=this[E];t._readyState=g.CLOSING,t._receiver.end(),this.end()}function Ks(){let t=this[E];this.removeListener("error",Ks),this.on("error",Ws),t&&(t._readyState=g.CLOSING,this.destroy())}});var tr=v((_a,er)=>{"use strict";var pa=Ke(),{Duplex:Ci}=S("stream");function Zs(t){t.emit("close")}function Pi(){!this.destroyed&&this._writableState.finished&&this.destroy()}function Qs(t){this.removeListener("error",Qs),this.destroy(),this.listenerCount("error")===0&&this.emit("error",t)}function Ri(t,e){let s=!0,r=new Ci({...e,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return t.on("message",function(i,o){let a=!o&&r._readableState.objectMode?i.toString():i;r.push(a)||t.pause()}),t.once("error",function(i){r.destroyed||(s=!1,r.destroy(i))}),t.once("close",function(){r.destroyed||r.push(null)}),r._destroy=function(n,i){if(t.readyState===t.CLOSED){i(n),process.nextTick(Zs,r);return}let o=!1;t.once("error",function(l){o=!0,i(l)}),t.once("close",function(){o||i(n),process.nextTick(Zs,r)}),s&&t.terminate()},r._final=function(n){if(t.readyState===t.CONNECTING){t.once("open",function(){r._final(n)});return}t._socket!==null&&(t._socket._writableState.finished?(n(),r._readableState.endEmitted&&r.destroy()):(t._socket.once("finish",function(){n()}),t.close()))},r._read=function(){t.isPaused&&t.resume()},r._write=function(n,i,o){if(t.readyState===t.CONNECTING){t.once("open",function(){r._write(n,i,o)});return}t.send(n,o)},r.on("end",Pi),r.on("error",Qs),r}er.exports=Ri});var Nt=v((ya,sr)=>{"use strict";var{tokenChars:ki}=ue();function Li(t){let e=new Set,s=-1,r=-1,n=0;for(n;n<t.length;n++){let o=t.charCodeAt(n);if(r===-1&&ki[o]===1)s===-1&&(s=n);else if(n!==0&&(o===32||o===9))r===-1&&s!==-1&&(r=n);else if(o===44){if(s===-1)throw new SyntaxError(`Unexpected character at index ${n}`);r===-1&&(r=n);let a=t.slice(s,r);if(e.has(a))throw new SyntaxError(`The "${a}" subprotocol is duplicated`);e.add(a),s=r=-1}else throw new SyntaxError(`Unexpected character at index ${n}`)}if(s===-1||r!==-1)throw new SyntaxError("Unexpected end of input");let i=t.slice(s,n);if(e.has(i))throw new SyntaxError(`The "${i}" subprotocol is duplicated`);return e.add(i),e}sr.exports={parse:Li}});var cr=v((Sa,lr)=>{"use strict";var Ni=S("events"),Je=S("http"),{Duplex:ga}=S("stream"),{createHash:Mi}=S("crypto"),rr=Ve(),Q=fe(),Di=Nt(),Bi=Ke(),{CLOSE_TIMEOUT:Ui,GUID:Fi,kWebSocket:Hi}=F(),Yi=/^[+/0-9A-Za-z]{22}==$/,nr=0,ir=1,ar=2,Mt=class extends Ni{constructor(e,s){if(super(),e={allowSynchronousEvents:!0,autoPong:!0,maxBufferedChunks:256*1024,maxFragments:16*1024,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,closeTimeout:Ui,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:Bi,...e},e.port==null&&!e.server&&!e.noServer||e.port!=null&&(e.server||e.noServer)||e.server&&e.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(e.port!=null?(this._server=Je.createServer((r,n)=>{let i=Je.STATUS_CODES[426];n.writeHead(426,{"Content-Length":i.length,"Content-Type":"text/plain"}),n.end(i)}),this._server.listen(e.port,e.host,e.backlog,s)):e.server&&(this._server=e.server),this._server){let r=this.emit.bind(this,"connection");this._removeListeners=$i(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(n,i,o)=>{this.handleUpgrade(n,i,o,r)}})}e.perMessageDeflate===!0&&(e.perMessageDeflate={}),e.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=e,this._state=nr}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(e){if(this._state===ar){e&&this.once("close",()=>{e(new Error("The server is not running"))}),process.nextTick(Pe,this);return}if(e&&this.once("close",e),this._state!==ir)if(this._state=ir,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients?this.clients.size?this._shouldEmitClose=!0:process.nextTick(Pe,this):process.nextTick(Pe,this);else{let s=this._server;this._removeListeners(),this._removeListeners=this._server=null,s.close(()=>{Pe(this)})}}shouldHandle(e){if(this.options.path){let s=e.url.indexOf("?");if((s!==-1?e.url.slice(0,s):e.url)!==this.options.path)return!1}return!0}handleUpgrade(e,s,r,n){s.on("error",or);let i=e.headers["sec-websocket-key"],o=e.headers.upgrade,a=+e.headers["sec-websocket-version"];if(e.method!=="GET"){ee(this,e,s,405,"Invalid HTTP method");return}if(o===void 0||o.toLowerCase()!=="websocket"){ee(this,e,s,400,"Invalid Upgrade header");return}if(i===void 0||!Yi.test(i)){ee(this,e,s,400,"Missing or invalid Sec-WebSocket-Key header");return}if(a!==13&&a!==8){ee(this,e,s,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"});return}if(!this.shouldHandle(e)){Re(s,400);return}let l=e.headers["sec-websocket-protocol"],c=new Set;if(l!==void 0)try{c=Di.parse(l)}catch{ee(this,e,s,400,"Invalid Sec-WebSocket-Protocol header");return}let f=e.headers["sec-websocket-extensions"],d={};if(this.options.perMessageDeflate&&f!==void 0){let u=new Q({...this.options.perMessageDeflate,isServer:!0,maxPayload:this.options.maxPayload});try{let h=rr.parse(f);h[Q.extensionName]&&(u.accept(h[Q.extensionName]),d[Q.extensionName]=u)}catch{ee(this,e,s,400,"Invalid or unacceptable Sec-WebSocket-Extensions header");return}}if(this.options.verifyClient){let u={origin:e.headers[`${a===8?"sec-websocket-origin":"origin"}`],secure:!!(e.socket.authorized||e.socket.encrypted),req:e};if(this.options.verifyClient.length===2){this.options.verifyClient(u,(h,p,_,b)=>{if(!h)return Re(s,p||401,_,b);this.completeUpgrade(d,i,c,e,s,r,n)});return}if(!this.options.verifyClient(u))return Re(s,401)}this.completeUpgrade(d,i,c,e,s,r,n)}completeUpgrade(e,s,r,n,i,o,a){if(!i.readable||!i.writable)return i.destroy();if(i[Hi])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>nr)return Re(i,503);let c=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${Mi("sha1").update(s+Fi).digest("base64")}`],f=new this.options.WebSocket(null,void 0,this.options);if(r.size){let d=this.options.handleProtocols?this.options.handleProtocols(r,n):r.values().next().value;d&&(c.push(`Sec-WebSocket-Protocol: ${d}`),f._protocol=d)}if(e[Q.extensionName]){let d=e[Q.extensionName].params,u=rr.format({[Q.extensionName]:[d]});c.push(`Sec-WebSocket-Extensions: ${u}`),f._extensions=e}this.emit("headers",c,n),i.write(c.concat(`\r
4
+ var fn=Object.create;var is=Object.defineProperty;var un=Object.getOwnPropertyDescriptor;var dn=Object.getOwnPropertyNames;var hn=Object.getPrototypeOf,pn=Object.prototype.hasOwnProperty;var S=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,s)=>(typeof require<"u"?require:e)[s]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var I=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var mn=(t,e,s,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of dn(e))!pn.call(t,n)&&n!==s&&is(t,n,{get:()=>e[n],enumerable:!(r=un(e,n))||r.enumerable});return t};var G=(t,e,s)=>(s=t!=null?fn(hn(t)):{},mn(e||!t||!t.__esModule?is(s,"default",{value:t,enumerable:!0}):s,t));var U=I((oa,cs)=>{"use strict";var as=["nodebuffer","arraybuffer","fragments"],ls=typeof Blob<"u";ls&&as.push("blob");cs.exports={BINARY_TYPES:as,CLOSE_TIMEOUT:3e4,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:ls,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}});var Ae=I((aa,Fe)=>{"use strict";var{EMPTY_BUFFER:In}=U(),mt=Buffer[Symbol.species];function vn(t,e){if(t.length===0)return In;if(t.length===1)return t[0];let s=Buffer.allocUnsafe(e),r=0;for(let n=0;n<t.length;n++){let i=t[n];s.set(i,r),r+=i.length}return r<e?new mt(s.buffer,s.byteOffset,r):s}function fs(t,e,s,r,n){for(let i=0;i<n;i++)s[r+i]=t[i]^e[i&3]}function us(t,e){for(let s=0;s<t.length;s++)t[s]^=e[s&3]}function On(t){return t.length===t.buffer.byteLength?t.buffer:t.buffer.slice(t.byteOffset,t.byteOffset+t.length)}function _t(t){if(_t.readOnly=!0,Buffer.isBuffer(t))return t;let e;return t instanceof ArrayBuffer?e=new mt(t):ArrayBuffer.isView(t)?e=new mt(t.buffer,t.byteOffset,t.byteLength):(e=Buffer.from(t),_t.readOnly=!1),e}Fe.exports={concat:vn,mask:fs,toArrayBuffer:On,toBuffer:_t,unmask:us};if(!process.env.WS_NO_BUFFER_UTIL)try{let t=S("bufferutil");Fe.exports.mask=function(e,s,r,n,i){i<48?fs(e,s,r,n,i):t.mask(e,s,r,n,i)},Fe.exports.unmask=function(e,s){e.length<32?us(e,s):t.unmask(e,s)}}catch{}});var ps=I((la,hs)=>{"use strict";var ds=Symbol("kDone"),yt=Symbol("kRun"),gt=class{constructor(e){this[ds]=()=>{this.pending--,this[yt]()},this.concurrency=e||1/0,this.jobs=[],this.pending=0}add(e){this.jobs.push(e),this[yt]()}[yt](){if(this.pending!==this.concurrency&&this.jobs.length){let e=this.jobs.shift();this.pending++,e(this[ds])}}};hs.exports=gt});var ue=I((ca,gs)=>{"use strict";var Ie=S("zlib"),ms=Ae(),Cn=ps(),{kStatusCode:_s}=U(),Pn=Buffer[Symbol.species],Rn=Buffer.from([0,0,255,255]),He=Symbol("permessage-deflate"),H=Symbol("total-length"),ce=Symbol("callback"),j=Symbol("buffers"),fe=Symbol("error"),Ue,St=class{constructor(e){if(this._options=e||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._maxPayload=this._options.maxPayload|0,this._isServer=!!this._options.isServer,this._deflate=null,this._inflate=null,this.params=null,!Ue){let s=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;Ue=new Cn(s)}}static get extensionName(){return"permessage-deflate"}offer(){let e={};return this._options.serverNoContextTakeover&&(e.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(e.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(e.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?e.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(e.client_max_window_bits=!0),e}accept(e){return e=this.normalizeParams(e),this.params=this._isServer?this.acceptAsServer(e):this.acceptAsClient(e),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let e=this._deflate[ce];this._deflate.close(),this._deflate=null,e&&e(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(e){let s=this._options,r=e.find(n=>!(s.serverNoContextTakeover===!1&&n.server_no_context_takeover||n.server_max_window_bits&&(s.serverMaxWindowBits===!1||typeof s.serverMaxWindowBits=="number"&&s.serverMaxWindowBits>n.server_max_window_bits)||typeof s.clientMaxWindowBits=="number"&&(typeof n.client_max_window_bits=="number"?s.clientMaxWindowBits>n.client_max_window_bits:!n.client_max_window_bits)));if(!r)throw new Error("None of the extension offers can be accepted");return s.serverNoContextTakeover&&(r.server_no_context_takeover=!0),s.clientNoContextTakeover&&(r.client_no_context_takeover=!0),typeof s.serverMaxWindowBits=="number"&&(r.server_max_window_bits=s.serverMaxWindowBits),typeof s.clientMaxWindowBits=="number"?r.client_max_window_bits=s.clientMaxWindowBits:(r.client_max_window_bits===!0||s.clientMaxWindowBits===!1)&&delete r.client_max_window_bits,r}acceptAsClient(e){let s=e[0];if(this._options.clientNoContextTakeover===!1&&s.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!s.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(s.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&s.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return s}normalizeParams(e){return e.forEach(s=>{Object.keys(s).forEach(r=>{let n=s[r];if(n.length>1)throw new Error(`Parameter "${r}" must have only a single value`);if(n=n[0],r==="client_max_window_bits"){if(n!==!0){let i=+n;if(!Number.isInteger(i)||i<8||i>15)throw new TypeError(`Invalid value for parameter "${r}": ${n}`);n=i}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${r}": ${n}`)}else if(r==="server_max_window_bits"){let i=+n;if(!Number.isInteger(i)||i<8||i>15)throw new TypeError(`Invalid value for parameter "${r}": ${n}`);n=i}else if(r==="client_no_context_takeover"||r==="server_no_context_takeover"){if(n!==!0)throw new TypeError(`Invalid value for parameter "${r}": ${n}`)}else throw new Error(`Unknown parameter "${r}"`);s[r]=n})}),e}decompress(e,s,r){Ue.add(n=>{this._decompress(e,s,(i,o)=>{n(),r(i,o)})})}compress(e,s,r){Ue.add(n=>{this._compress(e,s,(i,o)=>{n(),r(i,o)})})}_decompress(e,s,r){let n=this._isServer?"client":"server";if(!this._inflate){let i=`${n}_max_window_bits`,o=typeof this.params[i]!="number"?Ie.Z_DEFAULT_WINDOWBITS:this.params[i];this._inflate=Ie.createInflateRaw({...this._options.zlibInflateOptions,windowBits:o}),this._inflate[He]=this,this._inflate[H]=0,this._inflate[j]=[],this._inflate.on("error",Ln),this._inflate.on("data",ys)}this._inflate[ce]=r,this._inflate.write(e),s&&this._inflate.write(Rn),this._inflate.flush(()=>{let i=this._inflate[fe];if(i){this._inflate.close(),this._inflate=null,r(i);return}let o=ms.concat(this._inflate[j],this._inflate[H]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[H]=0,this._inflate[j]=[],s&&this.params[`${n}_no_context_takeover`]&&this._inflate.reset()),r(null,o)})}_compress(e,s,r){let n=this._isServer?"server":"client";if(!this._deflate){let i=`${n}_max_window_bits`,o=typeof this.params[i]!="number"?Ie.Z_DEFAULT_WINDOWBITS:this.params[i];this._deflate=Ie.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:o}),this._deflate[H]=0,this._deflate[j]=[],this._deflate.on("data",kn)}this._deflate[ce]=r,this._deflate.write(e),this._deflate.flush(Ie.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let i=ms.concat(this._deflate[j],this._deflate[H]);s&&(i=new Pn(i.buffer,i.byteOffset,i.length-4)),this._deflate[ce]=null,this._deflate[H]=0,this._deflate[j]=[],s&&this.params[`${n}_no_context_takeover`]&&this._deflate.reset(),r(null,i)})}};gs.exports=St;function kn(t){this[j].push(t),this[H]+=t.length}function ys(t){if(this[H]+=t.length,this[He]._maxPayload<1||this[H]<=this[He]._maxPayload){this[j].push(t);return}this[fe]=new RangeError("Max payload size exceeded"),this[fe].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[fe][_s]=1009,this.removeListener("data",ys),this.reset()}function Ln(t){if(this[He]._inflate=null,this[fe]){this[ce](this[fe]);return}t[_s]=1007,this[ce](t)}});var de=I((fa,$e)=>{"use strict";var{isUtf8:Ss}=S("buffer"),{hasBlob:Mn}=U(),Nn=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function Dn(t){return t>=1e3&&t<=1014&&t!==1004&&t!==1005&&t!==1006||t>=3e3&&t<=4999}function xt(t){let e=t.length,s=0;for(;s<e;)if((t[s]&128)===0)s++;else if((t[s]&224)===192){if(s+1===e||(t[s+1]&192)!==128||(t[s]&254)===192)return!1;s+=2}else if((t[s]&240)===224){if(s+2>=e||(t[s+1]&192)!==128||(t[s+2]&192)!==128||t[s]===224&&(t[s+1]&224)===128||t[s]===237&&(t[s+1]&224)===160)return!1;s+=3}else if((t[s]&248)===240){if(s+3>=e||(t[s+1]&192)!==128||(t[s+2]&192)!==128||(t[s+3]&192)!==128||t[s]===240&&(t[s+1]&240)===128||t[s]===244&&t[s+1]>143||t[s]>244)return!1;s+=4}else return!1;return!0}function Bn(t){return Mn&&typeof t=="object"&&typeof t.arrayBuffer=="function"&&typeof t.type=="string"&&typeof t.stream=="function"&&(t[Symbol.toStringTag]==="Blob"||t[Symbol.toStringTag]==="File")}$e.exports={isBlob:Bn,isValidStatusCode:Dn,isValidUTF8:xt,tokenChars:Nn};if(Ss)$e.exports.isValidUTF8=function(t){return t.length<24?xt(t):Ss(t)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let t=S("utf-8-validate");$e.exports.isValidUTF8=function(e){return e.length<32?xt(e):t(e)}}catch{}});var At=I((ua,Is)=>{"use strict";var{Writable:Fn}=S("stream"),xs=ue(),{BINARY_TYPES:Un,EMPTY_BUFFER:Es,kStatusCode:Hn,kWebSocket:$n}=U(),{concat:Et,toArrayBuffer:Yn,unmask:Wn}=Ae(),{isValidStatusCode:Gn,isValidUTF8:bs}=de(),Ye=Buffer[Symbol.species],P=0,Ts=1,ws=2,As=3,bt=4,Tt=5,We=6,wt=class extends Fn{constructor(e={}){super(),this._allowSynchronousEvents=e.allowSynchronousEvents!==void 0?e.allowSynchronousEvents:!0,this._binaryType=e.binaryType||Un[0],this._extensions=e.extensions||{},this._isServer=!!e.isServer,this._maxBufferedChunks=e.maxBufferedChunks|0,this._maxFragments=e.maxFragments|0,this._maxPayload=e.maxPayload|0,this._skipUTF8Validation=!!e.skipUTF8Validation,this[$n]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._numFragments=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=P}_write(e,s,r){if(this._opcode===8&&this._state==P)return r();if(this._maxBufferedChunks>0&&this._buffers.length>=this._maxBufferedChunks){r(this.createError(RangeError,"Too many buffered chunks",!1,1008,"WS_ERR_TOO_MANY_BUFFERED_PARTS"));return}this._bufferedBytes+=e.length,this._buffers.push(e),this.startLoop(r)}consume(e){if(this._bufferedBytes-=e,e===this._buffers[0].length)return this._buffers.shift();if(e<this._buffers[0].length){let r=this._buffers[0];return this._buffers[0]=new Ye(r.buffer,r.byteOffset+e,r.length-e),new Ye(r.buffer,r.byteOffset,e)}let s=Buffer.allocUnsafe(e);do{let r=this._buffers[0],n=s.length-e;e>=r.length?s.set(this._buffers.shift(),n):(s.set(new Uint8Array(r.buffer,r.byteOffset,e),n),this._buffers[0]=new Ye(r.buffer,r.byteOffset+e,r.length-e)),e-=r.length}while(e>0);return s}startLoop(e){this._loop=!0;do switch(this._state){case P:this.getInfo(e);break;case Ts:this.getPayloadLength16(e);break;case ws:this.getPayloadLength64(e);break;case As:this.getMask();break;case bt:this.getData(e);break;case Tt:case We:this._loop=!1;return}while(this._loop);this._errored||e()}getInfo(e){if(this._bufferedBytes<2){this._loop=!1;return}let s=this.consume(2);if((s[0]&48)!==0){let n=this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3");e(n);return}let r=(s[0]&64)===64;if(r&&!this._extensions[xs.extensionName]){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(n);return}if(this._fin=(s[0]&128)===128,this._opcode=s[0]&15,this._payloadLength=s[1]&127,this._opcode===0){if(r){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(n);return}if(!this._fragmented){let n=this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE");e(n);return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(n);return}this._compressed=r}else if(this._opcode>7&&this._opcode<11){if(!this._fin){let n=this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN");e(n);return}if(r){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(n);return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){let n=this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH");e(n);return}}else{let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(n);return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(s[1]&128)===128,this._isServer){if(!this._masked){let n=this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK");e(n);return}}else if(this._masked){let n=this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK");e(n);return}this._payloadLength===126?this._state=Ts:this._payloadLength===127?this._state=ws:this.haveLength(e)}getPayloadLength16(e){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(e)}getPayloadLength64(e){if(this._bufferedBytes<8){this._loop=!1;return}let s=this.consume(8),r=s.readUInt32BE(0);if(r>Math.pow(2,21)-1){let n=this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH");e(n);return}this._payloadLength=r*Math.pow(2,32)+s.readUInt32BE(4),this.haveLength(e)}haveLength(e){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){let s=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");e(s);return}this._masked?this._state=As:this._state=bt}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=bt}getData(e){let s=Es;if(this._payloadLength){if(this._bufferedBytes<this._payloadLength){this._loop=!1;return}s=this.consume(this._payloadLength),this._masked&&(this._mask[0]|this._mask[1]|this._mask[2]|this._mask[3])!==0&&Wn(s,this._mask)}if(this._opcode>7){this.controlMessage(s,e);return}if(this._maxFragments>0&&++this._numFragments>this._maxFragments){let r=this.createError(RangeError,"Too many message fragments",!1,1008,"WS_ERR_TOO_MANY_BUFFERED_PARTS");e(r);return}if(this._compressed){this._state=Tt,this.decompress(s,e);return}s.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(s)),this.dataMessage(e)}decompress(e,s){this._extensions[xs.extensionName].decompress(e,this._fin,(n,i)=>{if(n)return s(n);if(i.length){if(this._messageLength+=i.length,this._messageLength>this._maxPayload&&this._maxPayload>0){let o=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");s(o);return}this._fragments.push(i)}this.dataMessage(s),this._state===P&&this.startLoop(s)})}dataMessage(e){if(!this._fin){this._state=P;return}let s=this._messageLength,r=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._numFragments=0,this._fragments=[],this._opcode===2){let n;this._binaryType==="nodebuffer"?n=Et(r,s):this._binaryType==="arraybuffer"?n=Yn(Et(r,s)):this._binaryType==="blob"?n=new Blob(r):n=r,this._allowSynchronousEvents?(this.emit("message",n,!0),this._state=P):(this._state=We,setImmediate(()=>{this.emit("message",n,!0),this._state=P,this.startLoop(e)}))}else{let n=Et(r,s);if(!this._skipUTF8Validation&&!bs(n)){let i=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");e(i);return}this._state===Tt||this._allowSynchronousEvents?(this.emit("message",n,!1),this._state=P):(this._state=We,setImmediate(()=>{this.emit("message",n,!1),this._state=P,this.startLoop(e)}))}}controlMessage(e,s){if(this._opcode===8){if(e.length===0)this._loop=!1,this.emit("conclude",1005,Es),this.end();else{let r=e.readUInt16BE(0);if(!Gn(r)){let i=this.createError(RangeError,`invalid status code ${r}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");s(i);return}let n=new Ye(e.buffer,e.byteOffset+2,e.length-2);if(!this._skipUTF8Validation&&!bs(n)){let i=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");s(i);return}this._loop=!1,this.emit("conclude",r,n),this.end()}this._state=P;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?"ping":"pong",e),this._state=P):(this._state=We,setImmediate(()=>{this.emit(this._opcode===9?"ping":"pong",e),this._state=P,this.startLoop(s)}))}createError(e,s,r,n,i){this._loop=!1,this._errored=!0;let o=new e(r?`Invalid WebSocket frame: ${s}`:s);return Error.captureStackTrace(o,this.createError),o.code=i,o[Hn]=n,o}};Is.exports=wt});var Ot=I((ha,Cs)=>{"use strict";var{Duplex:da}=S("stream"),{randomFillSync:jn}=S("crypto"),{types:{isUint8Array:Vn}}=S("util"),vs=ue(),{EMPTY_BUFFER:qn,kWebSocket:zn,NOOP:Xn}=U(),{isBlob:he,isValidStatusCode:Kn}=de(),{mask:Os,toBuffer:J}=Ae(),R=Symbol("kByteLength"),Jn=Buffer.alloc(4),Ge=8*1024,Z,pe=Ge,L=0,Zn=1,Qn=2,It=class t{constructor(e,s,r){this._extensions=s||{},r&&(this._generateMask=r,this._maskBuffer=Buffer.alloc(4)),this._socket=e,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=L,this.onerror=Xn,this[zn]=void 0}static frame(e,s){let r,n=!1,i=2,o=!1;s.mask&&(r=s.maskBuffer||Jn,s.generateMask?s.generateMask(r):(pe===Ge&&(Z===void 0&&(Z=Buffer.alloc(Ge)),jn(Z,0,Ge),pe=0),r[0]=Z[pe++],r[1]=Z[pe++],r[2]=Z[pe++],r[3]=Z[pe++]),o=(r[0]|r[1]|r[2]|r[3])===0,i=6);let a;typeof e=="string"?(!s.mask||o)&&s[R]!==void 0?a=s[R]:(e=Buffer.from(e),a=e.length):(a=e.length,n=s.mask&&s.readOnly&&!o);let l=a;a>=65536?(i+=8,l=127):a>125&&(i+=2,l=126);let c=Buffer.allocUnsafe(n?a+i:i);return c[0]=s.fin?s.opcode|128:s.opcode,s.rsv1&&(c[0]|=64),c[1]=l,l===126?c.writeUInt16BE(a,2):l===127&&(c[2]=c[3]=0,c.writeUIntBE(a,4,6)),s.mask?(c[1]|=128,c[i-4]=r[0],c[i-3]=r[1],c[i-2]=r[2],c[i-1]=r[3],o?[c,e]:n?(Os(e,r,c,i,a),[c]):(Os(e,r,e,0,a),[c,e])):[c,e]}close(e,s,r,n){let i;if(e===void 0)i=qn;else{if(typeof e!="number"||!Kn(e))throw new TypeError("First argument must be a valid error code number");if(s===void 0||!s.length)i=Buffer.allocUnsafe(2),i.writeUInt16BE(e,0);else{let a=Buffer.byteLength(s);if(a>123)throw new RangeError("The message must not be greater than 123 bytes");if(i=Buffer.allocUnsafe(2+a),i.writeUInt16BE(e,0),typeof s=="string")i.write(s,2);else if(Vn(s))i.set(s,2);else throw new TypeError("Second argument must be a string or a Uint8Array")}}let o={[R]:i.length,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state!==L?this.enqueue([this.dispatch,i,!1,o,n]):this.sendFrame(t.frame(i,o),n)}ping(e,s,r){let n,i;if(typeof e=="string"?(n=Buffer.byteLength(e),i=!1):he(e)?(n=e.size,i=!1):(e=J(e),n=e.length,i=J.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[R]:n,fin:!0,generateMask:this._generateMask,mask:s,maskBuffer:this._maskBuffer,opcode:9,readOnly:i,rsv1:!1};he(e)?this._state!==L?this.enqueue([this.getBlobData,e,!1,o,r]):this.getBlobData(e,!1,o,r):this._state!==L?this.enqueue([this.dispatch,e,!1,o,r]):this.sendFrame(t.frame(e,o),r)}pong(e,s,r){let n,i;if(typeof e=="string"?(n=Buffer.byteLength(e),i=!1):he(e)?(n=e.size,i=!1):(e=J(e),n=e.length,i=J.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[R]:n,fin:!0,generateMask:this._generateMask,mask:s,maskBuffer:this._maskBuffer,opcode:10,readOnly:i,rsv1:!1};he(e)?this._state!==L?this.enqueue([this.getBlobData,e,!1,o,r]):this.getBlobData(e,!1,o,r):this._state!==L?this.enqueue([this.dispatch,e,!1,o,r]):this.sendFrame(t.frame(e,o),r)}send(e,s,r){let n=this._extensions[vs.extensionName],i=s.binary?2:1,o=s.compress,a,l;typeof e=="string"?(a=Buffer.byteLength(e),l=!1):he(e)?(a=e.size,l=!1):(e=J(e),a=e.length,l=J.readOnly),this._firstFragment?(this._firstFragment=!1,o&&n&&n.params[n._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(o=a>=n._threshold),this._compress=o):(o=!1,i=0),s.fin&&(this._firstFragment=!0);let c={[R]:a,fin:s.fin,generateMask:this._generateMask,mask:s.mask,maskBuffer:this._maskBuffer,opcode:i,readOnly:l,rsv1:o};he(e)?this._state!==L?this.enqueue([this.getBlobData,e,this._compress,c,r]):this.getBlobData(e,this._compress,c,r):this._state!==L?this.enqueue([this.dispatch,e,this._compress,c,r]):this.dispatch(e,this._compress,c,r)}getBlobData(e,s,r,n){this._bufferedBytes+=r[R],this._state=Qn,e.arrayBuffer().then(i=>{if(this._socket.destroyed){let a=new Error("The socket was closed while the blob was being read");process.nextTick(vt,this,a,n);return}this._bufferedBytes-=r[R];let o=J(i);s?this.dispatch(o,s,r,n):(this._state=L,this.sendFrame(t.frame(o,r),n),this.dequeue())}).catch(i=>{process.nextTick(ei,this,i,n)})}dispatch(e,s,r,n){if(!s){this.sendFrame(t.frame(e,r),n);return}let i=this._extensions[vs.extensionName];this._bufferedBytes+=r[R],this._state=Zn,i.compress(e,r.fin,(o,a)=>{if(this._socket.destroyed){let l=new Error("The socket was closed while data was being compressed");vt(this,l,n);return}this._bufferedBytes-=r[R],this._state=L,r.readOnly=!1,this.sendFrame(t.frame(a,r),n),this.dequeue()})}dequeue(){for(;this._state===L&&this._queue.length;){let e=this._queue.shift();this._bufferedBytes-=e[3][R],Reflect.apply(e[0],this,e.slice(1))}}enqueue(e){this._bufferedBytes+=e[3][R],this._queue.push(e)}sendFrame(e,s){e.length===2?(this._socket.cork(),this._socket.write(e[0]),this._socket.write(e[1],s),this._socket.uncork()):this._socket.write(e[0],s)}};Cs.exports=It;function vt(t,e,s){typeof s=="function"&&s(e);for(let r=0;r<t._queue.length;r++){let n=t._queue[r],i=n[n.length-1];typeof i=="function"&&i(e)}}function ei(t,e,s){vt(t,e,s),t.onerror(e)}});var Fs=I((pa,Bs)=>{"use strict";var{kForOnEventAttribute:ve,kListener:Ct}=U(),Ps=Symbol("kCode"),Rs=Symbol("kData"),ks=Symbol("kError"),Ls=Symbol("kMessage"),Ms=Symbol("kReason"),me=Symbol("kTarget"),Ns=Symbol("kType"),Ds=Symbol("kWasClean"),$=class{constructor(e){this[me]=null,this[Ns]=e}get target(){return this[me]}get type(){return this[Ns]}};Object.defineProperty($.prototype,"target",{enumerable:!0});Object.defineProperty($.prototype,"type",{enumerable:!0});var Q=class extends ${constructor(e,s={}){super(e),this[Ps]=s.code===void 0?0:s.code,this[Ms]=s.reason===void 0?"":s.reason,this[Ds]=s.wasClean===void 0?!1:s.wasClean}get code(){return this[Ps]}get reason(){return this[Ms]}get wasClean(){return this[Ds]}};Object.defineProperty(Q.prototype,"code",{enumerable:!0});Object.defineProperty(Q.prototype,"reason",{enumerable:!0});Object.defineProperty(Q.prototype,"wasClean",{enumerable:!0});var _e=class extends ${constructor(e,s={}){super(e),this[ks]=s.error===void 0?null:s.error,this[Ls]=s.message===void 0?"":s.message}get error(){return this[ks]}get message(){return this[Ls]}};Object.defineProperty(_e.prototype,"error",{enumerable:!0});Object.defineProperty(_e.prototype,"message",{enumerable:!0});var Oe=class extends ${constructor(e,s={}){super(e),this[Rs]=s.data===void 0?null:s.data}get data(){return this[Rs]}};Object.defineProperty(Oe.prototype,"data",{enumerable:!0});var ti={addEventListener(t,e,s={}){for(let n of this.listeners(t))if(!s[ve]&&n[Ct]===e&&!n[ve])return;let r;if(t==="message")r=function(i,o){let a=new Oe("message",{data:o?i:i.toString()});a[me]=this,je(e,this,a)};else if(t==="close")r=function(i,o){let a=new Q("close",{code:i,reason:o.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});a[me]=this,je(e,this,a)};else if(t==="error")r=function(i){let o=new _e("error",{error:i,message:i.message});o[me]=this,je(e,this,o)};else if(t==="open")r=function(){let i=new $("open");i[me]=this,je(e,this,i)};else return;r[ve]=!!s[ve],r[Ct]=e,s.once?this.once(t,r):this.on(t,r)},removeEventListener(t,e){for(let s of this.listeners(t))if(s[Ct]===e&&!s[ve]){this.removeListener(t,s);break}}};Bs.exports={CloseEvent:Q,ErrorEvent:_e,Event:$,EventTarget:ti,MessageEvent:Oe};function je(t,e,s){typeof t=="object"&&t.handleEvent?t.handleEvent.call(t,s):t.call(e,s)}});var Ve=I((ma,Us)=>{"use strict";var{tokenChars:Ce}=de();function D(t,e,s){t[e]===void 0?t[e]=[s]:t[e].push(s)}function si(t){let e=Object.create(null),s=Object.create(null),r=!1,n=!1,i=!1,o,a,l=-1,c=-1,f=-1,d=0;for(;d<t.length;d++)if(c=t.charCodeAt(d),o===void 0)if(f===-1&&Ce[c]===1)l===-1&&(l=d);else if(d!==0&&(c===32||c===9))f===-1&&l!==-1&&(f=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d);let h=t.slice(l,f);c===44?(D(e,h,s),s=Object.create(null)):o=h,l=f=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);else if(a===void 0)if(f===-1&&Ce[c]===1)l===-1&&(l=d);else if(c===32||c===9)f===-1&&l!==-1&&(f=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d),D(s,t.slice(l,f),!0),c===44&&(D(e,o,s),s=Object.create(null),o=void 0),l=f=-1}else if(c===61&&l!==-1&&f===-1)a=t.slice(l,d),l=f=-1;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(n){if(Ce[c]!==1)throw new SyntaxError(`Unexpected character at index ${d}`);l===-1?l=d:r||(r=!0),n=!1}else if(i)if(Ce[c]===1)l===-1&&(l=d);else if(c===34&&l!==-1)i=!1,f=d;else if(c===92)n=!0;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(c===34&&t.charCodeAt(d-1)===61)i=!0;else if(f===-1&&Ce[c]===1)l===-1&&(l=d);else if(l!==-1&&(c===32||c===9))f===-1&&(f=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d);let h=t.slice(l,f);r&&(h=h.replace(/\\/g,""),r=!1),D(s,a,h),c===44&&(D(e,o,s),s=Object.create(null),o=void 0),a=void 0,l=f=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);if(l===-1||i||c===32||c===9)throw new SyntaxError("Unexpected end of input");f===-1&&(f=d);let u=t.slice(l,f);return o===void 0?D(e,u,s):(a===void 0?D(s,u,!0):r?D(s,a,u.replace(/\\/g,"")):D(s,a,u),D(e,o,s)),e}function ri(t){return Object.keys(t).map(e=>{let s=t[e];return Array.isArray(s)||(s=[s]),s.map(r=>[e].concat(Object.keys(r).map(n=>{let i=r[n];return Array.isArray(i)||(i=[i]),i.map(o=>o===!0?n:`${n}=${o}`).join("; ")})).join("; ")).join(", ")}).join(", ")}Us.exports={format:ri,parse:si}});var Ke=I((ga,Js)=>{"use strict";var ni=S("events"),ii=S("https"),oi=S("http"),Ys=S("net"),ai=S("tls"),{randomBytes:li,createHash:ci}=S("crypto"),{Duplex:_a,Readable:ya}=S("stream"),{URL:Pt}=S("url"),V=ue(),fi=At(),ui=Ot(),{isBlob:di}=de(),{BINARY_TYPES:Hs,CLOSE_TIMEOUT:hi,EMPTY_BUFFER:qe,GUID:pi,kForOnEventAttribute:Rt,kListener:mi,kStatusCode:_i,kWebSocket:E,NOOP:Ws}=U(),{EventTarget:{addEventListener:yi,removeEventListener:gi}}=Fs(),{format:Si,parse:xi}=Ve(),{toBuffer:Ei}=Ae(),Gs=Symbol("kAborted"),kt=[8,13],Y=["CONNECTING","OPEN","CLOSING","CLOSED"],bi=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,g=class t extends ni{constructor(e,s,r){super(),this._binaryType=Hs[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=qe,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=t.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,e!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,s===void 0?s=[]:Array.isArray(s)||(typeof s=="object"&&s!==null?(r=s,s=[]):s=[s]),js(this,e,s,r)):(this._autoPong=r.autoPong,this._closeTimeout=r.closeTimeout,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(e){Hs.includes(e)&&(this._binaryType=e,this._receiver&&(this._receiver._binaryType=e))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(e,s,r){let n=new fi({allowSynchronousEvents:r.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxBufferedChunks:r.maxBufferedChunks,maxFragments:r.maxFragments,maxPayload:r.maxPayload,skipUTF8Validation:r.skipUTF8Validation}),i=new ui(e,this._extensions,r.generateMask);this._receiver=n,this._sender=i,this._socket=e,n[E]=this,i[E]=this,e[E]=this,n.on("conclude",Ai),n.on("drain",Ii),n.on("error",vi),n.on("message",Oi),n.on("ping",Ci),n.on("pong",Pi),i.onerror=Ri,e.setTimeout&&e.setTimeout(0),e.setNoDelay&&e.setNoDelay(),s.length>0&&e.unshift(s),e.on("close",zs),e.on("data",Xe),e.on("end",Xs),e.on("error",Ks),this._readyState=t.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=t.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[V.extensionName]&&this._extensions[V.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=t.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(e,s){if(this.readyState!==t.CLOSED){if(this.readyState===t.CONNECTING){O(this,this._req,"WebSocket was closed before the connection was established");return}if(this.readyState===t.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=t.CLOSING,this._sender.close(e,s,!this._isServer,r=>{r||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),qs(this)}}pause(){this.readyState===t.CONNECTING||this.readyState===t.CLOSED||(this._paused=!0,this._socket.pause())}ping(e,s,r){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(r=e,e=s=void 0):typeof s=="function"&&(r=s,s=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){Lt(this,e,r);return}s===void 0&&(s=!this._isServer),this._sender.ping(e||qe,s,r)}pong(e,s,r){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(r=e,e=s=void 0):typeof s=="function"&&(r=s,s=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){Lt(this,e,r);return}s===void 0&&(s=!this._isServer),this._sender.pong(e||qe,s,r)}resume(){this.readyState===t.CONNECTING||this.readyState===t.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(e,s,r){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof s=="function"&&(r=s,s={}),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){Lt(this,e,r);return}let n={binary:typeof e!="string",mask:!this._isServer,compress:!0,fin:!0,...s};this._extensions[V.extensionName]||(n.compress=!1),this._sender.send(e||qe,n,r)}terminate(){if(this.readyState!==t.CLOSED){if(this.readyState===t.CONNECTING){O(this,this._req,"WebSocket was closed before the connection was established");return}this._socket&&(this._readyState=t.CLOSING,this._socket.destroy())}}};Object.defineProperty(g,"CONNECTING",{enumerable:!0,value:Y.indexOf("CONNECTING")});Object.defineProperty(g.prototype,"CONNECTING",{enumerable:!0,value:Y.indexOf("CONNECTING")});Object.defineProperty(g,"OPEN",{enumerable:!0,value:Y.indexOf("OPEN")});Object.defineProperty(g.prototype,"OPEN",{enumerable:!0,value:Y.indexOf("OPEN")});Object.defineProperty(g,"CLOSING",{enumerable:!0,value:Y.indexOf("CLOSING")});Object.defineProperty(g.prototype,"CLOSING",{enumerable:!0,value:Y.indexOf("CLOSING")});Object.defineProperty(g,"CLOSED",{enumerable:!0,value:Y.indexOf("CLOSED")});Object.defineProperty(g.prototype,"CLOSED",{enumerable:!0,value:Y.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(t=>{Object.defineProperty(g.prototype,t,{enumerable:!0})});["open","error","close","message"].forEach(t=>{Object.defineProperty(g.prototype,`on${t}`,{enumerable:!0,get(){for(let e of this.listeners(t))if(e[Rt])return e[mi];return null},set(e){for(let s of this.listeners(t))if(s[Rt]){this.removeListener(t,s);break}typeof e=="function"&&this.addEventListener(t,e,{[Rt]:!0})}})});g.prototype.addEventListener=yi;g.prototype.removeEventListener=gi;Js.exports=g;function js(t,e,s,r){let n={allowSynchronousEvents:!0,autoPong:!0,closeTimeout:hi,protocolVersion:kt[1],maxBufferedChunks:262144,maxFragments:16384,maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...r,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:"GET",host:void 0,path:void 0,port:void 0};if(t._autoPong=n.autoPong,t._closeTimeout=n.closeTimeout,!kt.includes(n.protocolVersion))throw new RangeError(`Unsupported protocol version: ${n.protocolVersion} (supported versions: ${kt.join(", ")})`);let i;if(e instanceof Pt)i=e;else try{i=new Pt(e)}catch{throw new SyntaxError(`Invalid URL: ${e}`)}i.protocol==="http:"?i.protocol="ws:":i.protocol==="https:"&&(i.protocol="wss:"),t._url=i.href;let o=i.protocol==="wss:",a=i.protocol==="ws+unix:",l;if(i.protocol!=="ws:"&&!o&&!a?l=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:a&&!i.pathname?l="The URL's pathname is empty":i.hash&&(l="The URL contains a fragment identifier"),l){let _=new SyntaxError(l);if(t._redirects===0)throw _;ze(t,_);return}let c=o?443:80,f=li(16).toString("base64"),d=o?ii.request:oi.request,u=new Set,h;if(n.createConnection=n.createConnection||(o?wi:Ti),n.defaultPort=n.defaultPort||c,n.port=i.port||c,n.host=i.hostname.startsWith("[")?i.hostname.slice(1,-1):i.hostname,n.headers={...n.headers,"Sec-WebSocket-Version":n.protocolVersion,"Sec-WebSocket-Key":f,Connection:"Upgrade",Upgrade:"websocket"},n.path=i.pathname+i.search,n.timeout=n.handshakeTimeout,n.perMessageDeflate&&(h=new V({...n.perMessageDeflate,isServer:!1,maxPayload:n.maxPayload}),n.headers["Sec-WebSocket-Extensions"]=Si({[V.extensionName]:h.offer()})),s.length){for(let _ of s){if(typeof _!="string"||!bi.test(_)||u.has(_))throw new SyntaxError("An invalid or duplicated subprotocol was specified");u.add(_)}n.headers["Sec-WebSocket-Protocol"]=s.join(",")}if(n.origin&&(n.protocolVersion<13?n.headers["Sec-WebSocket-Origin"]=n.origin:n.headers.Origin=n.origin),(i.username||i.password)&&(n.auth=`${i.username}:${i.password}`),a){let _=n.path.split(":");n.socketPath=_[0],n.path=_[1]}let m;if(n.followRedirects){if(t._redirects===0){t._originalIpc=a,t._originalSecure=o,t._originalHostOrSocketPath=a?n.socketPath:i.host;let _=r&&r.headers;if(r={...r,headers:{}},_)for(let[b,oe]of Object.entries(_))r.headers[b.toLowerCase()]=oe}else if(t.listenerCount("redirect")===0){let _=a?t._originalIpc?n.socketPath===t._originalHostOrSocketPath:!1:t._originalIpc?!1:i.host===t._originalHostOrSocketPath;(!_||t._originalSecure&&!o)&&(delete n.headers.authorization,delete n.headers.cookie,_||delete n.headers.host,n.auth=void 0)}n.auth&&!r.headers.authorization&&(r.headers.authorization="Basic "+Buffer.from(n.auth).toString("base64")),m=t._req=d(n),t._redirects&&t.emit("redirect",t.url,m)}else m=t._req=d(n);n.timeout&&m.on("timeout",()=>{O(t,m,"Opening handshake has timed out")}),m.on("error",_=>{m===null||m[Gs]||(m=t._req=null,ze(t,_))}),m.on("response",_=>{let b=_.headers.location,oe=_.statusCode;if(b&&n.followRedirects&&oe>=300&&oe<400){if(++t._redirects>n.maxRedirects){O(t,m,"Maximum redirects exceeded");return}m.abort();let be;try{be=new Pt(b,e)}catch{let ae=new SyntaxError(`Invalid URL: ${b}`);ze(t,ae);return}js(t,be,s,r)}else t.emit("unexpected-response",m,_)||O(t,m,`Unexpected server response: ${_.statusCode}`)}),m.on("upgrade",(_,b,oe)=>{if(t.emit("upgrade",_),t.readyState!==g.CONNECTING)return;m=t._req=null;let be=_.headers.upgrade;if(be===void 0||be.toLowerCase()!=="websocket"){O(t,b,"Invalid Upgrade header");return}let ss=ci("sha1").update(f+pi).digest("base64");if(_.headers["sec-websocket-accept"]!==ss){O(t,b,"Invalid Sec-WebSocket-Accept header");return}let ae=_.headers["sec-websocket-protocol"],Te;if(ae!==void 0?u.size?u.has(ae)||(Te="Server sent an invalid subprotocol"):Te="Server sent a subprotocol but none was requested":u.size&&(Te="Server sent no subprotocol"),Te){O(t,b,Te);return}ae&&(t._protocol=ae);let rs=_.headers["sec-websocket-extensions"];if(rs!==void 0){if(!h){O(t,b,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let ft;try{ft=xi(rs)}catch{O(t,b,"Invalid Sec-WebSocket-Extensions header");return}let ns=Object.keys(ft);if(ns.length!==1||ns[0]!==V.extensionName){O(t,b,"Server indicated an extension that was not requested");return}try{h.accept(ft[V.extensionName])}catch{O(t,b,"Invalid Sec-WebSocket-Extensions header");return}t._extensions[V.extensionName]=h}t.setSocket(b,oe,{allowSynchronousEvents:n.allowSynchronousEvents,generateMask:n.generateMask,maxBufferedChunks:n.maxBufferedChunks,maxFragments:n.maxFragments,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation})}),n.finishRequest?n.finishRequest(m,t):m.end()}function ze(t,e){t._readyState=g.CLOSING,t._errorEmitted=!0,t.emit("error",e),t.emitClose()}function Ti(t){return t.path=t.socketPath,Ys.connect(t)}function wi(t){return t.path=void 0,!t.servername&&t.servername!==""&&(t.servername=Ys.isIP(t.host)?"":t.host),ai.connect(t)}function O(t,e,s){t._readyState=g.CLOSING;let r=new Error(s);Error.captureStackTrace(r,O),e.setHeader?(e[Gs]=!0,e.abort(),e.socket&&!e.socket.destroyed&&e.socket.destroy(),process.nextTick(ze,t,r)):(e.destroy(r),e.once("error",t.emit.bind(t,"error")),e.once("close",t.emitClose.bind(t)))}function Lt(t,e,s){if(e){let r=di(e)?e.size:Ei(e).length;t._socket?t._sender._bufferedBytes+=r:t._bufferedAmount+=r}if(s){let r=new Error(`WebSocket is not open: readyState ${t.readyState} (${Y[t.readyState]})`);process.nextTick(s,r)}}function Ai(t,e){let s=this[E];s._closeFrameReceived=!0,s._closeMessage=e,s._closeCode=t,s._socket[E]!==void 0&&(s._socket.removeListener("data",Xe),process.nextTick(Vs,s._socket),t===1005?s.close():s.close(t,e))}function Ii(){let t=this[E];t.isPaused||t._socket.resume()}function vi(t){let e=this[E];e._socket[E]!==void 0&&(e._socket.removeListener("data",Xe),process.nextTick(Vs,e._socket),e.close(t[_i])),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",t))}function $s(){this[E].emitClose()}function Oi(t,e){this[E].emit("message",t,e)}function Ci(t){let e=this[E];e._autoPong&&e.pong(t,!this._isServer,Ws),e.emit("ping",t)}function Pi(t){this[E].emit("pong",t)}function Vs(t){t.resume()}function Ri(t){let e=this[E];e.readyState!==g.CLOSED&&(e.readyState===g.OPEN&&(e._readyState=g.CLOSING,qs(e)),this._socket.end(),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",t)))}function qs(t){t._closeTimer=setTimeout(t._socket.destroy.bind(t._socket),t._closeTimeout)}function zs(){let t=this[E];if(this.removeListener("close",zs),this.removeListener("data",Xe),this.removeListener("end",Xs),t._readyState=g.CLOSING,!this._readableState.endEmitted&&!t._closeFrameReceived&&!t._receiver._writableState.errorEmitted&&this._readableState.length!==0){let e=this.read(this._readableState.length);t._receiver.write(e)}t._receiver.end(),this[E]=void 0,clearTimeout(t._closeTimer),t._receiver._writableState.finished||t._receiver._writableState.errorEmitted?t.emitClose():(t._receiver.on("error",$s),t._receiver.on("finish",$s))}function Xe(t){this[E]._receiver.write(t)||this.pause()}function Xs(){let t=this[E];t._readyState=g.CLOSING,t._receiver.end(),this.end()}function Ks(){let t=this[E];this.removeListener("error",Ks),this.on("error",Ws),t&&(t._readyState=g.CLOSING,this.destroy())}});var tr=I((xa,er)=>{"use strict";var Sa=Ke(),{Duplex:ki}=S("stream");function Zs(t){t.emit("close")}function Li(){!this.destroyed&&this._writableState.finished&&this.destroy()}function Qs(t){this.removeListener("error",Qs),this.destroy(),this.listenerCount("error")===0&&this.emit("error",t)}function Mi(t,e){let s=!0,r=new ki({...e,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return t.on("message",function(i,o){let a=!o&&r._readableState.objectMode?i.toString():i;r.push(a)||t.pause()}),t.once("error",function(i){r.destroyed||(s=!1,r.destroy(i))}),t.once("close",function(){r.destroyed||r.push(null)}),r._destroy=function(n,i){if(t.readyState===t.CLOSED){i(n),process.nextTick(Zs,r);return}let o=!1;t.once("error",function(l){o=!0,i(l)}),t.once("close",function(){o||i(n),process.nextTick(Zs,r)}),s&&t.terminate()},r._final=function(n){if(t.readyState===t.CONNECTING){t.once("open",function(){r._final(n)});return}t._socket!==null&&(t._socket._writableState.finished?(n(),r._readableState.endEmitted&&r.destroy()):(t._socket.once("finish",function(){n()}),t.close()))},r._read=function(){t.isPaused&&t.resume()},r._write=function(n,i,o){if(t.readyState===t.CONNECTING){t.once("open",function(){r._write(n,i,o)});return}t.send(n,o)},r.on("end",Li),r.on("error",Qs),r}er.exports=Mi});var Mt=I((Ea,sr)=>{"use strict";var{tokenChars:Ni}=de();function Di(t){let e=new Set,s=-1,r=-1,n=0;for(n;n<t.length;n++){let o=t.charCodeAt(n);if(r===-1&&Ni[o]===1)s===-1&&(s=n);else if(n!==0&&(o===32||o===9))r===-1&&s!==-1&&(r=n);else if(o===44){if(s===-1)throw new SyntaxError(`Unexpected character at index ${n}`);r===-1&&(r=n);let a=t.slice(s,r);if(e.has(a))throw new SyntaxError(`The "${a}" subprotocol is duplicated`);e.add(a),s=r=-1}else throw new SyntaxError(`Unexpected character at index ${n}`)}if(s===-1||r!==-1)throw new SyntaxError("Unexpected end of input");let i=t.slice(s,n);if(e.has(i))throw new SyntaxError(`The "${i}" subprotocol is duplicated`);return e.add(i),e}sr.exports={parse:Di}});var cr=I((Ta,lr)=>{"use strict";var Bi=S("events"),Je=S("http"),{Duplex:ba}=S("stream"),{createHash:Fi}=S("crypto"),rr=Ve(),ee=ue(),Ui=Mt(),Hi=Ke(),{CLOSE_TIMEOUT:$i,GUID:Yi,kWebSocket:Wi}=U(),Gi=/^[+/0-9A-Za-z]{22}==$/,nr=0,ir=1,ar=2,Nt=class extends Bi{constructor(e,s){if(super(),e={allowSynchronousEvents:!0,autoPong:!0,maxBufferedChunks:256*1024,maxFragments:16*1024,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,closeTimeout:$i,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:Hi,...e},e.port==null&&!e.server&&!e.noServer||e.port!=null&&(e.server||e.noServer)||e.server&&e.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(e.port!=null?(this._server=Je.createServer((r,n)=>{let i=Je.STATUS_CODES[426];n.writeHead(426,{"Content-Length":i.length,"Content-Type":"text/plain"}),n.end(i)}),this._server.listen(e.port,e.host,e.backlog,s)):e.server&&(this._server=e.server),this._server){let r=this.emit.bind(this,"connection");this._removeListeners=ji(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(n,i,o)=>{this.handleUpgrade(n,i,o,r)}})}e.perMessageDeflate===!0&&(e.perMessageDeflate={}),e.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=e,this._state=nr}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(e){if(this._state===ar){e&&this.once("close",()=>{e(new Error("The server is not running"))}),process.nextTick(Pe,this);return}if(e&&this.once("close",e),this._state!==ir)if(this._state=ir,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients?this.clients.size?this._shouldEmitClose=!0:process.nextTick(Pe,this):process.nextTick(Pe,this);else{let s=this._server;this._removeListeners(),this._removeListeners=this._server=null,s.close(()=>{Pe(this)})}}shouldHandle(e){if(this.options.path){let s=e.url.indexOf("?");if((s!==-1?e.url.slice(0,s):e.url)!==this.options.path)return!1}return!0}handleUpgrade(e,s,r,n){s.on("error",or);let i=e.headers["sec-websocket-key"],o=e.headers.upgrade,a=+e.headers["sec-websocket-version"];if(e.method!=="GET"){te(this,e,s,405,"Invalid HTTP method");return}if(o===void 0||o.toLowerCase()!=="websocket"){te(this,e,s,400,"Invalid Upgrade header");return}if(i===void 0||!Gi.test(i)){te(this,e,s,400,"Missing or invalid Sec-WebSocket-Key header");return}if(a!==13&&a!==8){te(this,e,s,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"});return}if(!this.shouldHandle(e)){Re(s,400);return}let l=e.headers["sec-websocket-protocol"],c=new Set;if(l!==void 0)try{c=Ui.parse(l)}catch{te(this,e,s,400,"Invalid Sec-WebSocket-Protocol header");return}let f=e.headers["sec-websocket-extensions"],d={};if(this.options.perMessageDeflate&&f!==void 0){let u=new ee({...this.options.perMessageDeflate,isServer:!0,maxPayload:this.options.maxPayload});try{let h=rr.parse(f);h[ee.extensionName]&&(u.accept(h[ee.extensionName]),d[ee.extensionName]=u)}catch{te(this,e,s,400,"Invalid or unacceptable Sec-WebSocket-Extensions header");return}}if(this.options.verifyClient){let u={origin:e.headers[`${a===8?"sec-websocket-origin":"origin"}`],secure:!!(e.socket.authorized||e.socket.encrypted),req:e};if(this.options.verifyClient.length===2){this.options.verifyClient(u,(h,m,_,b)=>{if(!h)return Re(s,m||401,_,b);this.completeUpgrade(d,i,c,e,s,r,n)});return}if(!this.options.verifyClient(u))return Re(s,401)}this.completeUpgrade(d,i,c,e,s,r,n)}completeUpgrade(e,s,r,n,i,o,a){if(!i.readable||!i.writable)return i.destroy();if(i[Wi])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>nr)return Re(i,503);let c=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${Fi("sha1").update(s+Yi).digest("base64")}`],f=new this.options.WebSocket(null,void 0,this.options);if(r.size){let d=this.options.handleProtocols?this.options.handleProtocols(r,n):r.values().next().value;d&&(c.push(`Sec-WebSocket-Protocol: ${d}`),f._protocol=d)}if(e[ee.extensionName]){let d=e[ee.extensionName].params,u=rr.format({[ee.extensionName]:[d]});c.push(`Sec-WebSocket-Extensions: ${u}`),f._extensions=e}this.emit("headers",c,n),i.write(c.concat(`\r
5
5
  `).join(`\r
6
- `)),i.removeListener("error",or),f.setSocket(i,o,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxBufferedChunks:this.options.maxBufferedChunks,maxFragments:this.options.maxFragments,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(f),f.on("close",()=>{this.clients.delete(f),this._shouldEmitClose&&!this.clients.size&&process.nextTick(Pe,this)})),a(f,n)}};lr.exports=Mt;function $i(t,e){for(let s of Object.keys(e))t.on(s,e[s]);return function(){for(let r of Object.keys(e))t.removeListener(r,e[r])}}function Pe(t){t._state=ar,t.emit("close")}function or(){this.destroy()}function Re(t,e,s,r){s=s||Je.STATUS_CODES[e],r={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(s),...r},t.once("finish",t.destroy),t.end(`HTTP/1.1 ${e} ${Je.STATUS_CODES[e]}\r
6
+ `)),i.removeListener("error",or),f.setSocket(i,o,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxBufferedChunks:this.options.maxBufferedChunks,maxFragments:this.options.maxFragments,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(f),f.on("close",()=>{this.clients.delete(f),this._shouldEmitClose&&!this.clients.size&&process.nextTick(Pe,this)})),a(f,n)}};lr.exports=Nt;function ji(t,e){for(let s of Object.keys(e))t.on(s,e[s]);return function(){for(let r of Object.keys(e))t.removeListener(r,e[r])}}function Pe(t){t._state=ar,t.emit("close")}function or(){this.destroy()}function Re(t,e,s,r){s=s||Je.STATUS_CODES[e],r={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(s),...r},t.once("finish",t.destroy),t.end(`HTTP/1.1 ${e} ${Je.STATUS_CODES[e]}\r
7
7
  `+Object.keys(r).map(n=>`${n}: ${r[n]}`).join(`\r
8
8
  `)+`\r
9
9
  \r
10
- `+s)}function ee(t,e,s,r,n,i){if(t.listenerCount("wsClientError")){let o=new Error(n);Error.captureStackTrace(o,ee),t.emit("wsClientError",o,s,e)}else Re(s,r,n,i)}});import qo from"node:fs";import zo from"node:path";import hn from"node:fs";import mn from"node:os";import we from"node:path";var ae=we.resolve(import.meta.dirname,"..");function ht(){if(process.env.RELAY_STATE_DIR)return process.env.RELAY_STATE_DIR;let t=process.env.XDG_STATE_HOME||we.join(mn.homedir(),".local","state");return we.join(t,"herdr-remote-relay")}var x={relay:{mode:"remote",host:"127.0.0.1",port:8787,publicUrl:"http://127.0.0.1:8787",maxPayloadBytes:5*1024*1024,maxClientsPerHost:16,maxHosts:1024,maxPendingHandshakes:1024,maxBufferedBytesPerClient:4*1024*1024,allowedOrigins:[],trustProxy:!1,hostReconnectGraceMs:30*1e3},auth:{pairingTtlMs:600*1e3,deviceTtlMs:720*60*60*1e3,maxDevices:32,password:null,adminToken:null,stateFile:null},cleanup:{intervalMs:60*1e3,heartbeatIntervalMs:30*1e3,staleAfterMs:90*1e3}};function pn(t){return JSON.parse(JSON.stringify(t))}function _n(t){try{return JSON.parse(hn.readFileSync(t,"utf8"))}catch(e){let{code:s,message:r}=e;if(s==="ENOENT")return null;throw new Error(`cannot read relay config ${t}: ${r}`)}}function mt(t,e){if(t==null||t==="")return e;if(t===!0||t===!1)return t;let s=String(t).trim().toLowerCase();return["true","1","yes","on"].includes(s)?!0:["false","0","no","off"].includes(s)?!1:e}function I(t,e,s,r){let n=Number(t);return!Number.isInteger(n)||n<s||n>r?e:n}function os(t){return Array.isArray(t)?t.map(e=>String(e).trim()).filter(Boolean):typeof t!="string"?null:t.split(",").map(e=>e.trim()).filter(Boolean)}function dt(t,e){if(!e||typeof e!="object")return;let s=e;for(let r of Object.keys(t))s[r]!==void 0&&(t[r]=s[r])}function yn(t=[]){let e={},s=[],r=!1,n=!1;for(let i=0;i<t.length;i+=1){let o=t[i];if(o==="--help"||o==="-h"){r=!0;continue}if(o==="--version"||o==="-v"){n=!0;continue}if(!o.startsWith("--")){s.push(`unexpected argument: ${o}`);continue}let a=o.indexOf("="),l=a===-1?o.slice(2):o.slice(2,a),c=a===-1?void 0:o.slice(a+1);if(c===void 0){let f=t[i+1];f===void 0||f.startsWith("--")?c="true":(c=f,i+=1)}e[l]=c}return{options:e,help:r,version:n,errors:s}}function gn(t,e){if(!e||typeof e!="object")return;let s=e;dt(t.relay,s.relay),dt(t.auth,s.auth),dt(t.cleanup,s.cleanup)}function Sn(t,e){if((e.RELAY_DEPLOYMENT_MODE==="local"||e.RELAY_DEPLOYMENT_MODE==="remote")&&(t.relay.mode=e.RELAY_DEPLOYMENT_MODE),e.RELAY_BIND&&(t.relay.host=e.RELAY_BIND),e.RELAY_PORT&&(t.relay.port=e.RELAY_PORT),e.RELAY_PUBLIC_URL&&(t.relay.publicUrl=e.RELAY_PUBLIC_URL),e.RELAY_MAX_PAYLOAD_BYTES&&(t.relay.maxPayloadBytes=e.RELAY_MAX_PAYLOAD_BYTES),e.RELAY_MAX_CLIENTS_PER_HOST&&(t.relay.maxClientsPerHost=e.RELAY_MAX_CLIENTS_PER_HOST),e.RELAY_MAX_HOSTS&&(t.relay.maxHosts=e.RELAY_MAX_HOSTS),e.RELAY_MAX_PENDING_HANDSHAKES&&(t.relay.maxPendingHandshakes=e.RELAY_MAX_PENDING_HANDSHAKES),e.RELAY_MAX_BUFFERED_BYTES_PER_CLIENT&&(t.relay.maxBufferedBytesPerClient=e.RELAY_MAX_BUFFERED_BYTES_PER_CLIENT),e.RELAY_HOST_RECONNECT_GRACE_MS&&(t.relay.hostReconnectGraceMs=e.RELAY_HOST_RECONNECT_GRACE_MS),e.RELAY_ALLOWED_ORIGINS!==void 0){let s=os(e.RELAY_ALLOWED_ORIGINS);s&&(t.relay.allowedOrigins=s)}e.RELAY_TRUST_PROXY!==void 0&&(t.relay.trustProxy=mt(e.RELAY_TRUST_PROXY,t.relay.trustProxy)),e.RELAY_PASSWORD&&(t.auth.password=e.RELAY_PASSWORD),e.RELAY_ADMIN_TOKEN&&(t.auth.adminToken=e.RELAY_ADMIN_TOKEN),e.RELAY_AUTH_STATE_FILE&&(t.auth.stateFile=e.RELAY_AUTH_STATE_FILE),e.RELAY_PAIRING_TTL_MS&&(t.auth.pairingTtlMs=e.RELAY_PAIRING_TTL_MS),e.RELAY_DEVICE_TTL_MS&&(t.auth.deviceTtlMs=e.RELAY_DEVICE_TTL_MS),e.RELAY_MAX_DEVICES&&(t.auth.maxDevices=e.RELAY_MAX_DEVICES)}function xn(t,e){if((e["deployment-mode"]==="local"||e["deployment-mode"]==="remote")&&(t.relay.mode=e["deployment-mode"]),e.bind&&(t.relay.host=e.bind),e.port&&(t.relay.port=e.port),e["public-url"]&&(t.relay.publicUrl=e["public-url"]),e["allowed-origins"]!==void 0){let s=os(e["allowed-origins"]);s&&(t.relay.allowedOrigins=s)}e["trust-proxy"]!==void 0&&(t.relay.trustProxy=mt(e["trust-proxy"],t.relay.trustProxy)),e.password&&(t.auth.password=e.password),e["admin-token"]&&(t.auth.adminToken=e["admin-token"]),e["state-file"]&&(t.auth.stateFile=e["state-file"]),e["max-clients"]&&(t.relay.maxClientsPerHost=e["max-clients"]),e["max-hosts"]&&(t.relay.maxHosts=e["max-hosts"]),e["max-pending-handshakes"]&&(t.relay.maxPendingHandshakes=e["max-pending-handshakes"]),e["max-buffered-bytes"]&&(t.relay.maxBufferedBytesPerClient=e["max-buffered-bytes"]),e["host-reconnect-grace-ms"]&&(t.relay.hostReconnectGraceMs=e["host-reconnect-grace-ms"])}function En(t){return t.relay.mode!=="local"&&t.relay.mode!=="remote"&&(t.relay.mode=x.relay.mode),t.relay.port=I(t.relay.port,x.relay.port,0,65535),t.relay.maxPayloadBytes=I(t.relay.maxPayloadBytes,x.relay.maxPayloadBytes,4096,16*1024*1024),t.relay.maxClientsPerHost=I(t.relay.maxClientsPerHost,x.relay.maxClientsPerHost,1,256),t.relay.maxHosts=I(t.relay.maxHosts,x.relay.maxHosts,1,1e5),t.relay.maxPendingHandshakes=I(t.relay.maxPendingHandshakes,x.relay.maxPendingHandshakes,16,1e5),t.relay.maxBufferedBytesPerClient=I(t.relay.maxBufferedBytesPerClient,x.relay.maxBufferedBytesPerClient,64*1024,256*1024*1024),t.relay.hostReconnectGraceMs=I(t.relay.hostReconnectGraceMs,x.relay.hostReconnectGraceMs,1e3,1440*60*1e3),t.auth.pairingTtlMs=I(t.auth.pairingTtlMs,x.auth.pairingTtlMs,30*1e3,1440*60*1e3),t.auth.deviceTtlMs=I(t.auth.deviceTtlMs,x.auth.deviceTtlMs,60*1e3,365*24*60*60*1e3),t.auth.maxDevices=I(t.auth.maxDevices,x.auth.maxDevices,1,1e4),t.cleanup.intervalMs=I(t.cleanup.intervalMs,x.cleanup.intervalMs,1e3,1440*60*1e3),t.cleanup.heartbeatIntervalMs=I(t.cleanup.heartbeatIntervalMs,x.cleanup.heartbeatIntervalMs,1e3,600*1e3),t.cleanup.staleAfterMs=I(t.cleanup.staleAfterMs,x.cleanup.staleAfterMs,t.cleanup.heartbeatIntervalMs*2,1440*60*1e3),(typeof t.relay.host!="string"||t.relay.host.length===0)&&(t.relay.host=x.relay.host),(typeof t.relay.publicUrl!="string"||t.relay.publicUrl.length===0)&&(t.relay.publicUrl=`http://${t.relay.host}:${t.relay.port}`),t.relay.publicUrl=String(t.relay.publicUrl).replace(/\/+$/,""),Array.isArray(t.relay.allowedOrigins)||(t.relay.allowedOrigins=[]),t.relay.trustProxy=mt(t.relay.trustProxy,!1),t.auth.stateFile||(t.auth.stateFile=we.join(ht(),"relay-auth.json")),t}function bn(t){let e=[],s=["127.0.0.1","localhost","::1"].includes(t.relay.host),r;try{r=new URL(t.relay.publicUrl)}catch{e.push(`publicUrl is not a valid URL: ${t.relay.publicUrl}`)}return t.auth.password||e.push("no password set (RELAY_PASSWORD): this is a public relay, anyone may connect a workstation to it"),t.relay.mode==="remote"&&!t.auth.adminToken&&e.push("no admin token set (RELAY_ADMIN_TOKEN): the relay operator dashboard is unavailable"),!s&&r&&r.protocol==="http:"&&!["127.0.0.1","localhost"].includes(r.hostname)&&e.push(`publicUrl uses plain http on a non-loopback address (${t.relay.publicUrl}); terminate TLS in front of the relay`),e}function Be({argv:t=[],env:e=process.env}={}){let{options:s,help:r,version:n,errors:i}=yn(t),o=pn(x),a=s.config||e.HERDR_RELAY_CONFIG||null;if(a){let c=_n(we.resolve(a));if(c===null)throw new Error(`relay config not found: ${a}`);gn(o,c)}Sn(o,e),xn(o,s);let l=En(o);return{config:l,help:r,version:n,errors:i,configFile:a,warnings:bn(l)}}import jo from"node:http";import ts from"node:path";import{URL as Vo}from"node:url";var Wi=G(tr(),1),Gi=G(Ve(),1),ji=G(fe(),1),Vi=G(At(),1),qi=G(Ot(),1),zi=G(Nt(),1),T=G(Ke(),1),Dt=G(cr(),1);import Ft from"node:crypto";import Ki from"node:path";import fr from"node:crypto";import te from"node:fs";import Xi from"node:path";function ke(t){te.mkdirSync(t,{recursive:!0,mode:448});try{te.chmodSync(t,448)}catch{}}function ur(t,e){ke(Xi.dirname(t));let s=`${t}.${process.pid}.${fr.randomBytes(4).toString("hex")}.tmp`;te.writeFileSync(s,`${JSON.stringify(e,null,2)}
11
- `,{mode:384});try{te.chmodSync(s,384)}catch{}te.renameSync(s,t);try{te.chmodSync(t,384)}catch{}}function dr(t,e){try{return JSON.parse(te.readFileSync(t,"utf8"))}catch(s){let{code:r,message:n}=s;return r!=="ENOENT"&&process.stderr.write(`herdr-remote: invalid state at ${t}: ${n}
12
- `),e}}function Bt(t=32){return fr.randomBytes(t).toString("base64url")}function B(t){return Ft.createHash("sha256").update(String(t),"utf8").digest("hex")}function _e(t,e){if(typeof t!="string"||typeof e!="string")return!1;let s=Buffer.from(t,"hex"),r=Buffer.from(e,"hex");return s.length===r.length&&s.length>0&&Ft.timingSafeEqual(s,r)}function U(t=Date.now()){return new Date(t).toISOString()}function Ut(t){return typeof t=="string"&&/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(t)}var hr="ABCDEFGHJKMNPQRSTUVWXYZ23456789",Ji=6;function Zi(){let t="";for(let e=0;e<Ji;e+=1)t+=hr[Ft.randomInt(hr.length)];return t}var Ze=class{stateFile;pairingTtlMs;deviceTtlMs;maxDevices;password;pairings=new Map;lastDeviceSaveAt=new Map;state;constructor({stateFile:e,pairingTtlMs:s=600*1e3,deviceTtlMs:r=720*60*60*1e3,maxDevices:n=32,password:i=null}={}){if(!e)throw new TypeError("stateFile is required");this.stateFile=e,this.pairingTtlMs=s,this.deviceTtlMs=r,this.maxDevices=n,this.password=i||null,this.state=dr(e,{version:1,hosts:{},devices:{}}),this.state.version=1,this.state.hosts=this.state.hosts&&typeof this.state.hosts=="object"?this.state.hosts:{},this.state.devices=this.state.devices&&typeof this.state.devices=="object"?this.state.devices:{},ke(Ki.dirname(e))}save(){ur(this.stateFile,this.state)}checkPassword(e){return this.password?typeof e=="string"&&_e(B(e),B(this.password)):!0}registerHost(e,s,r=null,n=Date.now()){if(!Ut(e)||typeof s!="string"||s.length<16||s.length>4096)return{ok:!1,code:"invalid_host_credentials",message:"hostId and token are required"};if(!this.checkPassword(r))return{ok:!1,code:"relay_password_required",message:"the relay password is missing or wrong"};let i=this.state.hosts[e];return i?_e(i.tokenHash,B(s))?(i.lastSeenAt=U(n),this.save(),{ok:!0,hostId:e,firstSeen:!1}):{ok:!1,code:"host_auth_failed",message:"host token is invalid"}:(this.state.hosts[e]={tokenHash:B(s),createdAt:U(n),lastSeenAt:U(n)},this.save(),{ok:!0,hostId:e,firstSeen:!0})}authenticateHost(e,s){if(!Ut(e)||typeof s!="string"||s.length<16||s.length>4096)return!1;let r=this.state.hosts[e];return!!r&&_e(r.tokenHash,B(s))}hostCount(){return Object.keys(this.state.hosts).length}startPairing(e,s,r=Date.now()){if(!Ut(e)||!this.state.hosts[e])throw Object.assign(new Error("host is not connected or enrolled"),{code:"host_not_found"});this.cleanup(r);let n;do n=Zi();while([...this.pairings.values()].some(o=>_e(o.codeHash,B(n))));let i=r+this.pairingTtlMs;return this.pairings.set(n,{codeHash:B(n),hostId:e,expiresAt:i,publicUrl:s}),{code:n,hostId:e,publicUrl:s,expiresAt:i,expiresAtIso:U(i)}}completePairing(e,s=Date.now()){if(typeof e!="string"||e.length<4||e.length>32)return null;this.cleanup(s);let r=e.trim().toUpperCase(),n=this.pairings.get(r);if(!n||n.expiresAt<=s||!_e(n.codeHash,B(r)))return null;this.pairings.delete(r);let i=Object.values(this.state.devices);i.length>=this.maxDevices&&(i.sort((c,f)=>(c.lastSeenAt||"").localeCompare(f.lastSeenAt||"")),delete this.state.devices[i[0].deviceId]);let o=`device-${Bt(9)}`,a=Bt(32),l=s+this.deviceTtlMs;return this.state.devices[o]={deviceId:o,hostId:n.hostId,tokenHash:B(a),createdAt:U(s),lastSeenAt:U(s),expiresAt:l},this.save(),{deviceId:o,hostId:n.hostId,token:a,expiresAt:l,expiresAtIso:U(l),publicUrl:n.publicUrl}}noteDeviceSeen(e,{userAgent:s,ip:r}={},n=Date.now()){let i=this.state.devices[e];if(!i)return null;let o=!1;return s&&i.userAgent!==s&&(i.userAgent=String(s).slice(0,256),o=!0),r&&i.lastIp!==r&&(i.lastIp=String(r).slice(0,64),o=!0),i.lastSeenAt=U(n),o&&this.save(),{...i}}listDevices(e=Date.now()){return Object.values(this.state.devices).filter(s=>s&&s.expiresAt>e).map(s=>({deviceId:s.deviceId,hostId:s.hostId,createdAt:s.createdAt,lastSeenAt:s.lastSeenAt,expiresAt:s.expiresAt,expiresAtIso:U(s.expiresAt),userAgent:s.userAgent||null,lastIp:s.lastIp||null})).sort((s,r)=>String(r.lastSeenAt||"").localeCompare(String(s.lastSeenAt||"")))}revokeDevice(e){if(typeof e!="string"||!e)return null;let s=this.state.devices[e];return s?(delete this.state.devices[e],this.lastDeviceSaveAt.delete(e),this.save(),{deviceId:s.deviceId,hostId:s.hostId,userAgent:s.userAgent||null,lastIp:s.lastIp||null}):null}authenticateDevice(e,s=Date.now()){if(typeof e!="string"||e.length<16)return null;let r=B(e);for(let n of Object.values(this.state.devices)){if(n.expiresAt<=s||!_e(n.tokenHash,r))continue;n.lastSeenAt=U(s),n.expiresAt=s+this.deviceTtlMs;let i=this.lastDeviceSaveAt.get(n.deviceId)||0;return s-i>=60*1e3&&(this.lastDeviceSaveAt.set(n.deviceId,s),this.save()),{...n}}return null}cleanup(e=Date.now()){let s=0;for(let[n,i]of Object.entries(this.state.devices))(!i||i.expiresAt<=e)&&(delete this.state.devices[n],this.lastDeviceSaveAt.delete(n),s+=1);let r=0;for(let[n,i]of this.pairings.entries())i.expiresAt<=e&&(this.pairings.delete(n),r+=1);return s&&this.save(),{removedDevices:s,removedPairings:r}}deviceCount(){return Object.keys(this.state.devices).length}};import Qe from"node:os";import{monitorEventLoopDelay as Qi}from"node:perf_hooks";function et(t,e=0){return Number.isFinite(t)?t:e}function q(t,e,s){return!s||s<=0?0:Math.max(0,(t-e)*1e3/s)}function st(t=[]){let e=new Set;for(let s of t)s&&e.add(typeof s.deviceId=="string"&&s.deviceId?`device:${s.deviceId}`:`client:${s.id}`);return e.size}var tt=class{version;protocolVersion;startedAt;bytesIn;bytesOut;framesIn;framesOut;cleanup;lastSample;hostTraffic;cpuSampleAt;cpuSample;eventLoop;constructor({version:e="0.1.0",protocolVersion:s=1}={}){this.version=e,this.protocolVersion=s,this.startedAt=Date.now(),this.bytesIn=0,this.bytesOut=0,this.framesIn=0,this.framesOut=0,this.cleanup={staleClientsPurged:0,closedPtysCleaned:0,deadConnectionsClosed:0,idleHostsTerminated:0,slowClientsDropped:0,lastCleanupAt:null},this.lastSample={at:this.startedAt,bytesIn:0,bytesOut:0,framesIn:0,framesOut:0},this.hostTraffic=new Map,this.cpuSampleAt=process.hrtime.bigint(),this.cpuSample=process.cpuUsage(),this.eventLoop=Qi({resolution:20}),this.eventLoop.enable()}hostCounter(e){if(typeof e!="string"||e.length===0)return null;let s=this.hostTraffic.get(e);return s||(s={bytesIn:0,bytesOut:0,framesIn:0,framesOut:0,sampleAt:Date.now(),sampleBytesIn:0,sampleBytesOut:0,sampleFramesIn:0,sampleFramesOut:0},this.hostTraffic.set(e,s)),s}recordIn(e,s=null){let r=Math.max(0,Number(e)||0);this.bytesIn+=r,this.framesIn+=1;let n=this.hostCounter(s);n&&(n.bytesIn+=r,n.framesIn+=1)}recordOut(e,s=null){let r=Math.max(0,Number(e)||0);this.bytesOut+=r,this.framesOut+=1;let n=this.hostCounter(s);n&&(n.bytesOut+=r,n.framesOut+=1)}forgetHost(e){typeof e=="string"&&this.hostTraffic.delete(e)}hostThroughput(e,s=Date.now()){let r=this.hostCounter(e);if(!r)return{bytesIn:0,bytesOut:0,bytesInPerSec:0,bytesOutPerSec:0,framesIn:0,framesOut:0,framesInPerSec:0,framesOutPerSec:0};let n=s-r.sampleAt,i={bytesIn:r.bytesIn,bytesOut:r.bytesOut,bytesInPerSec:q(r.bytesIn,r.sampleBytesIn,n),bytesOutPerSec:q(r.bytesOut,r.sampleBytesOut,n),framesIn:r.framesIn,framesOut:r.framesOut,framesInPerSec:q(r.framesIn,r.sampleFramesIn,n),framesOutPerSec:q(r.framesOut,r.sampleFramesOut,n)};return r.sampleAt=s,r.sampleBytesIn=r.bytesIn,r.sampleBytesOut=r.bytesOut,r.sampleFramesIn=r.framesIn,r.sampleFramesOut=r.framesOut,i}recordCleanup(e,s=1){Object.hasOwn(this.cleanup,e)&&typeof this.cleanup[e]=="number"&&(this.cleanup[e]+=s),this.cleanup.lastCleanupAt=new Date().toISOString()}cpuPercent(){let e=process.hrtime.bigint(),s=Number(e-this.cpuSampleAt),r=process.cpuUsage(this.cpuSample);if(this.cpuSampleAt=e,this.cpuSample=process.cpuUsage(),s<=0)return 0;let n=(r.user+r.system)*1e5/s;return Math.max(0,Math.round(n*100)/100)}eventLoopDelay(){let e=s=>Math.round(et(s/1e6)*100)/100;return{p50Ms:e(this.eventLoop.percentile(50)),p90Ms:e(this.eventLoop.percentile(90)),p99Ms:e(this.eventLoop.percentile(99)),maxMs:e(this.eventLoop.max),meanMs:e(this.eventLoop.mean)}}snapshot({clients:e=[],hosts:s=[],ptys:r=[],sample:n=!0,scopeHostId:i=null,activeUserCount:o=null}={}){let a=Date.now(),l=a-this.lastSample.at,c={bytesIn:this.bytesIn,bytesOut:this.bytesOut,bytesInPerSec:q(this.bytesIn,this.lastSample.bytesIn,l),bytesOutPerSec:q(this.bytesOut,this.lastSample.bytesOut,l),framesIn:this.framesIn,framesOut:this.framesOut,framesInPerSec:q(this.framesIn,this.lastSample.framesIn,l),framesOutPerSec:q(this.framesOut,this.lastSample.framesOut,l)};n&&(this.lastSample={at:a,bytesIn:this.bytesIn,bytesOut:this.bytesOut,framesIn:this.framesIn,framesOut:this.framesOut});let f=process.memoryUsage(),d=Qe.loadavg(),u=e[0],h=i?this.hostThroughput(i,a):c;return{version:this.version,protocolVersion:this.protocolVersion,uptimeSeconds:Math.floor((a-this.startedAt)/1e3),startTime:new Date(this.startedAt).toISOString(),serverTime:new Date(a).toISOString(),activeControllerId:null,activeHostId:u?.hostId||s[0]?.id||null,clients:e,hosts:s,ptys:r,clientCount:e.length,hostCount:s.length,ptyCount:r.length,activeUserCount:Number.isFinite(o)?o:st(e),throughput:h,cpu:{load1m:et(d[0]),load5m:et(d[1]),load15m:et(d[2]),cpuPercent:this.cpuPercent(),cores:Qe.cpus().length},memory:{rssBytes:f.rss,heapUsedBytes:f.heapUsed,heapTotalBytes:f.heapTotal,externalBytes:f.external,systemTotalBytes:Qe.totalmem(),systemFreeBytes:Qe.freemem()},eventLoopDelay:this.eventLoopDelay(),cleanup:{...this.cleanup}}}close(){this.eventLoop.disable(),this.hostTraffic.clear()}};function Le(t){return Buffer.isBuffer(t)?t:(typeof t=="string"||t instanceof ArrayBuffer,Buffer.from(t))}function mr(t,e,s=Buffer.alloc(0)){if(typeof t!="string"||!t||typeof e!="string"||!e)throw new TypeError("type and streamId must be non-empty strings");let r=Le(s),n=Buffer.from(JSON.stringify({type:t,streamId:e}),"utf8");if(n.length>8192)throw new RangeError("stream frame header is too large");let i=Buffer.allocUnsafe(4);return i.writeUInt32BE(n.length,0),Buffer.concat([i,n,r])}function eo(t){let e=Le(t);if(e.length<4)throw new Error("stream frame is truncated");let s=e.readUInt32BE(0);if(s===0||s>8192||e.length<4+s)throw new Error("stream frame header is invalid");let r;try{r=JSON.parse(e.subarray(4,4+s).toString("utf8"))}catch(n){throw new Error(`stream frame header is not JSON: ${n.message}`)}if(!r||typeof r.type!="string"||typeof r.streamId!="string")throw new Error("stream frame header is missing routing fields");return{version:1,type:r.type,streamId:r.streamId,payload:e.subarray(4+s)}}function pr(t,e,s=Buffer.alloc(0)){let r=t;if(t==="output"?r=0:t==="input"&&(r=1),r!==0&&r!==1)throw new TypeError("type must be FRAME_TYPE_OUTPUT (0) or FRAME_TYPE_INPUT (1)");if(!Number.isInteger(e)||e<0||e>65535)throw new RangeError("streamIndex must be an unsigned 16-bit integer (0-65535)");let n=Le(s),i=Buffer.allocUnsafe(4+n.length);return i.writeUInt8(255,0),i.writeUInt8(r,1),i.writeUInt16BE(e,2),n.copy(i,4),i}function to(t){let e=Le(t);if(e.length<4)throw new Error("v2 stream frame is truncated");if(e.readUInt8(0)!==255)throw new Error("invalid v2 stream frame magic byte");let r=e.readUInt8(1);if(r!==0&&r!==1)throw new Error(`unknown v2 stream frame type: ${r}`);let n=e.readUInt16BE(2);return{version:2,type:r===0?"output":"input",typeCode:r,streamIndex:n,payload:e.subarray(4)}}function _r(t){let e=Le(t);if(e.length<4)throw new Error("stream frame is truncated");return e[0]===255?to(e):eo(e)}var yr=["black","red","green","yellow","blue","magenta","cyan","white","brightBlack","brightRed","brightGreen","brightYellow","brightBlue","brightMagenta","brightCyan","brightWhite"],so=["regular","bold","italic","boldItalic"],ro=["truetype","opentype"],no=["cjk","all"];var io=/^#[0-9a-f]{6}$/i,oo=/["'\\;,{}<>@\u0000-\u001f\u007f]/,gr=/^[0-9a-f]{64}$/;function Ne(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function Ht(t,e){return t.includes(e)}function Sr(t){return typeof t=="string"&&io.test(t)?t.toLowerCase():void 0}function Er(t){if(!Ne(t))return null;let e={};for(let r of["background","foreground","cursor"]){let n=Sr(t[r]);n&&(e[r]=n)}let s=t.ansi;if(Ne(s)){let r={};for(let n of yr){let i=Sr(s[n]);i&&(r[n]=i)}Object.keys(r).length===yr.length&&(e.ansi=r)}return Object.keys(e).length>0?e:null}function xr(t){let e=typeof t=="string"?t.trim():"";return!e||e.length>128||oo.test(e)?null:e}function rt(t){if(!Ne(t))return null;let e=xr(t.family);if(!e)return null;let s=Number(t.sizePx),r=Number.isFinite(s)&&s>=4&&s<=96?Math.round(s*10)/10:null,n=typeof t.source=="string"&&/^[a-z0-9-]{1,32}$/.test(t.source)?t.source:null,i=[],o=new Set;for(let l of Array.isArray(t.faces)?t.faces.slice(0,16):[]){if(!Ne(l))continue;let{style:c,format:f,bytes:d,sha256:u}=l;!Ht(so,c)||o.has(c)||Ht(ro,f)&&(typeof d!="number"||!Number.isInteger(d)||d<=0||d>16777216||typeof u!="string"||!gr.test(u)||(o.add(c),i.push({style:c,format:f,bytes:d,sha256:u})))}let a=[];for(let l of Array.isArray(t.subsets)?t.subsets.slice(0,16):[]){if(!Ne(l))continue;let c=xr(l.family),{scope:f,sha256:d}=l;!c||l.style!=="regular"||Ht(no,f)&&(typeof d!="string"||!gr.test(d)||a.some(u=>u.scope===f)||a.push({family:c,style:"regular",scope:f,sha256:d}))}return{family:e,...r!==null&&{sizePx:r},...n!==null&&{source:n},faces:i,subsets:a}}var ao=/^[\x21-\x7e]+$/;function br(t){if(!Array.isArray(t))return;let e=new Set;for(let s of t){if(e.size>=8)break;if(typeof s!="string")continue;let r=s.replace(/\s+/g,"").toLowerCase();r.length<=32&&ao.test(r)&&e.add(r)}return e.size>0?[...e]:void 0}var Yt="/ws/host",Tr="/ws/client",ye={hostHandoff:"host_handoff",idleHeartbeat:"idle_heartbeat",binaryFrameV2:"binary_frame_v2",adminTabs:"admin_tabs"};var wr={"image/png":".png","image/jpeg":".jpg","image/webp":".webp","image/gif":".gif"},Da=Object.keys(wr);function Ar(t){return typeof t=="string"&&Object.hasOwn(wr,t)}function vr(t,e){switch(t){case"image/png":return e.length>=8&&e[0]===137&&e[1]===80&&e[2]===78&&e[3]===71;case"image/jpeg":return e.length>=3&&e[0]===255&&e[1]===216&&e[2]===255;case"image/webp":return e.length>=12&&e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70&&e[8]===87&&e[9]===69&&e[10]===66&&e[11]===80;case"image/gif":return e.length>=6&&e[0]===71&&e[1]===73&&e[2]===70&&e[3]===56;default:return!1}}var lo="dibin666/herdr-remote",Ir=`https://github.com/${lo}/releases`,Ua=`${Ir}/latest/download/latest.json`,Fa=`${Ir}/latest/download/herdr-remote.tgz`;import co from"node:crypto";var fo=500;function ge(t){return`${t}-${co.randomBytes(9).toString("base64url")}`}function z(t,e){return typeof t=="string"&&t.length>0?t.slice(0,e):null}function Me(t,e){let s=Number(t);return Number.isInteger(s)?Math.min(fo,Math.max(2,s)):e}function y(t){return!!t&&t?.readyState===T.default.OPEN}function m(t,e){y(t)&&t.send(JSON.stringify(e))}function k(t,e=1e3,s=""){if(!(!t||t.readyState===T.default.CLOSED||t.readyState===T.default.CLOSING))try{t.close(e,s.slice(0,120))}catch{}}function se(t){if(!(!t||t.readyState===T.default.CLOSED))try{typeof t.terminate=="function"?t.terminate():typeof t.destroy=="function"&&t.destroy()}catch{}}function Se(t){if(typeof t!="string")return null;try{return JSON.parse(t)}catch{return null}}function w(t,e,s="invalid_handshake"){m(t,{type:"error",code:s,message:e}),k(t,1008,e)}var Cr=4,Pr=3e4,Rr=Math.ceil(262144/3)*4,$t=/^[0-9a-f]{64}$/,uo=32*1024,ho=64,mo=16*1024*1024,kr=/^[A-Za-z0-9_-]{1,32}$/;function Wt(t){Array.isArray(t.fontChunkRequests)&&t.fontChunkRequests.length&&t.fontChunkRequests.shift()}function nt(t){Array.isArray(t.fontSubsetRequests)&&t.fontSubsetRequests.length&&t.fontSubsetRequests.shift()}function Lr(t,e,s){if(!e.session||!y(t.ws))return;let r=t.terminalFont?.faces?.find(a=>a.sha256===s.sha256),n=r?r.bytes:e.fontSubsets?.get(s.sha256)||0,i=Math.ceil(n/262144);if(!n||!Number.isInteger(s.index)||s.index<0||s.index>=i){m(e.ws,{type:"error",code:"host_font_unavailable",message:"The workstation did not offer this font file"});return}let o=Date.now();e.fontChunkRequests=(e.fontChunkRequests||[]).filter(a=>o-a<Pr),!(e.fontChunkRequests.length>=Cr)&&(e.fontChunkRequests.push(o),m(t.ws,{type:"host_font_chunk_request",clientId:e.session.streamId,streamId:e.session.streamId,sha256:s.sha256,index:s.index}))}function Nr(t,e,s){if(!e.session||!y(t.ws))return;if(!(t.terminalFont?.subsets?.some(o=>o.sha256===s.sha256)&&typeof s.text=="string"&&s.text.length>0&&s.text.length<=uo&&typeof s.requestId=="string"&&kr.test(s.requestId))){m(e.ws,{type:"error",code:"host_font_unavailable",message:"The workstation did not offer this font"});return}let i=Date.now();e.fontSubsetRequests=(e.fontSubsetRequests||[]).filter(o=>i-o<Pr),!(e.fontSubsetRequests.length>=Cr)&&(e.fontSubsetRequests.push(i),m(t.ws,{type:"host_font_subset_request",clientId:e.session.streamId,streamId:e.session.streamId,requestId:s.requestId,sha256:s.sha256,text:s.text}))}function Mr(t,e){if(nt(t),!!(typeof e.sha256=="string"&&$t.test(e.sha256)&&typeof e.subsetSha=="string"&&$t.test(e.subsetSha)&&typeof e.requestId=="string"&&kr.test(e.requestId)&&Number.isInteger(e.bytes)&&e.bytes>0&&e.bytes<=mo&&(e.dataBase64===void 0||typeof e.dataBase64=="string"&&e.dataBase64.length<=Rr))){if(e.dataBase64===void 0)for(t.fontSubsets||=new Map,t.fontSubsets.delete(e.subsetSha),t.fontSubsets.set(e.subsetSha,e.bytes);t.fontSubsets.size>ho;){let r=t.fontSubsets.keys().next().value;r!==void 0&&t.fontSubsets.delete(r)}m(t.ws,{type:"host_font_subset_ready",requestId:e.requestId,sha256:e.sha256,subsetSha:e.subsetSha,bytes:e.bytes,...e.dataBase64!==void 0?{dataBase64:e.dataBase64}:{}})}}function Dr(t,e){Wt(t),typeof e.sha256=="string"&&$t.test(e.sha256)&&Number.isInteger(e.index)&&e.index>=0&&Number.isInteger(e.total)&&e.total>e.index&&typeof e.dataBase64=="string"&&e.dataBase64.length<=Rr&&m(t.ws,{type:"host_font_chunk",sha256:e.sha256,index:e.index,total:e.total,dataBase64:e.dataBase64})}import Gt from"node:crypto";function po(t){let e=t.headers.authorization;if(typeof e!="string")return null;let s=/^Bearer\s+(.+)$/i.exec(e.trim());return s?s[1]:null}function _o(t,e){if(typeof t!="string"||t.length===0||typeof e!="string"||e.length===0)return!1;let s=Gt.createHash("sha256").update(t,"utf8").digest(),r=Gt.createHash("sha256").update(e,"utf8").digest();return Gt.timingSafeEqual(s,r)}function jt(t,e,s){if(!e||(t.config.relay.allowedOrigins||[]).includes(e))return!0;try{return new URL(e).host===s.headers.host}catch{return!1}}function Br(t,e){let s=e.headers.origin;return s?jt(t,s,e):!0}function Vt(t,e){let s=e.headers["x-herdr-host-id"],r=e.headers["x-herdr-host-token"];return typeof s!="string"||typeof r!="string"?null:t.auth.authenticateHost(s,r)?s:null}function yo(t,e){let s=po(e);return s?t.auth.authenticateDevice(s):null}function Ur(t,e){let s=e.headers["x-herdr-host-id"],r=e.headers["x-herdr-host-token"],n=s!==void 0||r!==void 0,i=e.headers.authorization!==void 0,o=Vt(t,e),a=yo(t,e);return n&&!o||i&&!a||o&&a&&o!==a.hostId?null:o?{kind:"host",hostId:o}:a?{kind:"device",hostId:a.hostId,deviceId:a.deviceId}:null}function Fr(t,e){return _o(e.headers["x-relay-admin-token"],t.adminToken)}function Hr(t,e){if(!t.trustProxy)return null;let s=e.headers["x-forwarded-for"];return typeof s!="string"||s.length===0?null:s.split(",")[0].trim()||null}function go(t,e){return Hr(t,e)||e.socket.remoteAddress||"unknown"}function Yr(t,e){return Hr(t,e)||e.socket.remoteAddress||null}function qt(t,e,s,r=20){let n=go(t,s),i=Date.now(),o=e.get(n);if(!o||i-o.startedAt>=6e4){if(e.size>=4096){let a=e.keys().next().value;a!==void 0&&e.delete(a)}return e.set(n,{startedAt:i,count:1}),!0}return o.count>=r?!1:(o.count+=1,!0)}function it(t,e){return qt(t,t.pairAttempts,e,20)}function $r(t,e){return qt(t,t.clientHandshakeAttempts,e,60)}function Wr(t,e){return qt(t,t.hostHandshakeAttempts,e,60)}function xe(t){!t||!y(t.ws)||m(t.ws,{type:"client_count",clientCount:t.clients.size})}function Gr(t,e,s,r){if(!s||!y(s.ws))return!1;let n=t.config.relay.maxBufferedBytesPerClient;if((Number(s.ws.bufferedAmount)||0)+r.length>n)return t.metrics.recordCleanup("slowClientsDropped"),C(t,s,{notify:!0,reason:"slow_client",closeCode:1013}),!1;let o=!1,a=()=>{if(y(s.ws))try{s.ws.send(r),s.bytesSent+=r.length,t.metrics.recordOut(r.length,e.id),o=!0}catch{C(t,s,{notify:!1,reason:"client_send_failed",closeCode:1011})}};return t.devLatencyMs>0?zt(t,s.ws,a):a(),t.devLatencyMs>0?!0:o}function zt(t,e,s){let r=t.sendQueues.get(e);if(!r){let i={items:[],timer:null};r=i,t.sendQueues.set(e,i),e.once("close",()=>{i.timer&&(clearTimeout(i.timer),t.activeDelayTimers.delete(i.timer),i.timer=null),i.items=[]})}let n=Date.now()+t.devDelayMs;if(r.items.push({sendAt:n,task:s}),!r.timer){let i=r,o=setTimeout(()=>jr(t,e,i),t.devDelayMs);r.timer=o,t.activeDelayTimers.add(o)}}function jr(t,e,s){s.timer&&(t.activeDelayTimers.delete(s.timer),s.timer=null);let r=Date.now();for(;s.items.length>0&&s.items[0].sendAt<=r;){let n=s.items.shift();try{n?.task()}catch{}}if(s.items.length>0&&!s.timer){let n=Math.max(0,s.items[0].sendAt-Date.now()),i=setTimeout(()=>jr(t,e,s),n);s.timer=i,t.activeDelayTimers.add(i)}}function X(t,e,s){for(let r of[...e.clients]){let n=t.clients.get(r);if(!n)continue;let i=s(n);i&&m(n.ws,i)}}var Xt=20,Kt=6;function So(t){if(!t)return null;let e=65536;for(let s=0;s<e;s++){let r=t.nextStreamIndex;if(t.nextStreamIndex=t.nextStreamIndex+1&65535,!t.streamIndices.has(r))return r}return null}function Ee(t,e,s){let r=s.session;r&&(r.streamIndex!==null&&r.streamIndex!==void 0&&e&&e.streamIndices.delete(r.streamIndex),t.streams.delete(r.streamId),s.session=null)}function ot(t,e,s,{restarted:r=!1}={}){if(!s||!y(e.ws))return;let n=ge("session"),i=null;e.binaryFrameV2&&(i=So(e),i!==null&&e.streamIndices.set(i,s.id)),s.session={streamId:n,streamIndex:i,cols:s.cols,rows:s.rows,ready:!1},t.streams.set(n,s.id),m(e.ws,{type:"session_start",clientId:n,streamId:n,cols:Math.max(Xt,s.cols),rows:Math.max(Kt,s.rows),role:"controller",...i!==null?{streamIndex:i}:{}}),r&&m(s.ws,{type:"session_restarted",streamId:n,cols:s.cols,rows:s.rows,hostname:e.hostname,platform:e.platform,...e.shellProfile?{shellProfile:e.shellProfile}:{},adminTerminalSupported:e.adminTabsAvailable,terminalPalette:e.terminalPalette||null,terminalFont:e.terminalFont||null,hostVersion:e.version,...e.herdrPrefixKeys?{herdrPrefixKeys:e.herdrPrefixKeys}:{}})}function Jt(t,e){for(let s of e.clients){let r=t.clients.get(s);r&&(r.role="controller",r.controllerId=null,m(r.ws,{type:"control_state",role:"controller",controllerId:null,clientCount:e.clients.size}))}}function Vr(t,e){if(!e)return 0;let s=0;for(let r of[...t.clients.values()])!r||r.deviceId!==e||(C(t,r,{notify:!1,reason:"device_revoked"}),k(r.ws,1e3,"this device has been revoked by the relay operator"),s+=1);return s}function C(t,e,{notify:s=!0,reason:r="client_disconnected",closeCode:n=1e3,terminate:i=!1}={}){if(!e||!t.clients.has(e.id))return;t.clients.delete(e.id);let o=t.hosts.get(e.hostId);if(e.session){let l=e.session.streamId;Ee(t,o,e),o&&y(o.ws)&&m(o.ws,{type:"session_stop",clientId:l,streamId:l})}o&&(o.clients.delete(e.id),xe(o),Jt(t,o),o.clients.size===0&&(o.controllerId=null,o.reconnecting&&N(t,o,{notify:!1,reason:"no_clients"})));let a=e.ws;e.ws=null,s&&m(a,{type:"error",code:r,message:r==="host_offline"?"Herdr host is offline":"connection closed"}),i||a?.readyState===T.default.CLOSING?se(a):k(a,n,r),t.metrics.recordCleanup("closedPtysCleaned")}function N(t,e,{notify:s=!0,reason:r="host_disconnected",terminate:n=!1}={}){if(!e||t.hosts.get(e.id)!==e)return;e.reconnectTimer&&clearTimeout(e.reconnectTimer),e.reconnectTimer=null,t.hosts.delete(e.id);for(let o of[...e.clients]){let a=t.clients.get(o);if(!a)continue;t.clients.delete(a.id),Ee(t,e,a);let l=a.ws;a.ws=null,s&&m(l,{type:"error",code:r,message:"Herdr host disconnected"}),n||l?.readyState===T.default.CLOSING?se(l):k(l,1012,r)}e.clients.clear(),t.metrics.forgetHost(e.id);let i=e.ws;e.ws=null,n||i?.readyState===T.default.CLOSING?se(i):k(i,1e3,r)}function at(t,e){if(!e?.handoffCapable||e.clients.size===0)return!1;for(let s of e.clients)if(!t.clients.get(s)?.handoffCapable)return!1;return!0}function lt(t,e,s="host_disconnected"){if(!e||t.hosts.get(e.id)!==e||e.reconnecting)return;if(!at(t,e)){N(t,e,{notify:!0,reason:s});return}e.ws=null,e.reconnecting=!0,e.reconnectStartedAt=Date.now(),e.lastSeenAt=Date.now(),e.load={},e.ptys=[];for(let n of e.clients){let i=t.clients.get(n);i&&Ee(t,e,i)}X(t,e,()=>({type:"host_reconnecting",code:s}));let r=setTimeout(()=>{e.reconnectTimer=null,t.hosts.get(e.id)===e&&e.reconnecting&&N(t,e,{notify:!0,reason:"host_reconnect_timeout"})},t.config.relay.hostReconnectGraceMs);e.reconnectTimer=r,r.unref?.()}var bo=3e3,To=2e3,wo=1e3;function Ao(t,e){if(typeof e!="string"||e.length===0)return!1;let s;try{s=Buffer.from(e.slice(0,32),"base64")}catch{return!1}return s.length===0?!1:vr(t,s)}function qr(t,e,s){let r={ws:e,req:s,authenticated:!1},n=setTimeout(()=>{r.authenticated||k(e,1008,"client hello timeout")},1e4);e.isAlive=!0,e.on("pong",()=>{e.isAlive=!0,r.client&&(r.client.lastSeenAt=Date.now(),r.client.lastPingAt=new Date().toISOString())}),e.on("ping",()=>{e.isAlive=!0,r.client&&(r.client.lastSeenAt=Date.now(),r.client.lastPingAt=new Date().toISOString())}),e.on("message",(i,o)=>{if(!r.authenticated){if(o)return w(e,"client hello must be JSON");let a=Se(i.toString());if(a?.type!=="hello"||a.protocol!==1)return w(e,"invalid client hello");if(!$r(t,s))return w(e,"too many connection attempts","rate_limited");let l=null,c=null;if(a.pairCode){if(!it(t,s))return w(e,"too many pairing attempts","rate_limited");c=t.auth.completePairing(a.pairCode)}if(c?l=c:a.token&&(l=t.auth.authenticateDevice(a.token)),!l)return w(e,"valid device token or pairing code required","auth_required");let f=t.hosts.get(l.hostId);if(!f||f.reconnecting||!y(f.ws))return w(e,"paired Herdr host is offline",f?.reconnecting?"host_reconnecting":"host_offline");if(f.clients.size>=t.config.relay.maxClientsPerHost)return w(e,"host client limit reached","too_many_clients");clearTimeout(n),t.finishHandshake(e);let u={id:ge("client"),ws:e,hostId:f.id,deviceId:l.deviceId,browserClientId:typeof a.clientId=="string"?a.clientId.slice(0,128):null,handoffCapable:Array.isArray(a.capabilities)&&a.capabilities.includes(ye.hostHandoff),session:null,role:"controller",controllerId:null,connectedAt:new Date().toISOString(),connectedAtMs:Date.now(),lastSeenAt:Date.now(),lastPingAt:null,bytesReceived:0,bytesSent:0,ip:Yr(t,s),userAgent:String(s.headers["user-agent"]||"").slice(0,256),cols:Me(a.cols,80),rows:Me(a.rows,24)};u.controllerId=null,t.auth.noteDeviceSeen(l.deviceId,{userAgent:u.userAgent,ip:u.ip}),r.authenticated=!0,r.client=u,t.clients.set(u.id,u),f.clients.add(u.id),xe(f),e.isAlive=!0,c&&m(e,{type:"paired",token:c.token,deviceId:c.deviceId,hostId:c.hostId,expiresAt:c.expiresAtIso}),m(e,{type:"ready",role:u.role,controllerId:null,hostId:f.id,hostname:f.hostname,platform:f.platform,...f.shellProfile?{shellProfile:f.shellProfile}:{},adminTerminalSupported:f.adminTabsAvailable,clientId:u.id,terminalPalette:f.terminalPalette||null,terminalFont:f.terminalFont||null,clientCount:f.clients.size,hostVersion:f.version,...f.herdrPrefixKeys?{herdrPrefixKeys:f.herdrPrefixKeys}:{}}),f.agentStatus&&m(e,f.agentStatus),f.updateStatus&&m(e,f.updateStatus),ot(t,f,u),Jt(t,f);return}r.client&&vo(t,r.client,i,o)}),e.on("close",()=>{clearTimeout(n),r.client&&C(t,r.client,{notify:!0})}),e.on("error",()=>{})}function vo(t,e,s,r){e.lastSeenAt=Date.now();let n=t.hosts.get(e.hostId);if(!n){C(t,e,{notify:!0,reason:"host_offline"});return}if(r){let o=s;if(o.length>t.config.relay.maxPayloadBytes||!e.session)return;let a=n.binaryFrameV2&&typeof e.session.streamIndex=="number"?pr(1,e.session.streamIndex,o):mr("input",e.session.streamId,o);if(y(n.ws)){let l=()=>{if(y(n.ws))try{n.ws.send(a),e.bytesReceived+=o.length,t.metrics.recordIn(o.length,n.id)}catch{lt(t,n,"host_send_failed")}};t.devLatencyMs>0?zt(t,n.ws,l):l()}return}let i=Se(s.toString());if(!i){m(e.ws,{type:"error",code:"invalid_json",message:"message must be JSON"});return}if(i.type==="ping")e.lastPingAt=new Date().toISOString(),m(e.ws,{type:"pong"});else if(i.type==="resize")e.cols=Me(i.cols,e.cols),e.rows=Me(i.rows,e.rows),e.session&&(e.session.cols=e.cols,e.session.rows=e.rows,y(n.ws)&&m(n.ws,{type:"resize",clientId:e.session.streamId,streamId:e.session.streamId,cols:Math.max(Xt,e.cols),rows:Math.max(Kt,e.rows)}));else if(i.type==="herdr_start"){if(!e.session){m(e.ws,{type:"error",code:"no_session",message:"terminal session is not ready"});return}let o=Date.now();if(e.herdrStartAt&&o-e.herdrStartAt<bo)return;e.herdrStartAt=o,y(n.ws)&&m(n.ws,{type:"herdr_start",clientId:e.session.streamId,streamId:e.session.streamId})}else if(i.type==="admin_tab_open"){if(!e.session||!y(n.ws))return;if(!n.adminTabsAvailable){m(e.ws,{type:"error",code:"admin_terminal_unsupported",message:"Update the host connector to open administrator terminals."});return}let o=Date.now();if(e.adminTabAt&&o-e.adminTabAt<wo)return;e.adminTabAt=o,m(n.ws,{type:"admin_tab_open",clientId:e.session.streamId,streamId:e.session.streamId})}else if(i.type==="host_font_chunk_request")Lr(n,e,i);else if(i.type==="host_font_subset_request")Nr(n,e,i);else if(i.type==="host_font_refresh"){if(!e.session||!y(n.ws))return;let o=Date.now();if(e.fontRefreshAt&&o-e.fontRefreshAt<To)return;e.fontRefreshAt=o,m(n.ws,{type:"host_font_refresh",clientId:e.session.streamId,streamId:e.session.streamId})}else if(i.type==="claim_control")e.role="controller",m(e.ws,{type:"control_granted"});else if(i.type==="release_control")m(e.ws,{type:"control_state",role:"controller",controllerId:null});else if(i.type==="paste_file"){if(e.role==="viewer"){m(e.ws,{type:"error",code:"viewer_mode",message:"Viewer mode cannot paste to terminal"});return}if(!Ar(i.mime)){m(e.ws,{type:"error",code:"paste_file_unsupported",message:"Unsupported paste image format"});return}if(typeof i.dataBase64!="string"){m(e.ws,{type:"error",code:"paste_file_unsupported",message:"Invalid paste image payload"});return}let o=Buffer.byteLength(i.dataBase64,"base64");if(o===0){m(e.ws,{type:"error",code:"paste_file_empty",message:"Pasted image payload is empty"});return}if(o>3145728){m(e.ws,{type:"error",code:"paste_file_too_large",message:"Pasted image exceeds 3 MB limit"});return}if(!Ao(i.mime,i.dataBase64)){m(e.ws,{type:"error",code:"paste_file_unsupported",message:"Pasted image content does not match declared MIME type"});return}if(!y(n?.ws)){m(e.ws,{type:"error",code:"host_offline",message:"Host is offline or disconnected"});return}if(!e.session){m(e.ws,{type:"error",code:"no_session",message:"Terminal session is not ready"});return}m(n.ws,{type:"paste_file",clientId:e.session.streamId,streamId:e.session.streamId,mime:i.mime,dataBase64:i.dataBase64})}}import Co from"node:os";var Io=/^\d{1,6}\.\d{1,6}\.\d{1,6}(?:-[0-9A-Za-z.-]{1,32})?$/;function De(t){return typeof t=="string"&&Io.test(t)?t:null}var Oo=16;function zr(t,e,s){let r={};if(s.counts&&typeof s.counts=="object")for(let[o,a]of Object.entries(s.counts))typeof a=="number"&&Number.isFinite(a)&&(r[o.slice(0,32)]=Math.max(0,Math.min(9999,Math.trunc(a))));let n=(Array.isArray(s.agents)?s.agents:[]).slice(0,Oo).map(o=>({paneId:z(o?.paneId,64),workspaceId:z(o?.workspaceId,64),agent:z(o?.agent,32),title:z(o?.title,64),status:z(o?.status,16),focused:o?.focused===!0})),i={type:"agent_status",focusedPaneId:z(s.focusedPaneId,64),focusedAgent:z(s.focusedAgent,32),counts:r,total:typeof s.total=="number"&&Number.isFinite(s.total)?Math.max(0,Math.trunc(s.total)):n.length,agents:n};e.agentStatus=i,X(t,e,()=>i)}function Xr(t,e,s){let r=De(s.current),n=De(s.latest);if(!r||!n)return;let i={type:"update_status",current:r,installed:De(s.installed)||r,latest:n,updateAvailable:s.updateAvailable===!0,restartPending:s.restartPending===!0,updateCommand:s.updateCommand===!0};e.updateStatus=i,X(t,e,()=>i)}function Kr(t,e,s){e.terminalFont=rt(s.terminalFont);let r={type:"terminal_font",terminalFont:e.terminalFont||null};X(t,e,()=>r)}function Po(t,e,s,r=new Set){let n=Array.isArray(t.capabilities)?t.capabilities:[],i=br(t.herdrPrefixKeys);return{id:t.hostId,ws:e,hostname:typeof t.hostname=="string"?t.hostname.slice(0,128):Co.hostname(),platform:typeof t.platform=="string"?t.platform.slice(0,32):process.platform,...t.shellProfile==="git-bash"?{shellProfile:t.shellProfile}:{},adminTabsAvailable:n.includes(ye.adminTabs),arch:typeof t.arch=="string"?t.arch.slice(0,32):process.arch,connectedAt:new Date(s.connectedAt).toISOString(),connectedAtMs:s.connectedAt,terminalPalette:Er(t.terminalPalette),terminalFont:rt(t.terminalFont),...i?{herdrPrefixKeys:i}:{},agentStatus:null,updateStatus:null,version:De(t.version),lastSeenAt:Date.now(),clients:r,controllerId:null,load:{},ptys:[],reconnecting:!1,reconnectTimer:null,connectionGeneration:ge("host-connection"),handoffCapable:n.includes(ye.hostHandoff),binaryFrameV2:n.includes(ye.binaryFrameV2),streamIndices:new Map,nextStreamIndex:0,shutdownRequested:!1}}function Jr(t,e,s){let r={ws:e,remoteAddress:s.socket.remoteAddress,connectedAt:Date.now(),authenticated:!1},n=setTimeout(()=>{r.authenticated||k(e,1008,"host hello timeout")},1e4);e.isAlive=!0,e.on("pong",()=>{e.isAlive=!0,r.host&&(r.host.lastSeenAt=Date.now())}),e.on("ping",()=>{e.isAlive=!0,r.host&&(r.host.lastSeenAt=Date.now())}),e.on("message",(i,o)=>{if(!r.authenticated){if(o)return w(e,"host hello must be JSON");let a=Se(i.toString());if(a?.type!=="host_hello"||a.protocol!==1)return w(e,"invalid host hello");if(!Wr(t,s))return w(e,"too many connection attempts","rate_limited");let l=t.hosts.get(a.hostId);if(!l&&t.hosts.size>=t.config.relay.maxHosts)return w(e,"relay host limit reached","too_many_hosts");let c=t.auth.registerHost(a.hostId,a.token,a.password??null);if(!c.ok)return w(e,c.message,c.code);clearTimeout(n),r.authenticated=!0,t.finishHandshake(e);let f=at(t,l),d=f&&l?l.clients:new Set;if(l)if(l.reconnectTimer&&clearTimeout(l.reconnectTimer),l.reconnectTimer=null,f){for(let h of l.clients){let p=t.clients.get(h);p?.session&&(y(l.ws)&&m(l.ws,{type:"session_stop",clientId:p.session.streamId,streamId:p.session.streamId}),Ee(t,l,p))}l.load={},l.ptys=[],X(t,l,()=>({type:"host_reconnecting",code:"host_replaced"}))}else N(t,l,{notify:!0,reason:"host_replaced"});let u=Po(a,e,r,d);if(r.host=u,t.hosts.set(u.id,u),l&&f&&k(l.ws,1e3,"host_replaced"),m(e,{type:"host_ready",protocol:1,hostId:u.id,clientCount:u.clients.size}),xe(u),f)for(let h of u.clients){let p=t.clients.get(h);p&&ot(t,u,p,{restarted:!0})}return}r.host&&Ro(t,r.host,i,o)}),e.on("close",(i,o)=>{clearTimeout(n);let a=r.host;if(!a||t.hosts.get(a.id)!==a||a.ws!==e)return;if((o?o.toString():"")==="host_shutdown"&&(a.shutdownRequested=!0),a.shutdownRequested||!at(t,a)){N(t,a,{notify:!0,reason:a.shutdownRequested?"host_shutdown":"host_disconnected"});return}lt(t,a,"host_disconnected")}),e.on("error",()=>{})}function Ro(t,e,s,r){if(e.lastSeenAt=Date.now(),r){let c;try{c=_r(s)}catch(u){t.metrics.recordCleanup("deadConnectionsClosed"),k(e.ws,1003,u.message);return}if(c.type!=="output")return;let f=c.version===2?e.streamIndices.get(c.streamIndex):t.streams.get(c.streamId);if(!f)return;let d=t.clients.get(f);if(!d||!y(d.ws))return;Gr(t,e,d,c.payload);return}let n=Se(s.toString());if(!n)return;if(n.type==="heartbeat"){e.load=n.load&&typeof n.load=="object"?n.load:{},e.ptys=Array.isArray(n.ptys)?n.ptys.slice(0,256):[];return}if(n.type==="host_shutdown"){e.shutdownRequested=!0,t.hosts.get(e.id)===e&&N(t,e,{notify:!0,reason:"host_shutdown"});return}if(n.type==="agent_status"){zr(t,e,n);return}if(n.type==="update_status"){Xr(t,e,n);return}if(n.type==="terminal_font"){Kr(t,e,n);return}let i=n,o=typeof i.clientId=="string"?i.clientId:i.streamId,a=o?t.streams.get(o):null,l=a?t.clients.get(a):null;if(l)if(n.type==="session_ready")l.session&&(l.session.ready=!0),m(l.ws,{type:"session_ready",clientId:l.id});else if(n.type==="session_exit"){let c=Number.isInteger(n.code)?n.code:null;m(l.ws,{type:"exit",code:c}),Ee(t,e,l),C(t,l,{notify:!1})}else n.type==="host_font_chunk"?Dr(l,n):n.type==="host_font_subset_ready"?Mr(l,n):n.type==="paste_file_ready"?m(l.ws,{type:"paste_file_ready",path:n.path}):n.type==="error"&&(n.code==="host_font_unavailable"&&(Wt(l),nt(l)),n.code==="host_font_subset_failed"&&nt(l),m(l.ws,{type:"error",code:n.code||"host_error",message:String(n.message||"Host connector error")}))}import Zr from"node:fs";import re from"node:path";import{URL as No}from"node:url";function Zt(t,{sample:e=!0,includeDevices:s=!1,scopeHostId:r=null}={}){let n=r?[...t.clients.values()].filter(h=>h.hostId===r):[...t.clients.values()],i=r?[...t.hosts.values()].filter(h=>h.id===r):[...t.hosts.values()],o=n.map(h=>({id:h.id,role:h.role,...r?{}:{hostId:h.hostId},...s?{deviceId:h.deviceId}:{},userAgent:h.userAgent,connectedAt:h.connectedAt,lastPingAt:h.lastPingAt,bytesReceived:h.bytesReceived,bytesSent:h.bytesSent,ip:h.ip})),a=t.auth.listDevices(),l=new Map;for(let h of a)l.set(h.hostId,(l.get(h.hostId)||0)+1);let c=i.map(h=>({id:h.id,hostname:h.hostname,platform:h.platform,arch:h.arch,status:h.reconnecting?"reconnecting":h.clients.size?"busy":"online",connectedAt:h.connectedAt,activePtyCount:h.ptys.length,connectedDeviceCount:st([...h.clients].map(p=>t.clients.get(p)).filter(p=>!!p)),pairedDeviceCount:l.get(h.id)||0,version:h.version??h.updateStatus?.current??null,latestVersion:h.updateStatus?.updateAvailable?h.updateStatus.latest:null,load:h.load})),f=i.flatMap(h=>h.ptys.map(p=>({...p,...r?{}:{hostId:h.id},activeClients:h.clients.size}))),d=s?a:void 0,u=t.address();return{...t.metrics.snapshot({clients:o,hosts:c,ptys:f,sample:e,scopeHostId:r,activeUserCount:st(n)}),...d?{devices:d}:{},relayMode:t.relayMode,isRemoteRelay:t.relayMode==="remote",remoteAdminUrl:t.relayMode==="remote"?`${String(t.config.relay.publicUrl||"").replace(/\/+$/,"")}/admin`:void 0,relay:{mode:t.relayMode,publicUrl:t.config.relay.publicUrl,bind:t.config.relay.host,port:(u&&"port"in u?u.port:void 0)||t.config.relay.port,maxClientsPerHost:t.config.relay.maxClientsPerHost,maxHosts:t.config.relay.maxHosts,maxPendingHandshakes:t.config.relay.maxPendingHandshakes,maxBufferedBytesPerClient:t.config.relay.maxBufferedBytesPerClient,hostReconnectGraceMs:t.config.relay.hostReconnectGraceMs,adminConfigured:!!t.adminToken,adminStatusPath:"/api/admin/status",dashboardPath:"/admin"}}}import ko from"node:fs";import Lo from"node:path";var W=JSON.parse(ko.readFileSync(Lo.join(ae,"package.json"),"utf8")).version;var Qr=re.join(ae,"web","dist"),Mo=10080*60,Do={".html":"text/html; charset=utf-8",".js":"text/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".json":"application/json",".svg":"image/svg+xml",".png":"image/png",".ico":"image/x-icon",".woff2":"font/woff2"};function Qt(t,e="application/json"){t.setHeader("Content-Type",e),t.setHeader("Cache-Control","no-store"),t.setHeader("X-Content-Type-Options","nosniff"),t.setHeader("X-Frame-Options","DENY"),t.setHeader("Referrer-Policy","no-referrer"),t.setHeader("Content-Security-Policy","default-src 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none'; connect-src 'self' ws: wss:; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'")}function ne(t,e,s){Qt(t),t.writeHead(e),t.end(JSON.stringify(s))}function A(t,e,s,r){ne(t,e,{ok:!1,code:s,message:r})}function en(t,e,s){return t.adminToken?Fr(t,e)?!0:(A(s,401,"admin_auth_required","a valid relay admin token is required"),!1):(A(s,503,"admin_not_configured","configure RELAY_ADMIN_TOKEN to access the relay dashboard"),!1)}var Bo=(t,e,s)=>{ne(s,200,{ok:!0,version:W,protocol:1,uptimeSeconds:Math.floor((Date.now()-t.startedAt)/1e3)})},Uo=(t,e,s)=>{let r=String(t.config.relay.publicUrl||"").replace(/\/+$/,"");ne(s,200,{ok:!0,version:W,protocol:1,relayMode:t.relayMode,isRemoteRelay:t.relayMode==="remote",adminConfigured:!!t.adminToken,adminPath:"/admin",adminStatusPath:"/api/admin/status",publicUrl:r,remoteAdminUrl:t.relayMode==="remote"?`${r}/admin`:null})},Fo=(t,e,s)=>{let r=Ur(t,e);if(!r){A(s,401,"auth_required","an authorized device or host token is required");return}ne(s,200,Zt(t,{scopeHostId:r.hostId}))},Ho=(t,e,s)=>{en(t,e,s)&&ne(s,200,Zt(t,{includeDevices:!0}))},Yo=(t,e,s,r)=>{if(!en(t,e,s))return;let n=decodeURIComponent(r.pathname.slice(19)),i=t.auth.revokeDevice(n);if(!i){A(s,404,"device_not_found","no such paired device");return}let o=Vr(t,n);ne(s,200,{ok:!0,deviceId:i.deviceId,disconnected:o})},$o=(t,e,s)=>{if(!it(t,e)){A(s,429,"rate_limited","too many pairing attempts");return}let r=Vt(t,e);if(!r){A(s,401,"host_auth_required","a valid host id and token are required");return}let n=t.hosts.get(r);if(!n||n.reconnecting||!y(n.ws)){A(s,409,"host_offline","no Herdr host is connected");return}try{let i=t.auth.startPairing(r,String(t.config.relay.publicUrl).replace(/\/$/,"")),o={ok:!0,...i,pairUrl:`${i.publicUrl}/?pairCode=${encodeURIComponent(i.code)}`};ne(s,200,o)}catch(i){let{code:o,message:a}=i;A(s,409,o||"pairing_failed",a)}},Wo=[{method:"GET",path:"/healthz",handle:Bo},{method:"GET",path:"/api/info",handle:Uo},{method:"GET",path:"/api/status",handle:Fo},{method:"GET",path:"/api/admin/status",handle:Ho},{method:"DELETE",path:"/api/admin/devices/",prefix:!0,handle:Yo},{method:"POST",path:"/api/pair/start",handle:$o}];function tn(t,e,s){let r;try{r=new No(e.url||"",`http://${e.headers.host||"localhost"}`)}catch{A(s,400,"bad_request","invalid URL");return}if(!Br(t,e)){A(s,403,"origin_denied","origin is not allowed");return}if(e.method==="OPTIONS"){s.writeHead(204,{"Access-Control-Allow-Origin":e.headers.origin||"*","Access-Control-Allow-Headers":"Authorization, Content-Type, X-Herdr-Host-Id, X-Herdr-Host-Token, X-Relay-Admin-Token","Access-Control-Allow-Methods":"GET, POST, DELETE, OPTIONS",Vary:"Origin"}),s.end();return}e.headers.origin&&(s.setHeader("Access-Control-Allow-Origin",e.headers.origin),s.setHeader("Vary","Origin"));let{pathname:n}=r,i=Wo.find(o=>o.method===e.method&&(o.prefix?n.startsWith(o.path):n===o.path));if(i){i.handle(t,e,s,r);return}if(n.startsWith("/api/")){A(s,404,"not_found","API route not found");return}Go(t.publicDir,n,s)}function Go(t,e,s){let r=e==="/"||e==="/admin"?"index.html":e.replace(/^\/+/,""),n=re.resolve(t,r);if(!n.startsWith(`${t}${re.sep}`)&&n!==re.join(t,"index.html")){A(s,403,"forbidden","path is not allowed");return}Zr.readFile(n,(i,o)=>{if(i&&!re.extname(r)){Zr.readFile(re.join(t,"index.html"),(l,c)=>{if(l){A(s,503,"web_not_built","frontend has not been built");return}Qt(s,"text/html; charset=utf-8"),s.end(c)});return}if(i){A(s,404,"not_found","file not found");return}let a=re.extname(n).toLowerCase();Qt(s,Do[a]||"application/octet-stream"),r.startsWith("fonts/")&&s.setHeader("Cache-Control",`public, max-age=${Mo}`),s.end(o)})}function sn(t){let e=[...[...t.hosts.values()].map(s=>s.ws),...[...t.clients.values()].map(s=>s.ws)].filter(s=>!!(s&&s.readyState!==T.default.CLOSED));for(let s of e){if(s.readyState===T.default.CLOSING){t.metrics.recordCleanup("deadConnectionsClosed"),se(s);continue}if(s.readyState===T.default.OPEN){if(!s.isAlive){t.metrics.recordCleanup("deadConnectionsClosed"),se(s);continue}s.isAlive=!1;try{s.ping()}catch{}}}}function es(t,e){for(let[s,r]of t.entries())e-r.startedAt>=6e4&&t.delete(s)}function rn(t){let e=Date.now(),s=t.config.cleanup.staleAfterMs;es(t.pairAttempts,e),es(t.clientHandshakeAttempts,e),es(t.hostHandshakeAttempts,e);for(let n of[...t.clients.values()])e-n.lastSeenAt>s&&(t.metrics.recordCleanup("staleClientsPurged"),C(t,n,{notify:!1,reason:"stale_client",terminate:!0}));for(let n of[...t.hosts.values()])n.reconnecting||e-n.lastSeenAt>s&&(t.metrics.recordCleanup("deadConnectionsClosed"),N(t,n,{notify:!0,reason:"stale_host",terminate:!0}));let r=t.auth.cleanup(e);(r.removedDevices||r.removedPairings)&&t.metrics.recordCleanup("staleClientsPurged",r.removedDevices),t.metrics.cleanup.lastCleanupAt=new Date(e).toISOString()}var ct=class{config;relayMode;hosts=new Map;clients=new Map;streams=new Map;pairAttempts=new Map;clientHandshakeAttempts=new Map;hostHandshakeAttempts=new Map;pendingHandshakes=new Set;startedAt=Date.now();metrics;stateFile;password;adminToken;trustProxy;devLatencyMs;devDelayMs;publicDir;sendQueues=new WeakMap;activeDelayTimers=new Set;auth;server;wss;heartbeatTimer=null;cleanupTimer=null;constructor(e=Be().config,s={}){this.config={relay:{...x.relay,...e.relay},auth:{...x.auth,...e.auth},cleanup:{...x.cleanup,...e.cleanup}};let{relay:r,auth:n}=this.config;this.relayMode=r.mode==="local"?"local":"remote",this.metrics=s.metrics||new tt({version:W,protocolVersion:1}),this.stateFile=s.stateFile||n.stateFile||ts.join(ht(),"relay-auth.json"),this.password=s.password??n.password??null,this.adminToken=s.adminToken??n.adminToken??null,this.trustProxy=!!(s.trustProxy??r.trustProxy),this.publicDir=ts.resolve(s.publicDir??Qr);let i=s.devLatencyMs??r.devLatencyMs??process.env.RELAY_DEV_LATENCY_MS;this.devLatencyMs=i?Math.max(0,Number.parseInt(String(i),10)||0):0,this.devDelayMs=this.devLatencyMs>0?Math.round(this.devLatencyMs/2):0,this.auth=s.auth||new Ze({stateFile:this.stateFile,pairingTtlMs:n.pairingTtlMs,deviceTtlMs:n.deviceTtlMs,maxDevices:n.maxDevices,password:this.password}),this.server=jo.createServer((o,a)=>tn(this,o,a)),this.wss=new Dt.default({noServer:!0,clientTracking:!1,maxPayload:r.maxPayloadBytes,perMessageDeflate:{threshold:1024,zlibDeflateOptions:{level:3},serverNoContextTakeover:!1,clientNoContextTakeover:!1,concurrencyLimit:10}}),this.server.on("upgrade",(o,a,l)=>this.handleUpgrade(o,a,l))}listen(e=this.config.relay.port,s=this.config.relay.host){return ke(ts.dirname(this.stateFile)),new Promise((r,n)=>{let i=a=>{this.server.off("listening",o),n(a)},o=()=>{this.server.off("error",i),this.heartbeatTimer=setInterval(()=>sn(this),this.config.cleanup.heartbeatIntervalMs),this.cleanupTimer=setInterval(()=>rn(this),this.config.cleanup.intervalMs),r(this.address())};this.server.once("error",i),this.server.once("listening",o),this.server.listen(e,s)})}address(){let e=this.server.address();return e?typeof e=="string"?{path:e}:{host:e.address,port:e.port}:null}async close(){this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.cleanupTimer&&clearInterval(this.cleanupTimer),this.heartbeatTimer=null,this.cleanupTimer=null;for(let e of this.activeDelayTimers)clearTimeout(e);this.activeDelayTimers.clear();for(let e of[...this.clients.values()])C(this,e,{notify:!1});for(let e of[...this.hosts.values()])N(this,e,{notify:!1});this.streams.clear(),this.pairAttempts.clear(),this.clientHandshakeAttempts.clear(),this.hostHandshakeAttempts.clear(),this.pendingHandshakes.clear(),this.metrics.close(),await new Promise(e=>{if(!this.server.listening)return e();this.server.close(()=>e())})}handleUpgrade(e,s,r){let n=(()=>{try{return new Vo(e.url||"","http://localhost").pathname}catch{return""}})();if(![Yt,Tr].includes(n)||!jt(this,e.headers.origin,e)){s.write(`HTTP/1.1 403 Forbidden\r
10
+ `+s)}function te(t,e,s,r,n,i){if(t.listenerCount("wsClientError")){let o=new Error(n);Error.captureStackTrace(o,te),t.emit("wsClientError",o,s,e)}else Re(s,r,n,i)}});import Jo from"node:fs";import Zo from"node:path";import _n from"node:fs";import yn from"node:os";import we from"node:path";var le=we.resolve(import.meta.dirname,"..");function ht(){if(process.env.RELAY_STATE_DIR)return process.env.RELAY_STATE_DIR;let t=process.env.XDG_STATE_HOME||we.join(yn.homedir(),".local","state");return we.join(t,"herdr-remote-relay")}var x={relay:{mode:"remote",host:"127.0.0.1",port:8787,publicUrl:"http://127.0.0.1:8787",maxPayloadBytes:5*1024*1024,maxClientsPerHost:16,maxHosts:1024,maxPendingHandshakes:1024,maxBufferedBytesPerClient:4*1024*1024,allowedOrigins:[],trustProxy:!1,hostReconnectGraceMs:30*1e3},auth:{pairingTtlMs:600*1e3,deviceTtlMs:720*60*60*1e3,maxDevices:32,password:null,adminToken:null,stateFile:null},cleanup:{intervalMs:60*1e3,heartbeatIntervalMs:30*1e3,staleAfterMs:90*1e3}};function gn(t){return JSON.parse(JSON.stringify(t))}function Sn(t){try{return JSON.parse(_n.readFileSync(t,"utf8"))}catch(e){let{code:s,message:r}=e;if(s==="ENOENT")return null;throw new Error(`cannot read relay config ${t}: ${r}`)}}function pt(t,e){if(t==null||t==="")return e;if(t===!0||t===!1)return t;let s=String(t).trim().toLowerCase();return["true","1","yes","on"].includes(s)?!0:["false","0","no","off"].includes(s)?!1:e}function v(t,e,s,r){let n=Number(t);return!Number.isInteger(n)||n<s||n>r?e:n}function os(t){return Array.isArray(t)?t.map(e=>String(e).trim()).filter(Boolean):typeof t!="string"?null:t.split(",").map(e=>e.trim()).filter(Boolean)}function dt(t,e){if(!e||typeof e!="object")return;let s=e;for(let r of Object.keys(t))s[r]!==void 0&&(t[r]=s[r])}function xn(t=[]){let e={},s=[],r=!1,n=!1;for(let i=0;i<t.length;i+=1){let o=t[i];if(o==="--help"||o==="-h"){r=!0;continue}if(o==="--version"||o==="-v"){n=!0;continue}if(!o.startsWith("--")){s.push(`unexpected argument: ${o}`);continue}let a=o.indexOf("="),l=a===-1?o.slice(2):o.slice(2,a),c=a===-1?void 0:o.slice(a+1);if(c===void 0){let f=t[i+1];f===void 0||f.startsWith("--")?c="true":(c=f,i+=1)}e[l]=c}return{options:e,help:r,version:n,errors:s}}function En(t,e){if(!e||typeof e!="object")return;let s=e;dt(t.relay,s.relay),dt(t.auth,s.auth),dt(t.cleanup,s.cleanup)}function bn(t,e){if((e.RELAY_DEPLOYMENT_MODE==="local"||e.RELAY_DEPLOYMENT_MODE==="remote")&&(t.relay.mode=e.RELAY_DEPLOYMENT_MODE),e.RELAY_BIND&&(t.relay.host=e.RELAY_BIND),e.RELAY_PORT&&(t.relay.port=e.RELAY_PORT),e.RELAY_PUBLIC_URL&&(t.relay.publicUrl=e.RELAY_PUBLIC_URL),e.RELAY_MAX_PAYLOAD_BYTES&&(t.relay.maxPayloadBytes=e.RELAY_MAX_PAYLOAD_BYTES),e.RELAY_MAX_CLIENTS_PER_HOST&&(t.relay.maxClientsPerHost=e.RELAY_MAX_CLIENTS_PER_HOST),e.RELAY_MAX_HOSTS&&(t.relay.maxHosts=e.RELAY_MAX_HOSTS),e.RELAY_MAX_PENDING_HANDSHAKES&&(t.relay.maxPendingHandshakes=e.RELAY_MAX_PENDING_HANDSHAKES),e.RELAY_MAX_BUFFERED_BYTES_PER_CLIENT&&(t.relay.maxBufferedBytesPerClient=e.RELAY_MAX_BUFFERED_BYTES_PER_CLIENT),e.RELAY_HOST_RECONNECT_GRACE_MS&&(t.relay.hostReconnectGraceMs=e.RELAY_HOST_RECONNECT_GRACE_MS),e.RELAY_ALLOWED_ORIGINS!==void 0){let s=os(e.RELAY_ALLOWED_ORIGINS);s&&(t.relay.allowedOrigins=s)}e.RELAY_TRUST_PROXY!==void 0&&(t.relay.trustProxy=pt(e.RELAY_TRUST_PROXY,t.relay.trustProxy)),e.RELAY_PASSWORD&&(t.auth.password=e.RELAY_PASSWORD),e.RELAY_ADMIN_TOKEN&&(t.auth.adminToken=e.RELAY_ADMIN_TOKEN),e.RELAY_AUTH_STATE_FILE&&(t.auth.stateFile=e.RELAY_AUTH_STATE_FILE),e.RELAY_PAIRING_TTL_MS&&(t.auth.pairingTtlMs=e.RELAY_PAIRING_TTL_MS),e.RELAY_DEVICE_TTL_MS&&(t.auth.deviceTtlMs=e.RELAY_DEVICE_TTL_MS),e.RELAY_MAX_DEVICES&&(t.auth.maxDevices=e.RELAY_MAX_DEVICES)}function Tn(t,e){if((e["deployment-mode"]==="local"||e["deployment-mode"]==="remote")&&(t.relay.mode=e["deployment-mode"]),e.bind&&(t.relay.host=e.bind),e.port&&(t.relay.port=e.port),e["public-url"]&&(t.relay.publicUrl=e["public-url"]),e["allowed-origins"]!==void 0){let s=os(e["allowed-origins"]);s&&(t.relay.allowedOrigins=s)}e["trust-proxy"]!==void 0&&(t.relay.trustProxy=pt(e["trust-proxy"],t.relay.trustProxy)),e.password&&(t.auth.password=e.password),e["admin-token"]&&(t.auth.adminToken=e["admin-token"]),e["state-file"]&&(t.auth.stateFile=e["state-file"]),e["max-clients"]&&(t.relay.maxClientsPerHost=e["max-clients"]),e["max-hosts"]&&(t.relay.maxHosts=e["max-hosts"]),e["max-pending-handshakes"]&&(t.relay.maxPendingHandshakes=e["max-pending-handshakes"]),e["max-buffered-bytes"]&&(t.relay.maxBufferedBytesPerClient=e["max-buffered-bytes"]),e["host-reconnect-grace-ms"]&&(t.relay.hostReconnectGraceMs=e["host-reconnect-grace-ms"])}function wn(t){return t.relay.mode!=="local"&&t.relay.mode!=="remote"&&(t.relay.mode=x.relay.mode),t.relay.port=v(t.relay.port,x.relay.port,0,65535),t.relay.maxPayloadBytes=v(t.relay.maxPayloadBytes,x.relay.maxPayloadBytes,4096,16*1024*1024),t.relay.maxClientsPerHost=v(t.relay.maxClientsPerHost,x.relay.maxClientsPerHost,1,256),t.relay.maxHosts=v(t.relay.maxHosts,x.relay.maxHosts,1,1e5),t.relay.maxPendingHandshakes=v(t.relay.maxPendingHandshakes,x.relay.maxPendingHandshakes,16,1e5),t.relay.maxBufferedBytesPerClient=v(t.relay.maxBufferedBytesPerClient,x.relay.maxBufferedBytesPerClient,64*1024,256*1024*1024),t.relay.hostReconnectGraceMs=v(t.relay.hostReconnectGraceMs,x.relay.hostReconnectGraceMs,1e3,1440*60*1e3),t.auth.pairingTtlMs=v(t.auth.pairingTtlMs,x.auth.pairingTtlMs,30*1e3,1440*60*1e3),t.auth.deviceTtlMs=v(t.auth.deviceTtlMs,x.auth.deviceTtlMs,60*1e3,365*24*60*60*1e3),t.auth.maxDevices=v(t.auth.maxDevices,x.auth.maxDevices,1,1e4),t.cleanup.intervalMs=v(t.cleanup.intervalMs,x.cleanup.intervalMs,1e3,1440*60*1e3),t.cleanup.heartbeatIntervalMs=v(t.cleanup.heartbeatIntervalMs,x.cleanup.heartbeatIntervalMs,1e3,600*1e3),t.cleanup.staleAfterMs=v(t.cleanup.staleAfterMs,x.cleanup.staleAfterMs,t.cleanup.heartbeatIntervalMs*2,1440*60*1e3),(typeof t.relay.host!="string"||t.relay.host.length===0)&&(t.relay.host=x.relay.host),(typeof t.relay.publicUrl!="string"||t.relay.publicUrl.length===0)&&(t.relay.publicUrl=`http://${t.relay.host}:${t.relay.port}`),t.relay.publicUrl=String(t.relay.publicUrl).replace(/\/+$/,""),Array.isArray(t.relay.allowedOrigins)||(t.relay.allowedOrigins=[]),t.relay.trustProxy=pt(t.relay.trustProxy,!1),t.auth.stateFile||(t.auth.stateFile=we.join(ht(),"relay-auth.json")),t}function An(t){let e=[],s=["127.0.0.1","localhost","::1"].includes(t.relay.host),r;try{r=new URL(t.relay.publicUrl)}catch{e.push(`publicUrl is not a valid URL: ${t.relay.publicUrl}`)}return t.auth.password||e.push("no password set (RELAY_PASSWORD): this is a public relay, anyone may connect a workstation to it"),t.relay.mode==="remote"&&!t.auth.adminToken&&e.push("no admin token set (RELAY_ADMIN_TOKEN): the relay operator dashboard is unavailable"),!s&&r&&r.protocol==="http:"&&!["127.0.0.1","localhost"].includes(r.hostname)&&e.push(`publicUrl uses plain http on a non-loopback address (${t.relay.publicUrl}); terminate TLS in front of the relay`),e}function Be({argv:t=[],env:e=process.env}={}){let{options:s,help:r,version:n,errors:i}=xn(t),o=gn(x),a=s.config||e.HERDR_RELAY_CONFIG||null;if(a){let c=Sn(we.resolve(a));if(c===null)throw new Error(`relay config not found: ${a}`);En(o,c)}bn(o,e),Tn(o,s);let l=wn(o);return{config:l,help:r,version:n,errors:i,configFile:a,warnings:An(l)}}import Xo from"node:http";import ts from"node:path";import{URL as Ko}from"node:url";var Vi=G(tr(),1),qi=G(Ve(),1),zi=G(ue(),1),Xi=G(At(),1),Ki=G(Ot(),1),Ji=G(Mt(),1),T=G(Ke(),1),Dt=G(cr(),1);import Ut from"node:crypto";import Qi from"node:path";import fr from"node:crypto";import se from"node:fs";import Zi from"node:path";function ke(t){se.mkdirSync(t,{recursive:!0,mode:448});try{se.chmodSync(t,448)}catch{}}function ur(t,e){ke(Zi.dirname(t));let s=`${t}.${process.pid}.${fr.randomBytes(4).toString("hex")}.tmp`;se.writeFileSync(s,`${JSON.stringify(e,null,2)}
11
+ `,{mode:384});try{se.chmodSync(s,384)}catch{}se.renameSync(s,t);try{se.chmodSync(t,384)}catch{}}function dr(t,e){try{return JSON.parse(se.readFileSync(t,"utf8"))}catch(s){let{code:r,message:n}=s;return r!=="ENOENT"&&process.stderr.write(`herdr-remote: invalid state at ${t}: ${n}
12
+ `),e}}function Bt(t=32){return fr.randomBytes(t).toString("base64url")}function B(t){return Ut.createHash("sha256").update(String(t),"utf8").digest("hex")}function ye(t,e){if(typeof t!="string"||typeof e!="string")return!1;let s=Buffer.from(t,"hex"),r=Buffer.from(e,"hex");return s.length===r.length&&s.length>0&&Ut.timingSafeEqual(s,r)}function F(t=Date.now()){return new Date(t).toISOString()}function Ft(t){return typeof t=="string"&&/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(t)}var hr="ABCDEFGHJKMNPQRSTUVWXYZ23456789",eo=6;function to(){let t="";for(let e=0;e<eo;e+=1)t+=hr[Ut.randomInt(hr.length)];return t}var Ze=class{stateFile;pairingTtlMs;deviceTtlMs;maxDevices;password;pairings=new Map;lastDeviceSaveAt=new Map;state;constructor({stateFile:e,pairingTtlMs:s=600*1e3,deviceTtlMs:r=720*60*60*1e3,maxDevices:n=32,password:i=null}={}){if(!e)throw new TypeError("stateFile is required");this.stateFile=e,this.pairingTtlMs=s,this.deviceTtlMs=r,this.maxDevices=n,this.password=i||null,this.state=dr(e,{version:1,hosts:{},devices:{}}),this.state.version=1,this.state.hosts=this.state.hosts&&typeof this.state.hosts=="object"?this.state.hosts:{},this.state.devices=this.state.devices&&typeof this.state.devices=="object"?this.state.devices:{},ke(Qi.dirname(e))}save(){ur(this.stateFile,this.state)}checkPassword(e){return this.password?typeof e=="string"&&ye(B(e),B(this.password)):!0}registerHost(e,s,r=null,n=Date.now()){if(!Ft(e)||typeof s!="string"||s.length<16||s.length>4096)return{ok:!1,code:"invalid_host_credentials",message:"hostId and token are required"};if(!this.checkPassword(r))return{ok:!1,code:"relay_password_required",message:"the relay password is missing or wrong"};let i=this.state.hosts[e];return i?ye(i.tokenHash,B(s))?(i.lastSeenAt=F(n),this.save(),{ok:!0,hostId:e,firstSeen:!1}):{ok:!1,code:"host_auth_failed",message:"host token is invalid"}:(this.state.hosts[e]={tokenHash:B(s),createdAt:F(n),lastSeenAt:F(n)},this.save(),{ok:!0,hostId:e,firstSeen:!0})}authenticateHost(e,s){if(!Ft(e)||typeof s!="string"||s.length<16||s.length>4096)return!1;let r=this.state.hosts[e];return!!r&&ye(r.tokenHash,B(s))}hostCount(){return Object.keys(this.state.hosts).length}startPairing(e,s,r=Date.now()){if(!Ft(e)||!this.state.hosts[e])throw Object.assign(new Error("host is not connected or enrolled"),{code:"host_not_found"});this.cleanup(r);let n;do n=to();while([...this.pairings.values()].some(o=>ye(o.codeHash,B(n))));let i=r+this.pairingTtlMs;return this.pairings.set(n,{codeHash:B(n),hostId:e,expiresAt:i,publicUrl:s}),{code:n,hostId:e,publicUrl:s,expiresAt:i,expiresAtIso:F(i)}}completePairing(e,s=Date.now()){if(typeof e!="string"||e.length<4||e.length>32)return null;this.cleanup(s);let r=e.trim().toUpperCase(),n=this.pairings.get(r);if(!n||n.expiresAt<=s||!ye(n.codeHash,B(r)))return null;this.pairings.delete(r);let i=Object.values(this.state.devices);i.length>=this.maxDevices&&(i.sort((c,f)=>(c.lastSeenAt||"").localeCompare(f.lastSeenAt||"")),delete this.state.devices[i[0].deviceId]);let o=`device-${Bt(9)}`,a=Bt(32),l=s+this.deviceTtlMs;return this.state.devices[o]={deviceId:o,hostId:n.hostId,tokenHash:B(a),createdAt:F(s),lastSeenAt:F(s),expiresAt:l},this.save(),{deviceId:o,hostId:n.hostId,token:a,expiresAt:l,expiresAtIso:F(l),publicUrl:n.publicUrl}}noteDeviceSeen(e,{userAgent:s,ip:r}={},n=Date.now()){let i=this.state.devices[e];if(!i)return null;let o=!1;return s&&i.userAgent!==s&&(i.userAgent=String(s).slice(0,256),o=!0),r&&i.lastIp!==r&&(i.lastIp=String(r).slice(0,64),o=!0),i.lastSeenAt=F(n),o&&this.save(),{...i}}listDevices(e=Date.now()){return Object.values(this.state.devices).filter(s=>s&&s.expiresAt>e).map(s=>({deviceId:s.deviceId,hostId:s.hostId,createdAt:s.createdAt,lastSeenAt:s.lastSeenAt,expiresAt:s.expiresAt,expiresAtIso:F(s.expiresAt),userAgent:s.userAgent||null,lastIp:s.lastIp||null})).sort((s,r)=>String(r.lastSeenAt||"").localeCompare(String(s.lastSeenAt||"")))}revokeDevice(e){if(typeof e!="string"||!e)return null;let s=this.state.devices[e];return s?(delete this.state.devices[e],this.lastDeviceSaveAt.delete(e),this.save(),{deviceId:s.deviceId,hostId:s.hostId,userAgent:s.userAgent||null,lastIp:s.lastIp||null}):null}authenticateDevice(e,s=Date.now()){if(typeof e!="string"||e.length<16)return null;let r=B(e);for(let n of Object.values(this.state.devices)){if(n.expiresAt<=s||!ye(n.tokenHash,r))continue;n.lastSeenAt=F(s),n.expiresAt=s+this.deviceTtlMs;let i=this.lastDeviceSaveAt.get(n.deviceId)||0;return s-i>=60*1e3&&(this.lastDeviceSaveAt.set(n.deviceId,s),this.save()),{...n}}return null}cleanup(e=Date.now()){let s=0;for(let[n,i]of Object.entries(this.state.devices))(!i||i.expiresAt<=e)&&(delete this.state.devices[n],this.lastDeviceSaveAt.delete(n),s+=1);let r=0;for(let[n,i]of this.pairings.entries())i.expiresAt<=e&&(this.pairings.delete(n),r+=1);return s&&this.save(),{removedDevices:s,removedPairings:r}}deviceCount(){return Object.keys(this.state.devices).length}};import Qe from"node:os";import{monitorEventLoopDelay as so}from"node:perf_hooks";function et(t,e=0){return Number.isFinite(t)?t:e}function q(t,e,s){return!s||s<=0?0:Math.max(0,(t-e)*1e3/s)}function st(t=[]){let e=new Set;for(let s of t)s&&e.add(typeof s.deviceId=="string"&&s.deviceId?`device:${s.deviceId}`:`client:${s.id}`);return e.size}var tt=class{version;protocolVersion;startedAt;bytesIn;bytesOut;framesIn;framesOut;cleanup;lastSample;hostTraffic;cpuSampleAt;cpuSample;eventLoop;constructor({version:e="0.1.0",protocolVersion:s=1}={}){this.version=e,this.protocolVersion=s,this.startedAt=Date.now(),this.bytesIn=0,this.bytesOut=0,this.framesIn=0,this.framesOut=0,this.cleanup={staleClientsPurged:0,closedPtysCleaned:0,deadConnectionsClosed:0,idleHostsTerminated:0,slowClientsDropped:0,lastCleanupAt:null},this.lastSample={at:this.startedAt,bytesIn:0,bytesOut:0,framesIn:0,framesOut:0},this.hostTraffic=new Map,this.cpuSampleAt=process.hrtime.bigint(),this.cpuSample=process.cpuUsage(),this.eventLoop=so({resolution:20}),this.eventLoop.enable()}hostCounter(e){if(typeof e!="string"||e.length===0)return null;let s=this.hostTraffic.get(e);return s||(s={bytesIn:0,bytesOut:0,framesIn:0,framesOut:0,sampleAt:Date.now(),sampleBytesIn:0,sampleBytesOut:0,sampleFramesIn:0,sampleFramesOut:0},this.hostTraffic.set(e,s)),s}recordIn(e,s=null){let r=Math.max(0,Number(e)||0);this.bytesIn+=r,this.framesIn+=1;let n=this.hostCounter(s);n&&(n.bytesIn+=r,n.framesIn+=1)}recordOut(e,s=null){let r=Math.max(0,Number(e)||0);this.bytesOut+=r,this.framesOut+=1;let n=this.hostCounter(s);n&&(n.bytesOut+=r,n.framesOut+=1)}forgetHost(e){typeof e=="string"&&this.hostTraffic.delete(e)}hostThroughput(e,s=Date.now()){let r=this.hostCounter(e);if(!r)return{bytesIn:0,bytesOut:0,bytesInPerSec:0,bytesOutPerSec:0,framesIn:0,framesOut:0,framesInPerSec:0,framesOutPerSec:0};let n=s-r.sampleAt,i={bytesIn:r.bytesIn,bytesOut:r.bytesOut,bytesInPerSec:q(r.bytesIn,r.sampleBytesIn,n),bytesOutPerSec:q(r.bytesOut,r.sampleBytesOut,n),framesIn:r.framesIn,framesOut:r.framesOut,framesInPerSec:q(r.framesIn,r.sampleFramesIn,n),framesOutPerSec:q(r.framesOut,r.sampleFramesOut,n)};return r.sampleAt=s,r.sampleBytesIn=r.bytesIn,r.sampleBytesOut=r.bytesOut,r.sampleFramesIn=r.framesIn,r.sampleFramesOut=r.framesOut,i}recordCleanup(e,s=1){Object.hasOwn(this.cleanup,e)&&typeof this.cleanup[e]=="number"&&(this.cleanup[e]+=s),this.cleanup.lastCleanupAt=new Date().toISOString()}cpuPercent(){let e=process.hrtime.bigint(),s=Number(e-this.cpuSampleAt),r=process.cpuUsage(this.cpuSample);if(this.cpuSampleAt=e,this.cpuSample=process.cpuUsage(),s<=0)return 0;let n=(r.user+r.system)*1e5/s;return Math.max(0,Math.round(n*100)/100)}eventLoopDelay(){let e=s=>Math.round(et(s/1e6)*100)/100;return{p50Ms:e(this.eventLoop.percentile(50)),p90Ms:e(this.eventLoop.percentile(90)),p99Ms:e(this.eventLoop.percentile(99)),maxMs:e(this.eventLoop.max),meanMs:e(this.eventLoop.mean)}}snapshot({clients:e=[],hosts:s=[],ptys:r=[],sample:n=!0,scopeHostId:i=null,activeUserCount:o=null}={}){let a=Date.now(),l=a-this.lastSample.at,c={bytesIn:this.bytesIn,bytesOut:this.bytesOut,bytesInPerSec:q(this.bytesIn,this.lastSample.bytesIn,l),bytesOutPerSec:q(this.bytesOut,this.lastSample.bytesOut,l),framesIn:this.framesIn,framesOut:this.framesOut,framesInPerSec:q(this.framesIn,this.lastSample.framesIn,l),framesOutPerSec:q(this.framesOut,this.lastSample.framesOut,l)};n&&(this.lastSample={at:a,bytesIn:this.bytesIn,bytesOut:this.bytesOut,framesIn:this.framesIn,framesOut:this.framesOut});let f=process.memoryUsage(),d=Qe.loadavg(),u=e[0],h=i?this.hostThroughput(i,a):c;return{version:this.version,protocolVersion:this.protocolVersion,uptimeSeconds:Math.floor((a-this.startedAt)/1e3),startTime:new Date(this.startedAt).toISOString(),serverTime:new Date(a).toISOString(),activeControllerId:null,activeHostId:u?.hostId||s[0]?.id||null,clients:e,hosts:s,ptys:r,clientCount:e.length,hostCount:s.length,ptyCount:r.length,activeUserCount:Number.isFinite(o)?o:st(e),throughput:h,cpu:{load1m:et(d[0]),load5m:et(d[1]),load15m:et(d[2]),cpuPercent:this.cpuPercent(),cores:Qe.cpus().length},memory:{rssBytes:f.rss,heapUsedBytes:f.heapUsed,heapTotalBytes:f.heapTotal,externalBytes:f.external,systemTotalBytes:Qe.totalmem(),systemFreeBytes:Qe.freemem()},eventLoopDelay:this.eventLoopDelay(),cleanup:{...this.cleanup}}}close(){this.eventLoop.disable(),this.hostTraffic.clear()}};function Le(t){return Buffer.isBuffer(t)?t:(typeof t=="string"||t instanceof ArrayBuffer,Buffer.from(t))}function pr(t,e,s=Buffer.alloc(0)){if(typeof t!="string"||!t||typeof e!="string"||!e)throw new TypeError("type and streamId must be non-empty strings");let r=Le(s),n=Buffer.from(JSON.stringify({type:t,streamId:e}),"utf8");if(n.length>8192)throw new RangeError("stream frame header is too large");let i=Buffer.allocUnsafe(4);return i.writeUInt32BE(n.length,0),Buffer.concat([i,n,r])}function ro(t){let e=Le(t);if(e.length<4)throw new Error("stream frame is truncated");let s=e.readUInt32BE(0);if(s===0||s>8192||e.length<4+s)throw new Error("stream frame header is invalid");let r;try{r=JSON.parse(e.subarray(4,4+s).toString("utf8"))}catch(n){throw new Error(`stream frame header is not JSON: ${n.message}`)}if(!r||typeof r.type!="string"||typeof r.streamId!="string")throw new Error("stream frame header is missing routing fields");return{version:1,type:r.type,streamId:r.streamId,payload:e.subarray(4+s)}}function mr(t,e,s=Buffer.alloc(0)){let r=t;if(t==="output"?r=0:t==="input"&&(r=1),r!==0&&r!==1)throw new TypeError("type must be FRAME_TYPE_OUTPUT (0) or FRAME_TYPE_INPUT (1)");if(!Number.isInteger(e)||e<0||e>65535)throw new RangeError("streamIndex must be an unsigned 16-bit integer (0-65535)");let n=Le(s),i=Buffer.allocUnsafe(4+n.length);return i.writeUInt8(255,0),i.writeUInt8(r,1),i.writeUInt16BE(e,2),n.copy(i,4),i}function no(t){let e=Le(t);if(e.length<4)throw new Error("v2 stream frame is truncated");if(e.readUInt8(0)!==255)throw new Error("invalid v2 stream frame magic byte");let r=e.readUInt8(1);if(r!==0&&r!==1)throw new Error(`unknown v2 stream frame type: ${r}`);let n=e.readUInt16BE(2);return{version:2,type:r===0?"output":"input",typeCode:r,streamIndex:n,payload:e.subarray(4)}}function _r(t){let e=Le(t);if(e.length<4)throw new Error("stream frame is truncated");return e[0]===255?no(e):ro(e)}var yr=["black","red","green","yellow","blue","magenta","cyan","white","brightBlack","brightRed","brightGreen","brightYellow","brightBlue","brightMagenta","brightCyan","brightWhite"],io=["regular","bold","italic","boldItalic"],oo=["truetype","opentype"],ao=["cjk","all"];var lo=/^#[0-9a-f]{6}$/i,co=/["'\\;,{}<>@\u0000-\u001f\u007f]/,gr=/^[0-9a-f]{64}$/;function Me(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function Ht(t,e){return t.includes(e)}function Sr(t){return typeof t=="string"&&lo.test(t)?t.toLowerCase():void 0}function Er(t){if(!Me(t))return null;let e={};for(let r of["background","foreground","cursor"]){let n=Sr(t[r]);n&&(e[r]=n)}let s=t.ansi;if(Me(s)){let r={};for(let n of yr){let i=Sr(s[n]);i&&(r[n]=i)}Object.keys(r).length===yr.length&&(e.ansi=r)}return Object.keys(e).length>0?e:null}function xr(t){let e=typeof t=="string"?t.trim():"";return!e||e.length>128||co.test(e)?null:e}function rt(t){if(!Me(t))return null;let e=xr(t.family);if(!e)return null;let s=Number(t.sizePx),r=Number.isFinite(s)&&s>=4&&s<=96?Math.round(s*10)/10:null,n=typeof t.source=="string"&&/^[a-z0-9-]{1,32}$/.test(t.source)?t.source:null,i=[],o=new Set;for(let l of Array.isArray(t.faces)?t.faces.slice(0,16):[]){if(!Me(l))continue;let{style:c,format:f,bytes:d,sha256:u}=l;!Ht(io,c)||o.has(c)||Ht(oo,f)&&(typeof d!="number"||!Number.isInteger(d)||d<=0||d>16777216||typeof u!="string"||!gr.test(u)||(o.add(c),i.push({style:c,format:f,bytes:d,sha256:u})))}let a=[];for(let l of Array.isArray(t.subsets)?t.subsets.slice(0,16):[]){if(!Me(l))continue;let c=xr(l.family),{scope:f,sha256:d}=l;!c||l.style!=="regular"||Ht(ao,f)&&(typeof d!="string"||!gr.test(d)||a.some(u=>u.scope===f)||a.push({family:c,style:"regular",scope:f,sha256:d}))}return{family:e,...r!==null&&{sizePx:r},...n!==null&&{source:n},faces:i,subsets:a}}var fo=8192;function br(t){if(typeof t!="string"||t.length>fo)return null;let e;try{e=new URL(t)}catch{return null}return e.protocol==="http:"||e.protocol==="https:"?t:null}var uo=/^[\x21-\x7e]+$/;function Tr(t){if(!Array.isArray(t))return;let e=new Set;for(let s of t){if(e.size>=8)break;if(typeof s!="string")continue;let r=s.replace(/\s+/g,"").toLowerCase();r.length<=32&&uo.test(r)&&e.add(r)}return e.size>0?[...e]:void 0}var $t="/ws/host",wr="/ws/client",z={hostHandoff:"host_handoff",idleHeartbeat:"idle_heartbeat",binaryFrameV2:"binary_frame_v2",adminTabs:"admin_tabs",pasteAnyFile:"paste_any_file",openLink:"open_link"};var Ar="application/octet-stream";function Ir(t){if(typeof t!="string")return"file";let s=(t.normalize("NFC").split(/[\\/]/).pop()??"").replace(/[^\p{L}\p{N}._-]+/gu,"_").replace(/^[._]+|[._]+$/g,"");if([...s].length>120){let r=s.lastIndexOf("."),n=r>0&&s.length-r<=16?s.slice(r):"";s=[...s.slice(0,s.length-n.length)].slice(0,120-n.length).join("")+n}return s||"file"}var vr={"image/png":".png","image/jpeg":".jpg","image/webp":".webp","image/gif":".gif"},Ha=Object.keys(vr);function Or(t){return typeof t=="string"&&Object.hasOwn(vr,t)}function Cr(t,e){switch(t){case"image/png":return e.length>=8&&e[0]===137&&e[1]===80&&e[2]===78&&e[3]===71;case"image/jpeg":return e.length>=3&&e[0]===255&&e[1]===216&&e[2]===255;case"image/webp":return e.length>=12&&e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70&&e[8]===87&&e[9]===69&&e[10]===66&&e[11]===80;case"image/gif":return e.length>=6&&e[0]===71&&e[1]===73&&e[2]===70&&e[3]===56;default:return!1}}var ho="dibin666/herdr-remote",Pr=`https://github.com/${ho}/releases`,Ya=`${Pr}/latest/download/latest.json`,Wa=`${Pr}/latest/download/herdr-remote.tgz`;import po from"node:crypto";var mo=500;function ge(t){return`${t}-${po.randomBytes(9).toString("base64url")}`}function X(t,e){return typeof t=="string"&&t.length>0?t.slice(0,e):null}function Ne(t,e){let s=Number(t);return Number.isInteger(s)?Math.min(mo,Math.max(2,s)):e}function y(t){return!!t&&t?.readyState===T.default.OPEN}function p(t,e){y(t)&&t.send(JSON.stringify(e))}function k(t,e=1e3,s=""){if(!(!t||t.readyState===T.default.CLOSED||t.readyState===T.default.CLOSING))try{t.close(e,s.slice(0,120))}catch{}}function re(t){if(!(!t||t.readyState===T.default.CLOSED))try{typeof t.terminate=="function"?t.terminate():typeof t.destroy=="function"&&t.destroy()}catch{}}function Se(t){if(typeof t!="string")return null;try{return JSON.parse(t)}catch{return null}}function w(t,e,s="invalid_handshake"){p(t,{type:"error",code:s,message:e}),k(t,1008,e)}var kr=4,Lr=3e4,Mr=Math.ceil(262144/3)*4,Yt=/^[0-9a-f]{64}$/,_o=32*1024,yo=64,go=16*1024*1024,Nr=/^[A-Za-z0-9_-]{1,32}$/;function Wt(t){Array.isArray(t.fontChunkRequests)&&t.fontChunkRequests.length&&t.fontChunkRequests.shift()}function nt(t){Array.isArray(t.fontSubsetRequests)&&t.fontSubsetRequests.length&&t.fontSubsetRequests.shift()}function Dr(t,e,s){if(!e.session||!y(t.ws))return;let r=t.terminalFont?.faces?.find(a=>a.sha256===s.sha256),n=r?r.bytes:e.fontSubsets?.get(s.sha256)||0,i=Math.ceil(n/262144);if(!n||!Number.isInteger(s.index)||s.index<0||s.index>=i){p(e.ws,{type:"error",code:"host_font_unavailable",message:"The workstation did not offer this font file"});return}let o=Date.now();e.fontChunkRequests=(e.fontChunkRequests||[]).filter(a=>o-a<Lr),!(e.fontChunkRequests.length>=kr)&&(e.fontChunkRequests.push(o),p(t.ws,{type:"host_font_chunk_request",clientId:e.session.streamId,streamId:e.session.streamId,sha256:s.sha256,index:s.index}))}function Br(t,e,s){if(!e.session||!y(t.ws))return;if(!(t.terminalFont?.subsets?.some(o=>o.sha256===s.sha256)&&typeof s.text=="string"&&s.text.length>0&&s.text.length<=_o&&typeof s.requestId=="string"&&Nr.test(s.requestId))){p(e.ws,{type:"error",code:"host_font_unavailable",message:"The workstation did not offer this font"});return}let i=Date.now();e.fontSubsetRequests=(e.fontSubsetRequests||[]).filter(o=>i-o<Lr),!(e.fontSubsetRequests.length>=kr)&&(e.fontSubsetRequests.push(i),p(t.ws,{type:"host_font_subset_request",clientId:e.session.streamId,streamId:e.session.streamId,requestId:s.requestId,sha256:s.sha256,text:s.text}))}function Fr(t,e){if(nt(t),!!(typeof e.sha256=="string"&&Yt.test(e.sha256)&&typeof e.subsetSha=="string"&&Yt.test(e.subsetSha)&&typeof e.requestId=="string"&&Nr.test(e.requestId)&&Number.isInteger(e.bytes)&&e.bytes>0&&e.bytes<=go&&(e.dataBase64===void 0||typeof e.dataBase64=="string"&&e.dataBase64.length<=Mr))){if(e.dataBase64===void 0)for(t.fontSubsets||=new Map,t.fontSubsets.delete(e.subsetSha),t.fontSubsets.set(e.subsetSha,e.bytes);t.fontSubsets.size>yo;){let r=t.fontSubsets.keys().next().value;r!==void 0&&t.fontSubsets.delete(r)}p(t.ws,{type:"host_font_subset_ready",requestId:e.requestId,sha256:e.sha256,subsetSha:e.subsetSha,bytes:e.bytes,...e.dataBase64!==void 0?{dataBase64:e.dataBase64}:{}})}}function Ur(t,e){Wt(t),typeof e.sha256=="string"&&Yt.test(e.sha256)&&Number.isInteger(e.index)&&e.index>=0&&Number.isInteger(e.total)&&e.total>e.index&&typeof e.dataBase64=="string"&&e.dataBase64.length<=Mr&&p(t.ws,{type:"host_font_chunk",sha256:e.sha256,index:e.index,total:e.total,dataBase64:e.dataBase64})}import Gt from"node:crypto";function So(t){let e=t.headers.authorization;if(typeof e!="string")return null;let s=/^Bearer\s+(.+)$/i.exec(e.trim());return s?s[1]:null}function xo(t,e){if(typeof t!="string"||t.length===0||typeof e!="string"||e.length===0)return!1;let s=Gt.createHash("sha256").update(t,"utf8").digest(),r=Gt.createHash("sha256").update(e,"utf8").digest();return Gt.timingSafeEqual(s,r)}function jt(t,e,s){if(!e||(t.config.relay.allowedOrigins||[]).includes(e))return!0;try{return new URL(e).host===s.headers.host}catch{return!1}}function Hr(t,e){let s=e.headers.origin;return s?jt(t,s,e):!0}function Vt(t,e){let s=e.headers["x-herdr-host-id"],r=e.headers["x-herdr-host-token"];return typeof s!="string"||typeof r!="string"?null:t.auth.authenticateHost(s,r)?s:null}function Eo(t,e){let s=So(e);return s?t.auth.authenticateDevice(s):null}function $r(t,e){let s=e.headers["x-herdr-host-id"],r=e.headers["x-herdr-host-token"],n=s!==void 0||r!==void 0,i=e.headers.authorization!==void 0,o=Vt(t,e),a=Eo(t,e);return n&&!o||i&&!a||o&&a&&o!==a.hostId?null:o?{kind:"host",hostId:o}:a?{kind:"device",hostId:a.hostId,deviceId:a.deviceId}:null}function Yr(t,e){return xo(e.headers["x-relay-admin-token"],t.adminToken)}function Wr(t,e){if(!t.trustProxy)return null;let s=e.headers["x-forwarded-for"];return typeof s!="string"||s.length===0?null:s.split(",")[0].trim()||null}function bo(t,e){return Wr(t,e)||e.socket.remoteAddress||"unknown"}function Gr(t,e){return Wr(t,e)||e.socket.remoteAddress||null}function qt(t,e,s,r=20){let n=bo(t,s),i=Date.now(),o=e.get(n);if(!o||i-o.startedAt>=6e4){if(e.size>=4096){let a=e.keys().next().value;a!==void 0&&e.delete(a)}return e.set(n,{startedAt:i,count:1}),!0}return o.count>=r?!1:(o.count+=1,!0)}function it(t,e){return qt(t,t.pairAttempts,e,20)}function jr(t,e){return qt(t,t.clientHandshakeAttempts,e,60)}function Vr(t,e){return qt(t,t.hostHandshakeAttempts,e,60)}function xe(t){!t||!y(t.ws)||p(t.ws,{type:"client_count",clientCount:t.clients.size})}function qr(t,e,s,r){if(!s||!y(s.ws))return!1;let n=t.config.relay.maxBufferedBytesPerClient;if((Number(s.ws.bufferedAmount)||0)+r.length>n)return t.metrics.recordCleanup("slowClientsDropped"),C(t,s,{notify:!0,reason:"slow_client",closeCode:1013}),!1;let o=!1,a=()=>{if(y(s.ws))try{s.ws.send(r),s.bytesSent+=r.length,t.metrics.recordOut(r.length,e.id),o=!0}catch{C(t,s,{notify:!1,reason:"client_send_failed",closeCode:1011})}};return t.devLatencyMs>0?zt(t,s.ws,a):a(),t.devLatencyMs>0?!0:o}function zt(t,e,s){let r=t.sendQueues.get(e);if(!r){let i={items:[],timer:null};r=i,t.sendQueues.set(e,i),e.once("close",()=>{i.timer&&(clearTimeout(i.timer),t.activeDelayTimers.delete(i.timer),i.timer=null),i.items=[]})}let n=Date.now()+t.devDelayMs;if(r.items.push({sendAt:n,task:s}),!r.timer){let i=r,o=setTimeout(()=>zr(t,e,i),t.devDelayMs);r.timer=o,t.activeDelayTimers.add(o)}}function zr(t,e,s){s.timer&&(t.activeDelayTimers.delete(s.timer),s.timer=null);let r=Date.now();for(;s.items.length>0&&s.items[0].sendAt<=r;){let n=s.items.shift();try{n?.task()}catch{}}if(s.items.length>0&&!s.timer){let n=Math.max(0,s.items[0].sendAt-Date.now()),i=setTimeout(()=>zr(t,e,s),n);s.timer=i,t.activeDelayTimers.add(i)}}function K(t,e,s){for(let r of[...e.clients]){let n=t.clients.get(r);if(!n)continue;let i=s(n);i&&p(n.ws,i)}}var Xt=20,Kt=6;function To(t){if(!t)return null;let e=65536;for(let s=0;s<e;s++){let r=t.nextStreamIndex;if(t.nextStreamIndex=t.nextStreamIndex+1&65535,!t.streamIndices.has(r))return r}return null}function Ee(t,e,s){let r=s.session;r&&(r.streamIndex!==null&&r.streamIndex!==void 0&&e&&e.streamIndices.delete(r.streamIndex),t.streams.delete(r.streamId),s.session=null)}function ot(t,e,s,{restarted:r=!1}={}){if(!s||!y(e.ws))return;let n=ge("session"),i=null;e.binaryFrameV2&&(i=To(e),i!==null&&e.streamIndices.set(i,s.id)),s.session={streamId:n,streamIndex:i,cols:s.cols,rows:s.rows,ready:!1},t.streams.set(n,s.id),p(e.ws,{type:"session_start",clientId:n,streamId:n,cols:Math.max(Xt,s.cols),rows:Math.max(Kt,s.rows),role:"controller",...i!==null?{streamIndex:i}:{}}),r&&p(s.ws,{type:"session_restarted",streamId:n,cols:s.cols,rows:s.rows,hostname:e.hostname,platform:e.platform,...e.shellProfile?{shellProfile:e.shellProfile}:{},adminTerminalSupported:e.adminTabsAvailable,terminalPalette:e.terminalPalette||null,terminalFont:e.terminalFont||null,hostVersion:e.version,...e.herdrPrefixKeys?{herdrPrefixKeys:e.herdrPrefixKeys}:{}})}function Jt(t,e){for(let s of e.clients){let r=t.clients.get(s);r&&(r.role="controller",r.controllerId=null,p(r.ws,{type:"control_state",role:"controller",controllerId:null,clientCount:e.clients.size}))}}function Xr(t,e){if(!e)return 0;let s=0;for(let r of[...t.clients.values()])!r||r.deviceId!==e||(C(t,r,{notify:!1,reason:"device_revoked"}),k(r.ws,1e3,"this device has been revoked by the relay operator"),s+=1);return s}function C(t,e,{notify:s=!0,reason:r="client_disconnected",closeCode:n=1e3,terminate:i=!1}={}){if(!e||!t.clients.has(e.id))return;t.clients.delete(e.id);let o=t.hosts.get(e.hostId);if(e.session){let l=e.session.streamId;Ee(t,o,e),o&&y(o.ws)&&p(o.ws,{type:"session_stop",clientId:l,streamId:l})}o&&(o.clients.delete(e.id),xe(o),Jt(t,o),o.clients.size===0&&(o.controllerId=null,o.reconnecting&&M(t,o,{notify:!1,reason:"no_clients"})));let a=e.ws;e.ws=null,s&&p(a,{type:"error",code:r,message:r==="host_offline"?"Herdr host is offline":"connection closed"}),i||a?.readyState===T.default.CLOSING?re(a):k(a,n,r),t.metrics.recordCleanup("closedPtysCleaned")}function M(t,e,{notify:s=!0,reason:r="host_disconnected",terminate:n=!1}={}){if(!e||t.hosts.get(e.id)!==e)return;e.reconnectTimer&&clearTimeout(e.reconnectTimer),e.reconnectTimer=null,t.hosts.delete(e.id);for(let o of[...e.clients]){let a=t.clients.get(o);if(!a)continue;t.clients.delete(a.id),Ee(t,e,a);let l=a.ws;a.ws=null,s&&p(l,{type:"error",code:r,message:"Herdr host disconnected"}),n||l?.readyState===T.default.CLOSING?re(l):k(l,1012,r)}e.clients.clear(),t.metrics.forgetHost(e.id);let i=e.ws;e.ws=null,n||i?.readyState===T.default.CLOSING?re(i):k(i,1e3,r)}function at(t,e){if(!e?.handoffCapable||e.clients.size===0)return!1;for(let s of e.clients)if(!t.clients.get(s)?.handoffCapable)return!1;return!0}function lt(t,e,s="host_disconnected"){if(!e||t.hosts.get(e.id)!==e||e.reconnecting)return;if(!at(t,e)){M(t,e,{notify:!0,reason:s});return}e.ws=null,e.reconnecting=!0,e.reconnectStartedAt=Date.now(),e.lastSeenAt=Date.now(),e.load={},e.ptys=[];for(let n of e.clients){let i=t.clients.get(n);i&&Ee(t,e,i)}K(t,e,()=>({type:"host_reconnecting",code:s}));let r=setTimeout(()=>{e.reconnectTimer=null,t.hosts.get(e.id)===e&&e.reconnecting&&M(t,e,{notify:!0,reason:"host_reconnect_timeout"})},t.config.relay.hostReconnectGraceMs);e.reconnectTimer=r,r.unref?.()}var Io=3e3,vo=2e3,Oo=1e3;function Co(t,e){if(typeof e!="string"||e.length===0)return!1;let s;try{s=Buffer.from(e.slice(0,32),"base64")}catch{return!1}return s.length===0?!1:Cr(t,s)}function Kr(t,e,s){let r={ws:e,req:s,authenticated:!1},n=setTimeout(()=>{r.authenticated||k(e,1008,"client hello timeout")},1e4);e.isAlive=!0,e.on("pong",()=>{e.isAlive=!0,r.client&&(r.client.lastSeenAt=Date.now(),r.client.lastPingAt=new Date().toISOString())}),e.on("ping",()=>{e.isAlive=!0,r.client&&(r.client.lastSeenAt=Date.now(),r.client.lastPingAt=new Date().toISOString())}),e.on("message",(i,o)=>{if(!r.authenticated){if(o)return w(e,"client hello must be JSON");let a=Se(i.toString());if(a?.type!=="hello"||a.protocol!==1)return w(e,"invalid client hello");if(!jr(t,s))return w(e,"too many connection attempts","rate_limited");let l=null,c=null;if(a.pairCode){if(!it(t,s))return w(e,"too many pairing attempts","rate_limited");c=t.auth.completePairing(a.pairCode)}if(c?l=c:a.token&&(l=t.auth.authenticateDevice(a.token)),!l)return w(e,"valid device token or pairing code required","auth_required");let f=t.hosts.get(l.hostId);if(!f||f.reconnecting||!y(f.ws))return w(e,"paired Herdr host is offline",f?.reconnecting?"host_reconnecting":"host_offline");if(f.clients.size>=t.config.relay.maxClientsPerHost)return w(e,"host client limit reached","too_many_clients");clearTimeout(n),t.finishHandshake(e);let u={id:ge("client"),ws:e,hostId:f.id,deviceId:l.deviceId,browserClientId:typeof a.clientId=="string"?a.clientId.slice(0,128):null,handoffCapable:Array.isArray(a.capabilities)&&a.capabilities.includes(z.hostHandoff),session:null,role:"controller",controllerId:null,connectedAt:new Date().toISOString(),connectedAtMs:Date.now(),lastSeenAt:Date.now(),lastPingAt:null,bytesReceived:0,bytesSent:0,ip:Gr(t,s),userAgent:String(s.headers["user-agent"]||"").slice(0,256),cols:Ne(a.cols,80),rows:Ne(a.rows,24)};u.controllerId=null,t.auth.noteDeviceSeen(l.deviceId,{userAgent:u.userAgent,ip:u.ip}),r.authenticated=!0,r.client=u,t.clients.set(u.id,u),f.clients.add(u.id),xe(f),e.isAlive=!0,c&&p(e,{type:"paired",token:c.token,deviceId:c.deviceId,hostId:c.hostId,expiresAt:c.expiresAtIso}),p(e,{type:"ready",role:u.role,controllerId:null,hostId:f.id,hostname:f.hostname,platform:f.platform,...f.shellProfile?{shellProfile:f.shellProfile}:{},adminTerminalSupported:f.adminTabsAvailable,clientId:u.id,terminalPalette:f.terminalPalette||null,terminalFont:f.terminalFont||null,clientCount:f.clients.size,hostVersion:f.version,...f.herdrPrefixKeys?{herdrPrefixKeys:f.herdrPrefixKeys}:{}}),f.agentStatus&&p(e,f.agentStatus),f.updateStatus&&p(e,f.updateStatus),ot(t,f,u),Jt(t,f);return}r.client&&Po(t,r.client,i,o)}),e.on("close",()=>{clearTimeout(n),r.client&&C(t,r.client,{notify:!0})}),e.on("error",()=>{})}function Po(t,e,s,r){e.lastSeenAt=Date.now();let n=t.hosts.get(e.hostId);if(!n){C(t,e,{notify:!0,reason:"host_offline"});return}if(r){let o=s;if(o.length>t.config.relay.maxPayloadBytes||!e.session)return;let a=n.binaryFrameV2&&typeof e.session.streamIndex=="number"?mr(1,e.session.streamIndex,o):pr("input",e.session.streamId,o);if(y(n.ws)){let l=()=>{if(y(n.ws))try{n.ws.send(a),e.bytesReceived+=o.length,t.metrics.recordIn(o.length,n.id)}catch{lt(t,n,"host_send_failed")}};t.devLatencyMs>0?zt(t,n.ws,l):l()}return}let i=Se(s.toString());if(!i){p(e.ws,{type:"error",code:"invalid_json",message:"message must be JSON"});return}if(i.type==="ping")e.lastPingAt=new Date().toISOString(),p(e.ws,{type:"pong"});else if(i.type==="resize")e.cols=Ne(i.cols,e.cols),e.rows=Ne(i.rows,e.rows),e.session&&(e.session.cols=e.cols,e.session.rows=e.rows,y(n.ws)&&p(n.ws,{type:"resize",clientId:e.session.streamId,streamId:e.session.streamId,cols:Math.max(Xt,e.cols),rows:Math.max(Kt,e.rows)}));else if(i.type==="herdr_start"){if(!e.session){p(e.ws,{type:"error",code:"no_session",message:"terminal session is not ready"});return}let o=Date.now();if(e.herdrStartAt&&o-e.herdrStartAt<Io)return;e.herdrStartAt=o,y(n.ws)&&p(n.ws,{type:"herdr_start",clientId:e.session.streamId,streamId:e.session.streamId})}else if(i.type==="admin_tab_open"){if(!e.session||!y(n.ws))return;if(!n.adminTabsAvailable){p(e.ws,{type:"error",code:"admin_terminal_unsupported",message:"Update the host connector to open administrator terminals."});return}let o=Date.now();if(e.adminTabAt&&o-e.adminTabAt<Oo)return;e.adminTabAt=o,p(n.ws,{type:"admin_tab_open",clientId:e.session.streamId,streamId:e.session.streamId})}else if(i.type==="host_font_chunk_request")Dr(n,e,i);else if(i.type==="host_font_subset_request")Br(n,e,i);else if(i.type==="host_font_refresh"){if(!e.session||!y(n.ws))return;let o=Date.now();if(e.fontRefreshAt&&o-e.fontRefreshAt<vo)return;e.fontRefreshAt=o,p(n.ws,{type:"host_font_refresh",clientId:e.session.streamId,streamId:e.session.streamId})}else if(i.type==="claim_control")e.role="controller",p(e.ws,{type:"control_granted"});else if(i.type==="release_control")p(e.ws,{type:"control_state",role:"controller",controllerId:null});else if(i.type==="paste_file"){let o=(c,f)=>p(e.ws,{type:"error",code:c,message:f});if(e.role==="viewer"){o("viewer_mode","Viewer mode cannot paste to terminal");return}let a=i.mime===Ar;if(!a&&!Or(i.mime)){o("paste_file_unsupported","Unsupported paste image format");return}if(typeof i.dataBase64!="string"){o("paste_file_unsupported","Invalid paste payload");return}let l=Buffer.byteLength(i.dataBase64,"base64");if(l===0){o("paste_file_empty","Pasted payload is empty");return}if(l>3145728){o("paste_file_too_large","Pasted payload exceeds 3 MB limit");return}if(!a&&!Co(i.mime,i.dataBase64)){o("paste_file_unsupported","Pasted image content does not match declared MIME type");return}if(!y(n?.ws)){o("host_offline","Host is offline or disconnected");return}if(a&&!n.pasteAnyFile){o("paste_file_host_outdated","Host is too old to receive files; update herdr-remote");return}if(!e.session){o("no_session","Terminal session is not ready");return}p(n.ws,{type:"paste_file",clientId:e.session.streamId,streamId:e.session.streamId,mime:i.mime,dataBase64:i.dataBase64,...a?{name:Ir(i.name)}:{}})}}import Lo from"node:os";var Ro=/^\d{1,6}\.\d{1,6}\.\d{1,6}(?:-[0-9A-Za-z.-]{1,32})?$/;function De(t){return typeof t=="string"&&Ro.test(t)?t:null}var ko=16;function Jr(t,e,s){let r={};if(s.counts&&typeof s.counts=="object")for(let[o,a]of Object.entries(s.counts))typeof a=="number"&&Number.isFinite(a)&&(r[o.slice(0,32)]=Math.max(0,Math.min(9999,Math.trunc(a))));let n=(Array.isArray(s.agents)?s.agents:[]).slice(0,ko).map(o=>({paneId:X(o?.paneId,64),workspaceId:X(o?.workspaceId,64),agent:X(o?.agent,32),title:X(o?.title,64),status:X(o?.status,16),focused:o?.focused===!0})),i={type:"agent_status",focusedPaneId:X(s.focusedPaneId,64),focusedAgent:X(s.focusedAgent,32),counts:r,total:typeof s.total=="number"&&Number.isFinite(s.total)?Math.max(0,Math.trunc(s.total)):n.length,agents:n};e.agentStatus=i,K(t,e,()=>i)}function Zr(t,e,s){let r=De(s.current),n=De(s.latest);if(!r||!n)return;let i={type:"update_status",current:r,installed:De(s.installed)||r,latest:n,updateAvailable:s.updateAvailable===!0,restartPending:s.restartPending===!0,updateCommand:s.updateCommand===!0};e.updateStatus=i,K(t,e,()=>i)}function Qr(t,e,s){e.terminalFont=rt(s.terminalFont);let r={type:"terminal_font",terminalFont:e.terminalFont||null};K(t,e,()=>r)}function Mo(t,e,s,r=new Set){let n=Array.isArray(t.capabilities)?t.capabilities:[],i=Tr(t.herdrPrefixKeys);return{id:t.hostId,ws:e,hostname:typeof t.hostname=="string"?t.hostname.slice(0,128):Lo.hostname(),platform:typeof t.platform=="string"?t.platform.slice(0,32):process.platform,...t.shellProfile==="git-bash"?{shellProfile:t.shellProfile}:{},adminTabsAvailable:n.includes(z.adminTabs),arch:typeof t.arch=="string"?t.arch.slice(0,32):process.arch,connectedAt:new Date(s.connectedAt).toISOString(),connectedAtMs:s.connectedAt,terminalPalette:Er(t.terminalPalette),terminalFont:rt(t.terminalFont),...i?{herdrPrefixKeys:i}:{},agentStatus:null,updateStatus:null,version:De(t.version),lastSeenAt:Date.now(),clients:r,controllerId:null,load:{},ptys:[],reconnecting:!1,reconnectTimer:null,connectionGeneration:ge("host-connection"),handoffCapable:n.includes(z.hostHandoff),binaryFrameV2:n.includes(z.binaryFrameV2),pasteAnyFile:n.includes(z.pasteAnyFile),streamIndices:new Map,nextStreamIndex:0,shutdownRequested:!1}}function en(t,e,s){let r={ws:e,remoteAddress:s.socket.remoteAddress,connectedAt:Date.now(),authenticated:!1},n=setTimeout(()=>{r.authenticated||k(e,1008,"host hello timeout")},1e4);e.isAlive=!0,e.on("pong",()=>{e.isAlive=!0,r.host&&(r.host.lastSeenAt=Date.now())}),e.on("ping",()=>{e.isAlive=!0,r.host&&(r.host.lastSeenAt=Date.now())}),e.on("message",(i,o)=>{if(!r.authenticated){if(o)return w(e,"host hello must be JSON");let a=Se(i.toString());if(a?.type!=="host_hello"||a.protocol!==1)return w(e,"invalid host hello");if(!Vr(t,s))return w(e,"too many connection attempts","rate_limited");let l=t.hosts.get(a.hostId);if(!l&&t.hosts.size>=t.config.relay.maxHosts)return w(e,"relay host limit reached","too_many_hosts");let c=t.auth.registerHost(a.hostId,a.token,a.password??null);if(!c.ok)return w(e,c.message,c.code);clearTimeout(n),r.authenticated=!0,t.finishHandshake(e);let f=at(t,l),d=f&&l?l.clients:new Set;if(l)if(l.reconnectTimer&&clearTimeout(l.reconnectTimer),l.reconnectTimer=null,f){for(let h of l.clients){let m=t.clients.get(h);m?.session&&(y(l.ws)&&p(l.ws,{type:"session_stop",clientId:m.session.streamId,streamId:m.session.streamId}),Ee(t,l,m))}l.load={},l.ptys=[],K(t,l,()=>({type:"host_reconnecting",code:"host_replaced"}))}else M(t,l,{notify:!0,reason:"host_replaced"});let u=Mo(a,e,r,d);if(r.host=u,t.hosts.set(u.id,u),l&&f&&k(l.ws,1e3,"host_replaced"),p(e,{type:"host_ready",protocol:1,hostId:u.id,clientCount:u.clients.size,capabilities:[z.openLink]}),xe(u),f)for(let h of u.clients){let m=t.clients.get(h);m&&ot(t,u,m,{restarted:!0})}return}r.host&&No(t,r.host,i,o)}),e.on("close",(i,o)=>{clearTimeout(n);let a=r.host;if(!a||t.hosts.get(a.id)!==a||a.ws!==e)return;if((o?o.toString():"")==="host_shutdown"&&(a.shutdownRequested=!0),a.shutdownRequested||!at(t,a)){M(t,a,{notify:!0,reason:a.shutdownRequested?"host_shutdown":"host_disconnected"});return}lt(t,a,"host_disconnected")}),e.on("error",()=>{})}function No(t,e,s,r){if(e.lastSeenAt=Date.now(),r){let c;try{c=_r(s)}catch(u){t.metrics.recordCleanup("deadConnectionsClosed"),k(e.ws,1003,u.message);return}if(c.type!=="output")return;let f=c.version===2?e.streamIndices.get(c.streamIndex):t.streams.get(c.streamId);if(!f)return;let d=t.clients.get(f);if(!d||!y(d.ws))return;qr(t,e,d,c.payload);return}let n=Se(s.toString());if(!n)return;if(n.type==="heartbeat"){e.load=n.load&&typeof n.load=="object"?n.load:{},e.ptys=Array.isArray(n.ptys)?n.ptys.slice(0,256):[];return}if(n.type==="host_shutdown"){e.shutdownRequested=!0,t.hosts.get(e.id)===e&&M(t,e,{notify:!0,reason:"host_shutdown"});return}if(n.type==="agent_status"){Jr(t,e,n);return}if(n.type==="update_status"){Zr(t,e,n);return}if(n.type==="terminal_font"){Qr(t,e,n);return}let i=n,o=typeof i.clientId=="string"?i.clientId:i.streamId,a=o?t.streams.get(o):null,l=a?t.clients.get(a):null;if(l)if(n.type==="session_ready")l.session&&(l.session.ready=!0),p(l.ws,{type:"session_ready",clientId:l.id});else if(n.type==="session_exit"){let c=Number.isInteger(n.code)?n.code:null;p(l.ws,{type:"exit",code:c}),Ee(t,e,l),C(t,l,{notify:!1})}else if(n.type==="host_font_chunk")Ur(l,n);else if(n.type==="host_font_subset_ready")Fr(l,n);else if(n.type==="paste_file_ready")p(l.ws,{type:"paste_file_ready",path:n.path});else if(n.type==="open_link"){let c=br(n.url);c&&p(l.ws,{type:"open_link",url:c})}else n.type==="error"&&(n.code==="host_font_unavailable"&&(Wt(l),nt(l)),n.code==="host_font_subset_failed"&&nt(l),p(l.ws,{type:"error",code:n.code||"host_error",message:String(n.message||"Host connector error")}))}import tn from"node:fs";import ne from"node:path";import{URL as Fo}from"node:url";function Zt(t,{sample:e=!0,includeDevices:s=!1,scopeHostId:r=null}={}){let n=r?[...t.clients.values()].filter(h=>h.hostId===r):[...t.clients.values()],i=r?[...t.hosts.values()].filter(h=>h.id===r):[...t.hosts.values()],o=n.map(h=>({id:h.id,role:h.role,...r?{}:{hostId:h.hostId},...s?{deviceId:h.deviceId}:{},userAgent:h.userAgent,connectedAt:h.connectedAt,lastPingAt:h.lastPingAt,bytesReceived:h.bytesReceived,bytesSent:h.bytesSent,ip:h.ip})),a=t.auth.listDevices(),l=new Map;for(let h of a)l.set(h.hostId,(l.get(h.hostId)||0)+1);let c=i.map(h=>({id:h.id,hostname:h.hostname,platform:h.platform,arch:h.arch,status:h.reconnecting?"reconnecting":h.clients.size?"busy":"online",connectedAt:h.connectedAt,activePtyCount:h.ptys.length,connectedDeviceCount:st([...h.clients].map(m=>t.clients.get(m)).filter(m=>!!m)),pairedDeviceCount:l.get(h.id)||0,version:h.version??h.updateStatus?.current??null,latestVersion:h.updateStatus?.updateAvailable?h.updateStatus.latest:null,load:h.load})),f=i.flatMap(h=>h.ptys.map(m=>({...m,...r?{}:{hostId:h.id},activeClients:h.clients.size}))),d=s?a:void 0,u=t.address();return{...t.metrics.snapshot({clients:o,hosts:c,ptys:f,sample:e,scopeHostId:r,activeUserCount:st(n)}),...d?{devices:d}:{},relayMode:t.relayMode,isRemoteRelay:t.relayMode==="remote",remoteAdminUrl:t.relayMode==="remote"?`${String(t.config.relay.publicUrl||"").replace(/\/+$/,"")}/admin`:void 0,relay:{mode:t.relayMode,publicUrl:t.config.relay.publicUrl,bind:t.config.relay.host,port:(u&&"port"in u?u.port:void 0)||t.config.relay.port,maxClientsPerHost:t.config.relay.maxClientsPerHost,maxHosts:t.config.relay.maxHosts,maxPendingHandshakes:t.config.relay.maxPendingHandshakes,maxBufferedBytesPerClient:t.config.relay.maxBufferedBytesPerClient,hostReconnectGraceMs:t.config.relay.hostReconnectGraceMs,adminConfigured:!!t.adminToken,adminStatusPath:"/api/admin/status",dashboardPath:"/admin"}}}import Do from"node:fs";import Bo from"node:path";var W=JSON.parse(Do.readFileSync(Bo.join(le,"package.json"),"utf8")).version;var sn=ne.join(le,"web","dist"),Uo=10080*60,Ho={".html":"text/html; charset=utf-8",".js":"text/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".json":"application/json",".svg":"image/svg+xml",".png":"image/png",".ico":"image/x-icon",".woff2":"font/woff2"};function Qt(t,e="application/json"){t.setHeader("Content-Type",e),t.setHeader("Cache-Control","no-store"),t.setHeader("X-Content-Type-Options","nosniff"),t.setHeader("X-Frame-Options","DENY"),t.setHeader("Referrer-Policy","no-referrer"),t.setHeader("Content-Security-Policy","default-src 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none'; connect-src 'self' ws: wss:; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'")}function ie(t,e,s){Qt(t),t.writeHead(e),t.end(JSON.stringify(s))}function A(t,e,s,r){ie(t,e,{ok:!1,code:s,message:r})}function rn(t,e,s){return t.adminToken?Yr(t,e)?!0:(A(s,401,"admin_auth_required","a valid relay admin token is required"),!1):(A(s,503,"admin_not_configured","configure RELAY_ADMIN_TOKEN to access the relay dashboard"),!1)}var $o=(t,e,s)=>{ie(s,200,{ok:!0,version:W,protocol:1,uptimeSeconds:Math.floor((Date.now()-t.startedAt)/1e3)})},Yo=(t,e,s)=>{let r=String(t.config.relay.publicUrl||"").replace(/\/+$/,"");ie(s,200,{ok:!0,version:W,protocol:1,relayMode:t.relayMode,isRemoteRelay:t.relayMode==="remote",adminConfigured:!!t.adminToken,adminPath:"/admin",adminStatusPath:"/api/admin/status",publicUrl:r,remoteAdminUrl:t.relayMode==="remote"?`${r}/admin`:null})},Wo=(t,e,s)=>{let r=$r(t,e);if(!r){A(s,401,"auth_required","an authorized device or host token is required");return}ie(s,200,Zt(t,{scopeHostId:r.hostId}))},Go=(t,e,s)=>{rn(t,e,s)&&ie(s,200,Zt(t,{includeDevices:!0}))},jo=(t,e,s,r)=>{if(!rn(t,e,s))return;let n=decodeURIComponent(r.pathname.slice(19)),i=t.auth.revokeDevice(n);if(!i){A(s,404,"device_not_found","no such paired device");return}let o=Xr(t,n);ie(s,200,{ok:!0,deviceId:i.deviceId,disconnected:o})},Vo=(t,e,s)=>{if(!it(t,e)){A(s,429,"rate_limited","too many pairing attempts");return}let r=Vt(t,e);if(!r){A(s,401,"host_auth_required","a valid host id and token are required");return}let n=t.hosts.get(r);if(!n||n.reconnecting||!y(n.ws)){A(s,409,"host_offline","no Herdr host is connected");return}try{let i=t.auth.startPairing(r,String(t.config.relay.publicUrl).replace(/\/$/,"")),o={ok:!0,...i,pairUrl:`${i.publicUrl}/?pairCode=${encodeURIComponent(i.code)}`};ie(s,200,o)}catch(i){let{code:o,message:a}=i;A(s,409,o||"pairing_failed",a)}},qo=[{method:"GET",path:"/healthz",handle:$o},{method:"GET",path:"/api/info",handle:Yo},{method:"GET",path:"/api/status",handle:Wo},{method:"GET",path:"/api/admin/status",handle:Go},{method:"DELETE",path:"/api/admin/devices/",prefix:!0,handle:jo},{method:"POST",path:"/api/pair/start",handle:Vo}];function nn(t,e,s){let r;try{r=new Fo(e.url||"",`http://${e.headers.host||"localhost"}`)}catch{A(s,400,"bad_request","invalid URL");return}if(!Hr(t,e)){A(s,403,"origin_denied","origin is not allowed");return}if(e.method==="OPTIONS"){s.writeHead(204,{"Access-Control-Allow-Origin":e.headers.origin||"*","Access-Control-Allow-Headers":"Authorization, Content-Type, X-Herdr-Host-Id, X-Herdr-Host-Token, X-Relay-Admin-Token","Access-Control-Allow-Methods":"GET, POST, DELETE, OPTIONS",Vary:"Origin"}),s.end();return}e.headers.origin&&(s.setHeader("Access-Control-Allow-Origin",e.headers.origin),s.setHeader("Vary","Origin"));let{pathname:n}=r,i=qo.find(o=>o.method===e.method&&(o.prefix?n.startsWith(o.path):n===o.path));if(i){i.handle(t,e,s,r);return}if(n.startsWith("/api/")){A(s,404,"not_found","API route not found");return}zo(t.publicDir,n,s)}function zo(t,e,s){let r=e==="/"||e==="/admin"?"index.html":e.replace(/^\/+/,""),n=ne.resolve(t,r);if(!n.startsWith(`${t}${ne.sep}`)&&n!==ne.join(t,"index.html")){A(s,403,"forbidden","path is not allowed");return}tn.readFile(n,(i,o)=>{if(i&&!ne.extname(r)){tn.readFile(ne.join(t,"index.html"),(l,c)=>{if(l){A(s,503,"web_not_built","frontend has not been built");return}Qt(s,"text/html; charset=utf-8"),s.end(c)});return}if(i){A(s,404,"not_found","file not found");return}let a=ne.extname(n).toLowerCase();Qt(s,Ho[a]||"application/octet-stream"),r.startsWith("fonts/")&&s.setHeader("Cache-Control",`public, max-age=${Uo}`),s.end(o)})}function on(t){let e=[...[...t.hosts.values()].map(s=>s.ws),...[...t.clients.values()].map(s=>s.ws)].filter(s=>!!(s&&s.readyState!==T.default.CLOSED));for(let s of e){if(s.readyState===T.default.CLOSING){t.metrics.recordCleanup("deadConnectionsClosed"),re(s);continue}if(s.readyState===T.default.OPEN){if(!s.isAlive){t.metrics.recordCleanup("deadConnectionsClosed"),re(s);continue}s.isAlive=!1;try{s.ping()}catch{}}}}function es(t,e){for(let[s,r]of t.entries())e-r.startedAt>=6e4&&t.delete(s)}function an(t){let e=Date.now(),s=t.config.cleanup.staleAfterMs;es(t.pairAttempts,e),es(t.clientHandshakeAttempts,e),es(t.hostHandshakeAttempts,e);for(let n of[...t.clients.values()])e-n.lastSeenAt>s&&(t.metrics.recordCleanup("staleClientsPurged"),C(t,n,{notify:!1,reason:"stale_client",terminate:!0}));for(let n of[...t.hosts.values()])n.reconnecting||e-n.lastSeenAt>s&&(t.metrics.recordCleanup("deadConnectionsClosed"),M(t,n,{notify:!0,reason:"stale_host",terminate:!0}));let r=t.auth.cleanup(e);(r.removedDevices||r.removedPairings)&&t.metrics.recordCleanup("staleClientsPurged",r.removedDevices),t.metrics.cleanup.lastCleanupAt=new Date(e).toISOString()}var ct=class{config;relayMode;hosts=new Map;clients=new Map;streams=new Map;pairAttempts=new Map;clientHandshakeAttempts=new Map;hostHandshakeAttempts=new Map;pendingHandshakes=new Set;startedAt=Date.now();metrics;stateFile;password;adminToken;trustProxy;devLatencyMs;devDelayMs;publicDir;sendQueues=new WeakMap;activeDelayTimers=new Set;auth;server;wss;heartbeatTimer=null;cleanupTimer=null;constructor(e=Be().config,s={}){this.config={relay:{...x.relay,...e.relay},auth:{...x.auth,...e.auth},cleanup:{...x.cleanup,...e.cleanup}};let{relay:r,auth:n}=this.config;this.relayMode=r.mode==="local"?"local":"remote",this.metrics=s.metrics||new tt({version:W,protocolVersion:1}),this.stateFile=s.stateFile||n.stateFile||ts.join(ht(),"relay-auth.json"),this.password=s.password??n.password??null,this.adminToken=s.adminToken??n.adminToken??null,this.trustProxy=!!(s.trustProxy??r.trustProxy),this.publicDir=ts.resolve(s.publicDir??sn);let i=s.devLatencyMs??r.devLatencyMs??process.env.RELAY_DEV_LATENCY_MS;this.devLatencyMs=i?Math.max(0,Number.parseInt(String(i),10)||0):0,this.devDelayMs=this.devLatencyMs>0?Math.round(this.devLatencyMs/2):0,this.auth=s.auth||new Ze({stateFile:this.stateFile,pairingTtlMs:n.pairingTtlMs,deviceTtlMs:n.deviceTtlMs,maxDevices:n.maxDevices,password:this.password}),this.server=Xo.createServer((o,a)=>nn(this,o,a)),this.wss=new Dt.default({noServer:!0,clientTracking:!1,maxPayload:r.maxPayloadBytes,perMessageDeflate:{threshold:1024,zlibDeflateOptions:{level:3},serverNoContextTakeover:!1,clientNoContextTakeover:!1,concurrencyLimit:10}}),this.server.on("upgrade",(o,a,l)=>this.handleUpgrade(o,a,l))}listen(e=this.config.relay.port,s=this.config.relay.host){return ke(ts.dirname(this.stateFile)),new Promise((r,n)=>{let i=a=>{this.server.off("listening",o),n(a)},o=()=>{this.server.off("error",i),this.heartbeatTimer=setInterval(()=>on(this),this.config.cleanup.heartbeatIntervalMs),this.cleanupTimer=setInterval(()=>an(this),this.config.cleanup.intervalMs),r(this.address())};this.server.once("error",i),this.server.once("listening",o),this.server.listen(e,s)})}address(){let e=this.server.address();return e?typeof e=="string"?{path:e}:{host:e.address,port:e.port}:null}async close(){this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.cleanupTimer&&clearInterval(this.cleanupTimer),this.heartbeatTimer=null,this.cleanupTimer=null;for(let e of this.activeDelayTimers)clearTimeout(e);this.activeDelayTimers.clear();for(let e of[...this.clients.values()])C(this,e,{notify:!1});for(let e of[...this.hosts.values()])M(this,e,{notify:!1});this.streams.clear(),this.pairAttempts.clear(),this.clientHandshakeAttempts.clear(),this.hostHandshakeAttempts.clear(),this.pendingHandshakes.clear(),this.metrics.close(),await new Promise(e=>{if(!this.server.listening)return e();this.server.close(()=>e())})}handleUpgrade(e,s,r){let n=(()=>{try{return new Ko(e.url||"","http://localhost").pathname}catch{return""}})();if(![$t,wr].includes(n)||!jt(this,e.headers.origin,e)){s.write(`HTTP/1.1 403 Forbidden\r
13
13
  Connection: close\r
14
14
  \r
15
15
  `),s.destroy();return}if(this.pendingHandshakes.size>=this.config.relay.maxPendingHandshakes){s.write(`HTTP/1.1 503 Service Unavailable\r
16
16
  Connection: close\r
17
17
  \r
18
- `),s.destroy();return}try{let i=s;i.setNoDelay(!0),i.setKeepAlive?.(!0,this.config.cleanup.heartbeatIntervalMs)}catch{}this.wss.handleUpgrade(e,s,r,i=>{this.pendingHandshakes.add(i),i.once("close",()=>this.finishHandshake(i)),n===Yt?Jr(this,i,e):qr(this,i,e)})}finishHandshake(e){this.pendingHandshakes.delete(e)}};var nn=`herdr-remote-relay ${W} \u2014 standalone relay for Herdr Remote
18
+ `),s.destroy();return}try{let i=s;i.setNoDelay(!0),i.setKeepAlive?.(!0,this.config.cleanup.heartbeatIntervalMs)}catch{}this.wss.handleUpgrade(e,s,r,i=>{this.pendingHandshakes.add(i),i.once("close",()=>this.finishHandshake(i)),n===$t?en(this,i,e):Kr(this,i,e)})}finishHandshake(e){this.pendingHandshakes.delete(e)}};var ln=`herdr-remote-relay ${W} \u2014 standalone relay for Herdr Remote
19
19
 
20
20
  Usage: herdr-remote-relay [options]
21
21
 
@@ -39,10 +39,10 @@ Options:
39
39
  -v, --version Show version
40
40
 
41
41
  Guide: docs/self-hosted-relay.md
42
- `;function Xo(){return qo.existsSync(zo.join(ae,"web","dist","index.html"))}async function Ko(t=process.argv.slice(2)){let e;try{e=Be({argv:t})}catch(u){process.stderr.write(`herdr-remote-relay: ${u.message}
43
- `),process.exitCode=1;return}let{config:s,help:r,version:n,errors:i,warnings:o,configFile:a}=e;if(r){process.stdout.write(nn);return}if(n){process.stdout.write(`${W}
42
+ `;function Qo(){return Jo.existsSync(Zo.join(le,"web","dist","index.html"))}async function ea(t=process.argv.slice(2)){let e;try{e=Be({argv:t})}catch(u){process.stderr.write(`herdr-remote-relay: ${u.message}
43
+ `),process.exitCode=1;return}let{config:s,help:r,version:n,errors:i,warnings:o,configFile:a}=e;if(r){process.stdout.write(ln);return}if(n){process.stdout.write(`${W}
44
44
  `);return}if(i.length>0){for(let u of i)process.stderr.write(`herdr-remote-relay: ${u}
45
- `);process.stderr.write(nn),process.exitCode=2;return}let l=new ct(s),c;try{c=await l.listen(s.relay.port,s.relay.host)}catch(u){let h=u.code==="EADDRINUSE"?` (port ${s.relay.port} is already in use)`:u.code==="EACCES"?` (no permission to bind port ${s.relay.port})`:"";process.stderr.write(`herdr-remote-relay: failed to listen${h}: ${u.message}
45
+ `);process.stderr.write(ln),process.exitCode=2;return}let l=new ct(s),c;try{c=await l.listen(s.relay.port,s.relay.host)}catch(u){let h=u.code==="EADDRINUSE"?` (port ${s.relay.port} is already in use)`:u.code==="EACCES"?` (no permission to bind port ${s.relay.port})`:"";process.stderr.write(`herdr-remote-relay: failed to listen${h}: ${u.message}
46
46
  `),process.exitCode=1;return}process.stdout.write(`herdr-remote-relay ${W} (protocol ${1})
47
47
  `),process.stdout.write(` listening http://${s.relay.host}:${c.port}
48
48
  `),process.stdout.write(` public url ${s.relay.publicUrl}
@@ -50,8 +50,8 @@ Guide: docs/self-hosted-relay.md
50
50
  `),process.stdout.write(` admin ${s.auth.adminToken?"set (/admin)":"not configured"}
51
51
  `),process.stdout.write(` state file ${l.stateFile}
52
52
  `),a&&process.stdout.write(` config file ${a}
53
- `),Xo()||process.stdout.write(` web ui NOT BUILT (run "npm run build" in this package)
53
+ `),Qo()||process.stdout.write(` web ui NOT BUILT (run "npm run build" in this package)
54
54
  `);for(let u of o)process.stdout.write(` warning: ${u}
55
55
  `);let f=!1,d=u=>{f||(f=!0,process.stdout.write(`herdr-remote-relay: ${u} received, shutting down
56
- `),l.close().finally(()=>process.exit(0)))};process.on("SIGINT",()=>d("SIGINT")),process.on("SIGTERM",()=>d("SIGTERM"))}Ko().catch(t=>{process.stderr.write(`herdr-remote-relay: ${t.stack||t.message}
56
+ `),l.close().finally(()=>process.exit(0)))};process.on("SIGINT",()=>d("SIGINT")),process.on("SIGTERM",()=>d("SIGTERM"))}ea().catch(t=>{process.stderr.write(`herdr-remote-relay: ${t.stack||t.message}
57
57
  `),process.exitCode=1});