iosignal 3.0.0 → 3.1.0

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 (57) hide show
  1. package/README.ko.md +566 -0
  2. package/README.md +561 -2
  3. package/dist/io.d.ts +481 -0
  4. package/dist/io.js +3 -3
  5. package/dist/io.js.map +1 -1
  6. package/dist/io.min.js +3 -3
  7. package/dist/io.min.js.map +1 -1
  8. package/dist/iosignal.js +558 -104
  9. package/dist/types/client/IOCore.d.ts +408 -0
  10. package/dist/types/client/browser/IOWebSocket.d.ts +75 -0
  11. package/dist/types/common/constants.d.ts +169 -0
  12. package/dist/types/common/payload.d.ts +6 -0
  13. package/dist/types/common/quotaTable.d.ts +47 -0
  14. package/examples/react-chat-js/dist/assets/index-Cy4qaVcJ.js +56 -0
  15. package/examples/react-chat-js/dist/assets/index-NETrjYhz.css +1 -0
  16. package/examples/react-chat-js/dist/index.html +14 -0
  17. package/examples/react-chat-js/index.html +13 -0
  18. package/examples/react-chat-js/package-lock.json +1723 -0
  19. package/examples/react-chat-js/package.json +20 -0
  20. package/examples/react-chat-js/src/App.css +61 -0
  21. package/examples/react-chat-js/src/App.jsx +125 -0
  22. package/examples/react-chat-js/src/index.css +13 -0
  23. package/examples/react-chat-js/src/main.jsx +13 -0
  24. package/examples/react-chat-js/src/shared_io.js +12 -0
  25. package/examples/react-chat-js/vite.config.js +7 -0
  26. package/examples/server/index.js +12 -0
  27. package/examples/server/package-lock.json +47 -0
  28. package/examples/server/package.json +12 -0
  29. package/examples/svelte-chat-js/.devtools +3 -0
  30. package/examples/svelte-chat-js/README.md +38 -0
  31. package/examples/svelte-chat-js/package-lock.json +1505 -0
  32. package/examples/svelte-chat-js/package.json +22 -0
  33. package/examples/svelte-chat-js/src/app.css +105 -0
  34. package/examples/svelte-chat-js/src/app.d.ts +13 -0
  35. package/examples/svelte-chat-js/src/app.html +12 -0
  36. package/examples/svelte-chat-js/src/lib/images/github.svg +1 -0
  37. package/examples/svelte-chat-js/src/lib/images/svelte-logo.svg +1 -0
  38. package/examples/svelte-chat-js/src/lib/images/svelte-welcome.png +0 -0
  39. package/examples/svelte-chat-js/src/lib/images/svelte-welcome.webp +0 -0
  40. package/examples/svelte-chat-js/src/lib/shared_io.js +12 -0
  41. package/examples/svelte-chat-js/src/routes/+layout.svelte +9 -0
  42. package/examples/svelte-chat-js/src/routes/+page.js +3 -0
  43. package/examples/svelte-chat-js/src/routes/+page.svelte +162 -0
  44. package/examples/svelte-chat-js/static/favicon.svg +1 -0
  45. package/examples/svelte-chat-js/static/global.css +19 -0
  46. package/examples/svelte-chat-js/static/robots.txt +3 -0
  47. package/examples/svelte-chat-js/svelte.config.js +15 -0
  48. package/examples/svelte-chat-js/vite.config.js +6 -0
  49. package/package.json +9 -3
  50. package/rollup.config.js +11 -4
  51. package/src/client/IOCongSocket.js +20 -9
  52. package/src/client/IOCore.js +437 -79
  53. package/src/client/IOWS.js +12 -15
  54. package/src/client/browser/IOWebSocket.js +101 -17
  55. package/src/common/constants.js +91 -1
  56. package/tsconfig.json +24 -0
  57. package/docs/README.kr.md +0 -230
package/dist/iosignal.js CHANGED
@@ -13,7 +13,7 @@ import require$$2 from 'os';
13
13
  import require$$0$1 from 'buffer';
14
14
  import { memoryUsage } from 'process';
15
15
 
16
- var version = "3.0.0";
16
+ var version = "3.1.0";
17
17
 
18
18
  var t$1,e$1={},r$1={};var n$1,i$1,o$1={};
19
19
  /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */function f$1(){return n$1||(n$1=1,o$1.read=function(t,e,r,n,i){var o,f,u=8*i-n-1,s=(1<<u)-1,h=s>>1,a=-7,c=r?i-1:0,l=r?-1:1,p=t[e+c];for(c+=l,o=p&(1<<-a)-1,p>>=-a,a+=u;a>0;o=256*o+t[e+c],c+=l,a-=8);for(f=o&(1<<-a)-1,o>>=-a,a+=n;a>0;f=256*f+t[e+c],c+=l,a-=8);if(0===o)o=1-h;else {if(o===s)return f?NaN:1/0*(p?-1:1);f+=Math.pow(2,n),o-=h;}return (p?-1:1)*f*Math.pow(2,o-n)},o$1.write=function(t,e,r,n,i,o){var f,u,s,h=8*o-i-1,a=(1<<h)-1,c=a>>1,l=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,p=n?0:o-1,y=n?1:-1,g=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(u=isNaN(e)?1:0,f=a):(f=Math.floor(Math.log(e)/Math.LN2),e*(s=Math.pow(2,-f))<1&&(f--,s*=2),(e+=f+c>=1?l/s:l*Math.pow(2,1-c))*s>=2&&(f++,s/=2),f+c>=a?(u=0,f=a):f+c>=1?(u=(e*s-1)*Math.pow(2,i),f+=c):(u=e*Math.pow(2,c-1)*Math.pow(2,i),f=0));i>=8;t[r+p]=255&u,p+=y,u/=256,i-=8);for(f=f<<i|u,h+=i;h>0;t[r+p]=255&f,p+=y,f/=256,h-=8);t[r+p-y]|=128*g;}),o$1}
@@ -378,6 +378,18 @@ function requireEventemitter3 () {
378
378
  var eventemitter3Exports = requireEventemitter3();
379
379
  var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
380
380
 
381
+ /**
382
+ * @typedef {object} STATES
383
+ * @property {number} OPENING
384
+ * @property {number} OPEN
385
+ * @property {number} CLOSING
386
+ * @property {number} CLOSED
387
+ * @property {number} SERVER_READY
388
+ * @property {number} AUTH_FAIL
389
+ * @property {number} AUTH_READY
390
+ * @property {number} READY
391
+ * @property {number} REDIRECTING
392
+ */
381
393
  // Client STATES: name and number
382
394
  const STATES = {
383
395
  OPENING: 0,
@@ -392,7 +404,17 @@ const STATES = {
392
404
  };
393
405
  for (let c in STATES) { STATES[STATES[c]] = c; }
394
406
 
395
- // server side client state
407
+ /**
408
+ * @typedef {object} CLIENT_STATE
409
+ * @property {number} INIT
410
+ * @property {number} SENT_SERVER_READY
411
+ * @property {number} RECV_AUTH_REQ
412
+ * @property {number} SENT_SERVER_NONCE
413
+ * @property {number} RECV_AUTH_HMAC
414
+ * @property {number} AUTH_FAIL
415
+ * @property {number} AUTH_READY
416
+ * @property {number} CID_READY
417
+ */
396
418
  const CLIENT_STATE = {
397
419
  INIT: 0,
398
420
  SENT_SERVER_READY: 1,
@@ -405,6 +427,12 @@ const CLIENT_STATE = {
405
427
  };
406
428
  for (let c in CLIENT_STATE) { CLIENT_STATE[CLIENT_STATE[c]] = c; }
407
429
 
430
+ /**
431
+ * @typedef {object} ENC_MODE
432
+ * @property {number} NO
433
+ * @property {number} YES
434
+ * @property {number} AUTO
435
+ */
408
436
  let ENC_MODE = {
409
437
  NO: 0,
410
438
  YES: 1,
@@ -414,6 +442,15 @@ let ENC_MODE = {
414
442
  for (let c in ENC_MODE) { ENC_MODE[ENC_MODE[c]] = c; }
415
443
 
416
444
 
445
+ /**
446
+ * @typedef {object} SIZE_LIMIT
447
+ * @property {number} TAG_LEN1
448
+ * @property {number} TAG_LEN2
449
+ * @property {number} CONNECTION_CHECKER_PERIOD
450
+ * @property {number} PROMISE_TIMEOUT
451
+ * @property {number} DID
452
+ * @property {number} CID
453
+ */
417
454
  const SIZE_LIMIT = {
418
455
  TAG_LEN1: 255,
419
456
  TAG_LEN2: 65535,
@@ -423,6 +460,15 @@ const SIZE_LIMIT = {
423
460
  CID: 12
424
461
  };
425
462
 
463
+ /**
464
+ * @typedef {object} PAYLOAD_TYPE
465
+ * @property {number} EMPTY
466
+ * @property {number} TEXT
467
+ * @property {number} BINARY
468
+ * @property {number} OBJECT
469
+ * @property {number} MJSON
470
+ * @property {number} MBA
471
+ */
426
472
  let PAYLOAD_TYPE = {
427
473
  EMPTY: 0,
428
474
  TEXT: 1,
@@ -434,6 +480,40 @@ let PAYLOAD_TYPE = {
434
480
  for (let c in PAYLOAD_TYPE) { PAYLOAD_TYPE[PAYLOAD_TYPE[c]] = c; }
435
481
 
436
482
 
483
+ /**
484
+ * @typedef {object} IOMsg
485
+ * @property {number} SERVER_READY
486
+ * @property {number} CID_REQ
487
+ * @property {number} CID_RES
488
+ * @property {number} QUOTA_LEVEL
489
+ * @property {number} SERVER_CLEAR_AUTH
490
+ * @property {number} SERVER_REDIRECT
491
+ * @property {number} LOOP
492
+ * @property {number} ECHO
493
+ * @property {number} PING
494
+ * @property {number} PONG
495
+ * @property {number} CLOSE
496
+ * @property {number} SIGNAL
497
+ * @property {number} SIGNAL_REQ
498
+ * @property {number} SIGNAL_E2E
499
+ * @property {number} SUBSCRIBE
500
+ * @property {number} SUBSCRIBE_REQ
501
+ * @property {number} UNSUBSCRIBE
502
+ * @property {number} SERVER_SIGNAL
503
+ * @property {number} IAM
504
+ * @property {number} IAM_RES
505
+ * @property {number} SET
506
+ * @property {number} RESPONSE_CODE
507
+ * @property {number} RESPONSE_MBP
508
+ * @property {number} REQUEST
509
+ * @property {number} RESPONSE
510
+ * @property {number} FLOW_MODE
511
+ * @property {number} WAIT
512
+ * @property {number} RESUME
513
+ * @property {number} TIME_OUT
514
+ * @property {number} OVER_SIZE
515
+ * @property {number} OVER_FLOW
516
+ */
437
517
  // IO message's one-byte headers.
438
518
  let IOMsg = {
439
519
 
@@ -513,11 +593,21 @@ let IOMsg = {
513
593
  for (let c in IOMsg) { IOMsg[IOMsg[c]] = c; }
514
594
  // console.log( IOMsg );
515
595
 
596
+ /**
597
+ * @typedef {object} API_TYPE
598
+ * @property {string} REQUEST_RESPONSE
599
+ * @property {string} ONE_WAY
600
+ */
516
601
  const API_TYPE = {
517
602
  'REQUEST_RESPONSE': 'requet_response',
518
603
  'ONE_WAY': 'one_way'
519
604
  };
520
605
 
606
+ /**
607
+ * @typedef {object} STATUS
608
+ * @property {number} OK
609
+ * @property {number} ERROR
610
+ */
521
611
  // api response status code
522
612
  const STATUS$1 = {
523
613
  OK: 0,
@@ -691,6 +781,19 @@ const t=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1
691
781
  * @license MIT
692
782
  */var V=(K||(K=1,function(t){const e=function(){if(j)return D;j=1,D.byteLength=function(t){var e=o(t),r=e[0],n=e[1];return 3*(r+n)/4-n},D.toByteArray=function(t){var n,i,f=o(t),s=f[0],u=f[1],h=new r(function(t,e,r){return 3*(e+r)/4-r}(0,s,u)),a=0,c=u>0?s-4:s;for(i=0;i<c;i+=4)n=e[t.charCodeAt(i)]<<18|e[t.charCodeAt(i+1)]<<12|e[t.charCodeAt(i+2)]<<6|e[t.charCodeAt(i+3)],h[a++]=n>>16&255,h[a++]=n>>8&255,h[a++]=255&n;return 2===u&&(n=e[t.charCodeAt(i)]<<2|e[t.charCodeAt(i+1)]>>4,h[a++]=255&n),1===u&&(n=e[t.charCodeAt(i)]<<10|e[t.charCodeAt(i+1)]<<4|e[t.charCodeAt(i+2)]>>2,h[a++]=n>>8&255,h[a++]=255&n),h},D.fromByteArray=function(e){for(var r,n=e.length,i=n%3,o=[],s=16383,u=0,h=n-i;u<h;u+=s)o.push(f(e,u,u+s>h?h:u+s));return 1===i?(r=e[n-1],o.push(t[r>>2]+t[r<<4&63]+"==")):2===i&&(r=(e[n-2]<<8)+e[n-1],o.push(t[r>>10]+t[r>>4&63]+t[r<<2&63]+"=")),o.join("")};for(var t=[],e=[],r="undefined"!=typeof Uint8Array?Uint8Array:Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",i=0;i<64;++i)t[i]=n[i],e[n.charCodeAt(i)]=i;function o(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var r=t.indexOf("=");return -1===r&&(r=e),[r,r===e?0:4-r%4]}function f(e,r,n){for(var i,o,f=[],s=r;s<n;s+=3)i=(e[s]<<16&16711680)+(e[s+1]<<8&65280)+(255&e[s+2]),f.push(t[(o=i)>>18&63]+t[o>>12&63]+t[o>>6&63]+t[63&o]);return f.join("")}return e["-".charCodeAt(0)]=62,e["_".charCodeAt(0)]=63,D}(),r=G(),n="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):null;t.Buffer=f,t.SlowBuffer=function(t){return +t!=t&&(t=0),f.alloc(+t)},t.INSPECT_MAX_BYTES=50;const i=2147483647;function o(t){if(t>i)throw new RangeError('The value "'+t+'" is invalid for option "size"');const e=new Uint8Array(t);return Object.setPrototypeOf(e,f.prototype),e}function f(t,e,r){if("number"==typeof t){if("string"==typeof e)throw new TypeError('The "string" argument must be of type string. Received type number');return h(t)}return s(t,e,r)}function s(t,e,r){if("string"==typeof t)return function(t,e){if("string"==typeof e&&""!==e||(e="utf8"),!f.isEncoding(e))throw new TypeError("Unknown encoding: "+e);const r=0|p(t,e);let n=o(r);const i=n.write(t,e);return i!==r&&(n=n.slice(0,i)),n}(t,e);if(ArrayBuffer.isView(t))return function(t){if(Q(t,Uint8Array)){const e=new Uint8Array(t);return c(e.buffer,e.byteOffset,e.byteLength)}return a(t)}(t);if(null==t)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t);if(Q(t,ArrayBuffer)||t&&Q(t.buffer,ArrayBuffer))return c(t,e,r);if("undefined"!=typeof SharedArrayBuffer&&(Q(t,SharedArrayBuffer)||t&&Q(t.buffer,SharedArrayBuffer)))return c(t,e,r);if("number"==typeof t)throw new TypeError('The "value" argument must not be of type number. Received type number');const n=t.valueOf&&t.valueOf();if(null!=n&&n!==t)return f.from(n,e,r);const i=function(t){if(f.isBuffer(t)){const e=0|l(t.length),r=o(e);return 0===r.length||t.copy(r,0,0,e),r}return void 0!==t.length?"number"!=typeof t.length||X(t.length)?o(0):a(t):"Buffer"===t.type&&Array.isArray(t.data)?a(t.data):void 0}(t);if(i)return i;if("undefined"!=typeof Symbol&&null!=Symbol.toPrimitive&&"function"==typeof t[Symbol.toPrimitive])return f.from(t[Symbol.toPrimitive]("string"),e,r);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t)}function u(t){if("number"!=typeof t)throw new TypeError('"size" argument must be of type number');if(t<0)throw new RangeError('The value "'+t+'" is invalid for option "size"')}function h(t){return u(t),o(t<0?0:0|l(t))}function a(t){const e=t.length<0?0:0|l(t.length),r=o(e);for(let n=0;n<e;n+=1)r[n]=255&t[n];return r}function c(t,e,r){if(e<0||t.byteLength<e)throw new RangeError('"offset" is outside of buffer bounds');if(t.byteLength<e+(r||0))throw new RangeError('"length" is outside of buffer bounds');let n;return n=void 0===e&&void 0===r?new Uint8Array(t):void 0===r?new Uint8Array(t,e):new Uint8Array(t,e,r),Object.setPrototypeOf(n,f.prototype),n}function l(t){if(t>=i)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+i.toString(16)+" bytes");return 0|t}function p(t,e){if(f.isBuffer(t))return t.length;if(ArrayBuffer.isView(t)||Q(t,ArrayBuffer))return t.byteLength;if("string"!=typeof t)throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof t);const r=t.length,n=arguments.length>2&&true===arguments[2];if(!n&&0===r)return 0;let i=false;for(;;)switch(e){case "ascii":case "latin1":case "binary":return r;case "utf8":case "utf-8":return q(t).length;case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":return 2*r;case "hex":return r>>>1;case "base64":return V(t).length;default:if(i)return n?-1:q(t).length;e=(""+e).toLowerCase(),i=true;}}function y(t,e,r){let n=false;if((void 0===e||e<0)&&(e=0),e>this.length)return "";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return "";if((r>>>=0)<=(e>>>=0))return "";for(t||(t="utf8");;)switch(t){case "hex":return T(this,e,r);case "utf8":case "utf-8":return U(this,e,r);case "ascii":return L(this,e,r);case "latin1":case "binary":return v(this,e,r);case "base64":return _(this,e,r);case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":return S(this,e,r);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=true;}}function g(t,e,r){const n=t[e];t[e]=t[r],t[r]=n;}function d(t,e,r,n,i){if(0===t.length)return -1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),X(r=+r)&&(r=i?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(i)return -1;r=t.length-1;}else if(r<0){if(!i)return -1;r=0;}if("string"==typeof e&&(e=f.from(e,n)),f.isBuffer(e))return 0===e.length?-1:b(t,e,r,n,i);if("number"==typeof e)return e&=255,"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):b(t,[e],r,n,i);throw new TypeError("val must be string, number or Buffer")}function b(t,e,r,n,i){let o,f=1,s=t.length,u=e.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||e.length<2)return -1;f=2,s/=2,u/=2,r/=2;}function h(t,e){return 1===f?t[e]:t.readUInt16BE(e*f)}if(i){let n=-1;for(o=r;o<s;o++)if(h(t,o)===h(e,-1===n?0:o-n)){if(-1===n&&(n=o),o-n+1===u)return n*f}else -1!==n&&(o-=o-n),n=-1;}else for(r+u>s&&(r=s-u),o=r;o>=0;o--){let r=true;for(let n=0;n<u;n++)if(h(t,o+n)!==h(e,n)){r=false;break}if(r)return o}return -1}function w(t,e,r,n){r=Number(r)||0;const i=t.length-r;n?(n=Number(n))>i&&(n=i):n=i;const o=e.length;let f;for(n>o/2&&(n=o/2),f=0;f<n;++f){const n=parseInt(e.substr(2*f,2),16);if(X(n))return f;t[r+f]=n;}return f}function B(t,e,r,n){return J(q(e,t.length-r),t,r,n)}function m(t,e,r,n){return J(function(t){const e=[];for(let r=0;r<t.length;++r)e.push(255&t.charCodeAt(r));return e}(e),t,r,n)}function E(t,e,r,n){return J(V(e),t,r,n)}function A(t,e,r,n){return J(function(t,e){let r,n,i;const o=[];for(let f=0;f<t.length&&!((e-=2)<0);++f)r=t.charCodeAt(f),n=r>>8,i=r%256,o.push(i),o.push(n);return o}(e,t.length-r),t,r,n)}function _(t,r,n){return 0===r&&n===t.length?e.fromByteArray(t):e.fromByteArray(t.slice(r,n))}function U(t,e,r){r=Math.min(t.length,r);const n=[];let i=e;for(;i<r;){const e=t[i];let o=null,f=e>239?4:e>223?3:e>191?2:1;if(i+f<=r){let r,n,s,u;switch(f){case 1:e<128&&(o=e);break;case 2:r=t[i+1],128==(192&r)&&(u=(31&e)<<6|63&r,u>127&&(o=u));break;case 3:r=t[i+1],n=t[i+2],128==(192&r)&&128==(192&n)&&(u=(15&e)<<12|(63&r)<<6|63&n,u>2047&&(u<55296||u>57343)&&(o=u));break;case 4:r=t[i+1],n=t[i+2],s=t[i+3],128==(192&r)&&128==(192&n)&&128==(192&s)&&(u=(15&e)<<18|(63&r)<<12|(63&n)<<6|63&s,u>65535&&u<1114112&&(o=u));}}null===o?(o=65533,f=1):o>65535&&(o-=65536,n.push(o>>>10&1023|55296),o=56320|1023&o),n.push(o),i+=f;}return function(t){const e=t.length;if(e<=I)return String.fromCharCode.apply(String,t);let r="",n=0;for(;n<e;)r+=String.fromCharCode.apply(String,t.slice(n,n+=I));return r}(n)}t.kMaxLength=i,f.TYPED_ARRAY_SUPPORT=function(){try{const t=new Uint8Array(1),e={foo:function(){return 42}};return Object.setPrototypeOf(e,Uint8Array.prototype),Object.setPrototypeOf(t,e),42===t.foo()}catch(t){return false}}(),f.TYPED_ARRAY_SUPPORT||"undefined"==typeof console||"function"!=typeof console.error||console.error("This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support."),Object.defineProperty(f.prototype,"parent",{enumerable:true,get:function(){if(f.isBuffer(this))return this.buffer}}),Object.defineProperty(f.prototype,"offset",{enumerable:true,get:function(){if(f.isBuffer(this))return this.byteOffset}}),f.poolSize=8192,f.from=function(t,e,r){return s(t,e,r)},Object.setPrototypeOf(f.prototype,Uint8Array.prototype),Object.setPrototypeOf(f,Uint8Array),f.alloc=function(t,e,r){return function(t,e,r){return u(t),t<=0?o(t):void 0!==e?"string"==typeof r?o(t).fill(e,r):o(t).fill(e):o(t)}(t,e,r)},f.allocUnsafe=function(t){return h(t)},f.allocUnsafeSlow=function(t){return h(t)},f.isBuffer=function(t){return null!=t&&true===t._isBuffer&&t!==f.prototype},f.compare=function(t,e){if(Q(t,Uint8Array)&&(t=f.from(t,t.offset,t.byteLength)),Q(e,Uint8Array)&&(e=f.from(e,e.offset,e.byteLength)),!f.isBuffer(t)||!f.isBuffer(e))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(t===e)return 0;let r=t.length,n=e.length;for(let i=0,o=Math.min(r,n);i<o;++i)if(t[i]!==e[i]){r=t[i],n=e[i];break}return r<n?-1:n<r?1:0},f.isEncoding=function(t){switch(String(t).toLowerCase()){case "hex":case "utf8":case "utf-8":case "ascii":case "latin1":case "binary":case "base64":case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":return true;default:return false}},f.concat=function(t,e){if(!Array.isArray(t))throw new TypeError('"list" argument must be an Array of Buffers');if(0===t.length)return f.alloc(0);let r;if(void 0===e)for(e=0,r=0;r<t.length;++r)e+=t[r].length;const n=f.allocUnsafe(e);let i=0;for(r=0;r<t.length;++r){let e=t[r];if(Q(e,Uint8Array))i+e.length>n.length?(f.isBuffer(e)||(e=f.from(e)),e.copy(n,i)):Uint8Array.prototype.set.call(n,e,i);else {if(!f.isBuffer(e))throw new TypeError('"list" argument must be an Array of Buffers');e.copy(n,i);}i+=e.length;}return n},f.byteLength=p,f.prototype._isBuffer=true,f.prototype.swap16=function(){const t=this.length;if(t%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let e=0;e<t;e+=2)g(this,e,e+1);return this},f.prototype.swap32=function(){const t=this.length;if(t%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(let e=0;e<t;e+=4)g(this,e,e+3),g(this,e+1,e+2);return this},f.prototype.swap64=function(){const t=this.length;if(t%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(let e=0;e<t;e+=8)g(this,e,e+7),g(this,e+1,e+6),g(this,e+2,e+5),g(this,e+3,e+4);return this},f.prototype.toString=function(){const t=this.length;return 0===t?"":0===arguments.length?U(this,0,t):y.apply(this,arguments)},f.prototype.toLocaleString=f.prototype.toString,f.prototype.equals=function(t){if(!f.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===f.compare(this,t)},f.prototype.inspect=function(){let e="";const r=t.INSPECT_MAX_BYTES;return e=this.toString("hex",0,r).replace(/(.{2})/g,"$1 ").trim(),this.length>r&&(e+=" ... "),"<Buffer "+e+">"},n&&(f.prototype[n]=f.prototype.inspect),f.prototype.compare=function(t,e,r,n,i){if(Q(t,Uint8Array)&&(t=f.from(t,t.offset,t.byteLength)),!f.isBuffer(t))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof t);if(void 0===e&&(e=0),void 0===r&&(r=t?t.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),e<0||r>t.length||n<0||i>this.length)throw new RangeError("out of range index");if(n>=i&&e>=r)return 0;if(n>=i)return -1;if(e>=r)return 1;if(this===t)return 0;let o=(i>>>=0)-(n>>>=0),s=(r>>>=0)-(e>>>=0);const u=Math.min(o,s),h=this.slice(n,i),a=t.slice(e,r);for(let t=0;t<u;++t)if(h[t]!==a[t]){o=h[t],s=a[t];break}return o<s?-1:s<o?1:0},f.prototype.includes=function(t,e,r){return -1!==this.indexOf(t,e,r)},f.prototype.indexOf=function(t,e,r){return d(this,t,e,r,true)},f.prototype.lastIndexOf=function(t,e,r){return d(this,t,e,r,false)},f.prototype.write=function(t,e,r,n){if(void 0===e)n="utf8",r=this.length,e=0;else if(void 0===r&&"string"==typeof e)n=e,r=this.length,e=0;else {if(!isFinite(e))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");e>>>=0,isFinite(r)?(r>>>=0,void 0===n&&(n="utf8")):(n=r,r=void 0);}const i=this.length-e;if((void 0===r||r>i)&&(r=i),t.length>0&&(r<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");let o=false;for(;;)switch(n){case "hex":return w(this,t,e,r);case "utf8":case "utf-8":return B(this,t,e,r);case "ascii":case "latin1":case "binary":return m(this,t,e,r);case "base64":return E(this,t,e,r);case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":return A(this,t,e,r);default:if(o)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),o=true;}},f.prototype.toJSON=function(){return {type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};const I=4096;function L(t,e,r){let n="";r=Math.min(t.length,r);for(let i=e;i<r;++i)n+=String.fromCharCode(127&t[i]);return n}function v(t,e,r){let n="";r=Math.min(t.length,r);for(let i=e;i<r;++i)n+=String.fromCharCode(t[i]);return n}function T(t,e,r){const n=t.length;(!e||e<0)&&(e=0),(!r||r<0||r>n)&&(r=n);let i="";for(let n=e;n<r;++n)i+=W[t[n]];return i}function S(t,e,r){const n=t.slice(e,r);let i="";for(let t=0;t<n.length-1;t+=2)i+=String.fromCharCode(n[t]+256*n[t+1]);return i}function R(t,e,r){if(t%1!=0||t<0)throw new RangeError("offset is not uint");if(t+e>r)throw new RangeError("Trying to access beyond buffer length")}function O(t,e,r,n,i,o){if(!f.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>i||e<o)throw new RangeError('"value" argument is out of bounds');if(r+n>t.length)throw new RangeError("Index out of range")}function M(t,e,r,n,i){F(e,n,i,t,r,7);let o=Number(e&BigInt(4294967295));t[r++]=o,o>>=8,t[r++]=o,o>>=8,t[r++]=o,o>>=8,t[r++]=o;let f=Number(e>>BigInt(32)&BigInt(4294967295));return t[r++]=f,f>>=8,t[r++]=f,f>>=8,t[r++]=f,f>>=8,t[r++]=f,r}function C(t,e,r,n,i){F(e,n,i,t,r,7);let o=Number(e&BigInt(4294967295));t[r+7]=o,o>>=8,t[r+6]=o,o>>=8,t[r+5]=o,o>>=8,t[r+4]=o;let f=Number(e>>BigInt(32)&BigInt(4294967295));return t[r+3]=f,f>>=8,t[r+2]=f,f>>=8,t[r+1]=f,f>>=8,t[r]=f,r+8}function N(t,e,r,n,i,o){if(r+n>t.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function x(t,e,n,i,o){return e=+e,n>>>=0,o||N(t,0,n,4),r.write(t,e,n,i,23,4),n+4}function k(t,e,n,i,o){return e=+e,n>>>=0,o||N(t,0,n,8),r.write(t,e,n,i,52,8),n+8}f.prototype.slice=function(t,e){const r=this.length;(t=~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),(e=void 0===e?r:~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),e<t&&(e=t);const n=this.subarray(t,e);return Object.setPrototypeOf(n,f.prototype),n},f.prototype.readUintLE=f.prototype.readUIntLE=function(t,e,r){t>>>=0,e>>>=0,r||R(t,e,this.length);let n=this[t],i=1,o=0;for(;++o<e&&(i*=256);)n+=this[t+o]*i;return n},f.prototype.readUintBE=f.prototype.readUIntBE=function(t,e,r){t>>>=0,e>>>=0,r||R(t,e,this.length);let n=this[t+--e],i=1;for(;e>0&&(i*=256);)n+=this[t+--e]*i;return n},f.prototype.readUint8=f.prototype.readUInt8=function(t,e){return t>>>=0,e||R(t,1,this.length),this[t]},f.prototype.readUint16LE=f.prototype.readUInt16LE=function(t,e){return t>>>=0,e||R(t,2,this.length),this[t]|this[t+1]<<8},f.prototype.readUint16BE=f.prototype.readUInt16BE=function(t,e){return t>>>=0,e||R(t,2,this.length),this[t]<<8|this[t+1]},f.prototype.readUint32LE=f.prototype.readUInt32LE=function(t,e){return t>>>=0,e||R(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},f.prototype.readUint32BE=f.prototype.readUInt32BE=function(t,e){return t>>>=0,e||R(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},f.prototype.readBigUInt64LE=Z((function(t){z(t>>>=0,"offset");const e=this[t],r=this[t+7];void 0!==e&&void 0!==r||Y(t,this.length-8);const n=e+256*this[++t]+65536*this[++t]+this[++t]*2**24,i=this[++t]+256*this[++t]+65536*this[++t]+r*2**24;return BigInt(n)+(BigInt(i)<<BigInt(32))})),f.prototype.readBigUInt64BE=Z((function(t){z(t>>>=0,"offset");const e=this[t],r=this[t+7];void 0!==e&&void 0!==r||Y(t,this.length-8);const n=e*2**24+65536*this[++t]+256*this[++t]+this[++t],i=this[++t]*2**24+65536*this[++t]+256*this[++t]+r;return (BigInt(n)<<BigInt(32))+BigInt(i)})),f.prototype.readIntLE=function(t,e,r){t>>>=0,e>>>=0,r||R(t,e,this.length);let n=this[t],i=1,o=0;for(;++o<e&&(i*=256);)n+=this[t+o]*i;return i*=128,n>=i&&(n-=Math.pow(2,8*e)),n},f.prototype.readIntBE=function(t,e,r){t>>>=0,e>>>=0,r||R(t,e,this.length);let n=e,i=1,o=this[t+--n];for(;n>0&&(i*=256);)o+=this[t+--n]*i;return i*=128,o>=i&&(o-=Math.pow(2,8*e)),o},f.prototype.readInt8=function(t,e){return t>>>=0,e||R(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},f.prototype.readInt16LE=function(t,e){t>>>=0,e||R(t,2,this.length);const r=this[t]|this[t+1]<<8;return 32768&r?4294901760|r:r},f.prototype.readInt16BE=function(t,e){t>>>=0,e||R(t,2,this.length);const r=this[t+1]|this[t]<<8;return 32768&r?4294901760|r:r},f.prototype.readInt32LE=function(t,e){return t>>>=0,e||R(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},f.prototype.readInt32BE=function(t,e){return t>>>=0,e||R(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},f.prototype.readBigInt64LE=Z((function(t){z(t>>>=0,"offset");const e=this[t],r=this[t+7];void 0!==e&&void 0!==r||Y(t,this.length-8);const n=this[t+4]+256*this[t+5]+65536*this[t+6]+(r<<24);return (BigInt(n)<<BigInt(32))+BigInt(e+256*this[++t]+65536*this[++t]+this[++t]*2**24)})),f.prototype.readBigInt64BE=Z((function(t){z(t>>>=0,"offset");const e=this[t],r=this[t+7];void 0!==e&&void 0!==r||Y(t,this.length-8);const n=(e<<24)+65536*this[++t]+256*this[++t]+this[++t];return (BigInt(n)<<BigInt(32))+BigInt(this[++t]*2**24+65536*this[++t]+256*this[++t]+r)})),f.prototype.readFloatLE=function(t,e){return t>>>=0,e||R(t,4,this.length),r.read(this,t,true,23,4)},f.prototype.readFloatBE=function(t,e){return t>>>=0,e||R(t,4,this.length),r.read(this,t,false,23,4)},f.prototype.readDoubleLE=function(t,e){return t>>>=0,e||R(t,8,this.length),r.read(this,t,true,52,8)},f.prototype.readDoubleBE=function(t,e){return t>>>=0,e||R(t,8,this.length),r.read(this,t,false,52,8)},f.prototype.writeUintLE=f.prototype.writeUIntLE=function(t,e,r,n){t=+t,e>>>=0,r>>>=0,n||O(this,t,e,r,Math.pow(2,8*r)-1,0);let i=1,o=0;for(this[e]=255&t;++o<r&&(i*=256);)this[e+o]=t/i&255;return e+r},f.prototype.writeUintBE=f.prototype.writeUIntBE=function(t,e,r,n){t=+t,e>>>=0,r>>>=0,n||O(this,t,e,r,Math.pow(2,8*r)-1,0);let i=r-1,o=1;for(this[e+i]=255&t;--i>=0&&(o*=256);)this[e+i]=t/o&255;return e+r},f.prototype.writeUint8=f.prototype.writeUInt8=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,1,255,0),this[e]=255&t,e+1},f.prototype.writeUint16LE=f.prototype.writeUInt16LE=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,2,65535,0),this[e]=255&t,this[e+1]=t>>>8,e+2},f.prototype.writeUint16BE=f.prototype.writeUInt16BE=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,2,65535,0),this[e]=t>>>8,this[e+1]=255&t,e+2},f.prototype.writeUint32LE=f.prototype.writeUInt32LE=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,4,4294967295,0),this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t,e+4},f.prototype.writeUint32BE=f.prototype.writeUInt32BE=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,4,4294967295,0),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},f.prototype.writeBigUInt64LE=Z((function(t,e=0){return M(this,t,e,BigInt(0),BigInt("0xffffffffffffffff"))})),f.prototype.writeBigUInt64BE=Z((function(t,e=0){return C(this,t,e,BigInt(0),BigInt("0xffffffffffffffff"))})),f.prototype.writeIntLE=function(t,e,r,n){if(t=+t,e>>>=0,!n){const n=Math.pow(2,8*r-1);O(this,t,e,r,n-1,-n);}let i=0,o=1,f=0;for(this[e]=255&t;++i<r&&(o*=256);)t<0&&0===f&&0!==this[e+i-1]&&(f=1),this[e+i]=(t/o|0)-f&255;return e+r},f.prototype.writeIntBE=function(t,e,r,n){if(t=+t,e>>>=0,!n){const n=Math.pow(2,8*r-1);O(this,t,e,r,n-1,-n);}let i=r-1,o=1,f=0;for(this[e+i]=255&t;--i>=0&&(o*=256);)t<0&&0===f&&0!==this[e+i+1]&&(f=1),this[e+i]=(t/o|0)-f&255;return e+r},f.prototype.writeInt8=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,1,127,-128),t<0&&(t=255+t+1),this[e]=255&t,e+1},f.prototype.writeInt16LE=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,2,32767,-32768),this[e]=255&t,this[e+1]=t>>>8,e+2},f.prototype.writeInt16BE=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,2,32767,-32768),this[e]=t>>>8,this[e+1]=255&t,e+2},f.prototype.writeInt32LE=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,4,2147483647,-2147483648),this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24,e+4},f.prototype.writeInt32BE=function(t,e,r){return t=+t,e>>>=0,r||O(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},f.prototype.writeBigInt64LE=Z((function(t,e=0){return M(this,t,e,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),f.prototype.writeBigInt64BE=Z((function(t,e=0){return C(this,t,e,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),f.prototype.writeFloatLE=function(t,e,r){return x(this,t,e,true,r)},f.prototype.writeFloatBE=function(t,e,r){return x(this,t,e,false,r)},f.prototype.writeDoubleLE=function(t,e,r){return k(this,t,e,true,r)},f.prototype.writeDoubleBE=function(t,e,r){return k(this,t,e,false,r)},f.prototype.copy=function(t,e,r,n){if(!f.isBuffer(t))throw new TypeError("argument should be a Buffer");if(r||(r=0),n||0===n||(n=this.length),e>=t.length&&(e=t.length),e||(e=0),n>0&&n<r&&(n=r),n===r)return 0;if(0===t.length||0===this.length)return 0;if(e<0)throw new RangeError("targetStart out of bounds");if(r<0||r>=this.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-e<n-r&&(n=t.length-e+r);const i=n-r;return this===t&&"function"==typeof Uint8Array.prototype.copyWithin?this.copyWithin(e,r,n):Uint8Array.prototype.set.call(t,this.subarray(r,n),e),i},f.prototype.fill=function(t,e,r,n){if("string"==typeof t){if("string"==typeof e?(n=e,e=0,r=this.length):"string"==typeof r&&(n=r,r=this.length),void 0!==n&&"string"!=typeof n)throw new TypeError("encoding must be a string");if("string"==typeof n&&!f.isEncoding(n))throw new TypeError("Unknown encoding: "+n);if(1===t.length){const e=t.charCodeAt(0);("utf8"===n&&e<128||"latin1"===n)&&(t=e);}}else "number"==typeof t?t&=255:"boolean"==typeof t&&(t=Number(t));if(e<0||this.length<e||this.length<r)throw new RangeError("Out of range index");if(r<=e)return this;let i;if(e>>>=0,r=void 0===r?this.length:r>>>0,t||(t=0),"number"==typeof t)for(i=e;i<r;++i)this[i]=t;else {const o=f.isBuffer(t)?t:f.from(t,n),s=o.length;if(0===s)throw new TypeError('The value "'+t+'" is invalid for argument "value"');for(i=0;i<r-e;++i)this[i+e]=o[i%s];}return this};const P={};function $(t,e,r){P[t]=class extends r{constructor(){super(),Object.defineProperty(this,"message",{value:e.apply(this,arguments),writable:true,configurable:true}),this.name=`${this.name} [${t}]`,this.stack,delete this.name;}get code(){return t}set code(t){Object.defineProperty(this,"code",{configurable:true,enumerable:true,value:t,writable:true});}toString(){return `${this.name} [${t}]: ${this.message}`}};}function H(t){let e="",r=t.length;const n="-"===t[0]?1:0;for(;r>=n+4;r-=3)e=`_${t.slice(r-3,r)}${e}`;return `${t.slice(0,r)}${e}`}function F(t,e,r,n,i,o){if(t>r||t<e){const r="bigint"==typeof e?"n":"";let n;throw n=0===e||e===BigInt(0)?`>= 0${r} and < 2${r} ** ${8*(o+1)}${r}`:`>= -(2${r} ** ${8*(o+1)-1}${r}) and < 2 ** ${8*(o+1)-1}${r}`,new P.ERR_OUT_OF_RANGE("value",n,t)}!function(t,e,r){z(e,"offset"),void 0!==t[e]&&void 0!==t[e+r]||Y(e,t.length-(r+1));}(n,i,o);}function z(t,e){if("number"!=typeof t)throw new P.ERR_INVALID_ARG_TYPE(e,"number",t)}function Y(t,e,r){if(Math.floor(t)!==t)throw z(t,r),new P.ERR_OUT_OF_RANGE("offset","an integer",t);if(e<0)throw new P.ERR_BUFFER_OUT_OF_BOUNDS;throw new P.ERR_OUT_OF_RANGE("offset",`>= 0 and <= ${e}`,t)}$("ERR_BUFFER_OUT_OF_BOUNDS",(function(t){return t?`${t} is outside of buffer bounds`:"Attempt to access memory outside buffer bounds"}),RangeError),$("ERR_INVALID_ARG_TYPE",(function(t,e){return `The "${t}" argument must be of type number. Received type ${typeof e}`}),TypeError),$("ERR_OUT_OF_RANGE",(function(t,e,r){let n=`The value of "${t}" is out of range.`,i=r;return Number.isInteger(r)&&Math.abs(r)>2**32?i=H(String(r)):"bigint"==typeof r&&(i=String(r),(r>BigInt(2)**BigInt(32)||r<-(BigInt(2)**BigInt(32)))&&(i=H(i)),i+="n"),n+=` It must be ${e}. Received ${i}`,n}),RangeError);const K=/[^+/0-9A-Za-z-_]/g;function q(t,e){let r;e=e||1/0;const n=t.length;let i=null;const o=[];for(let f=0;f<n;++f){if(r=t.charCodeAt(f),r>55295&&r<57344){if(!i){if(r>56319){(e-=3)>-1&&o.push(239,191,189);continue}if(f+1===n){(e-=3)>-1&&o.push(239,191,189);continue}i=r;continue}if(r<56320){(e-=3)>-1&&o.push(239,191,189),i=r;continue}r=65536+(i-55296<<10|r-56320);}else i&&(e-=3)>-1&&o.push(239,191,189);if(i=null,r<128){if((e-=1)<0)break;o.push(r);}else if(r<2048){if((e-=2)<0)break;o.push(r>>6|192,63&r|128);}else if(r<65536){if((e-=3)<0)break;o.push(r>>12|224,r>>6&63|128,63&r|128);}else {if(!(r<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;o.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128);}}return o}function V(t){return e.toByteArray(function(t){if((t=(t=t.split("=")[0]).trim().replace(K,"")).length<2)return "";for(;t.length%4!=0;)t+="=";return t}(t))}function J(t,e,r,n){let i;for(i=0;i<n&&!(i+r>=e.length||i>=t.length);++i)e[i+r]=t[i];return i}function Q(t,e){return t instanceof e||null!=t&&null!=t.constructor&&null!=t.constructor.name&&t.constructor.name===e.name}function X(t){return t!=t}const W=function(){const t="0123456789abcdef",e=new Array(256);for(let r=0;r<16;++r){const n=16*r;for(let i=0;i<16;++i)e[n+i]=t[r]+t[i];}return e}();function Z(t){return "undefined"==typeof BigInt?tt:t}function tt(){throw new Error("BigInt not supported")}}(z)),z);let J={AUTH_REQ:176,AUTH_NONCE:177,AUTH_HMAC:178,AUTH_ACK:179,AUTH_FAIL:180,AUTH_EXT:181,ENC_PACK:182,ENC_E2E:183,ENC_488:184};for(let t in J)J[J[t]]=t;const Q={AUTH_REQ:H.meta(H.MB("header","8",0),H.MB("reserved","8",0)),AUTH_NONCE:H.meta(H.MB("header","8",0),H.MB("unixTime","32L",0),H.MB("milTime","32L",0),H.MB("nonce",V.Buffer.alloc(4))),AUTH_HMAC:H.meta(H.MB("header","8",0),H.MB("id8",V.Buffer.alloc(8)),H.MB("nonce",V.Buffer.alloc(4)),H.MB("hmac32",V.Buffer.alloc(32))),AUTH_ACK:H.meta(H.MB("header","8",0),H.MB("hmac32",V.Buffer.alloc(32))),ENC_PACK:H.meta(H.MB("type","8",0),H.MB("len","32L",0),H.MB("salt12",V.Buffer.alloc(12)),H.MB("hmac",8,0)),ENC_488:H.meta(H.MB("type","8",0),H.MB("len","32L",0),H.MB("otpSrc8",V.Buffer.alloc(8)),H.MB("hmac8",V.Buffer.alloc(8)))};function X(t){let e=t[t.length-1];return e[2]+e[3]}const W={AUTH_REQ:X(Q.AUTH_REQ),AUTH_NONCE:X(Q.AUTH_NONCE),AUTH_HMAC:X(Q.AUTH_HMAC),AUTH_ACK:X(Q.AUTH_ACK),ENC_PACK:X(Q.ENC_PACK),ENC_488:X(Q.ENC_488)};function Z(t){return globalThis.crypto.getRandomValues(V.Buffer.alloc(t))}class tt{constructor(){this._id8=V.Buffer.alloc(8),this._otpSrc44=V.Buffer.alloc(44),this._otp36=V.Buffer.alloc(36),this._hmac=V.Buffer.alloc(32),this.auth_salt12=V.Buffer.alloc(12),this.localNonce=V.Buffer.alloc(4),this.remoteNonce=V.Buffer.alloc(4),this.isAuthorized=false;}clearAuth(){this._id8.fill(0),this._otpSrc44.fill(0),this._otp36.fill(0),this._hmac.fill(0),this.auth_salt12.fill(0),this.localNonce.fill(0),this.remoteNonce.fill(0),this.isAuthorized=false;}set_hash_id8(t){H.B8(F.hash(t)).copy(this._id8,0,0,8);}set_id8(t){let e=H.B8(t);this._id8.fill(0),e.copy(this._id8,0,0,8);}set_key(t){H.B8(F.hash(t)).copy(this._otpSrc44,0,0,32);}set_id_key(t){let e=t.indexOf(".");if(-1==e)return;let r=t.substring(0,e),n=t.substring(e+1);this.set_id8(r),this.set_key(n);}copy_id8(t){t.copy(this._id8,0,0,8);}copy_key(t){t.copy(this._otpSrc44,0,0,32);}sha256_n(t,e){let r=F.hash(t);for(let t=0;t<e;t++)r=F.hash(r);return r}set_clock_rand(){let t=Date.now(),e=parseInt(t/1e3);t%=4294967295;V.Buffer.concat([H.NB("32L",e),H.NB("32L",t),Z(4)]).copy(this._otpSrc44,32);}set_clock_nonce(t){let e=Date.now(),r=parseInt(e/1e3);e%=4294967295;V.Buffer.concat([H.NB("32L",r),H.NB("32L",e),t]).copy(this._otpSrc44,32);}set_salt12(t){t.copy(this._otpSrc44,32);}resetOTP(){H.B8(F.hash(this._otpSrc44)).copy(this._otp36,0,0,32);}getIndexOTP(t){return this._otp36.writeUInt32LE(t,32),F.hash(this._otp36)}generateHMAC(t){let e=V.Buffer.concat([this._otpSrc44,t]);this._hmac=H.B8(F.hash(e));}getHMAC8(t){let e=V.Buffer.concat([this._otpSrc44,t]);return this._hmac=H.B8(F.hash(e)),this._hmac.subarray(0,8)}xotp(t,e=0,r=false){let n=(t=H.B8(t,r)).byteLength,i=e,o=0,f=0;for(;n>0;){f=n<32?n:32;let e=this.getIndexOTP(++i);for(let r=0;r<f;r++)t[o++]^=e[r];n-=32;}return t}auth_req(){return H.pack(H.MB("#type","8",J.AUTH_REQ),H.MB("#reserved","8",0))}auth_nonce(){let t=Date.now(),e=Math.floor(t/1e3),r=t%1e3;return this.localNonce=Z(4),this.auth_salt12=V.Buffer.concat([H.NB("32L",e),H.NB("32L",r),this.localNonce]),V.Buffer.concat([H.NB("8",J.AUTH_NONCE),this.auth_salt12])}auth_hmac(t){let e=H.unpack(t,Q.AUTH_NONCE);if(e){let t=V.Buffer.concat([H.NB("32L",e.unixTime),H.NB("32L",e.milTime),e.nonce]);return this.set_salt12(t),this.localNonce=Z(4),this.generateHMAC(this.localNonce),this.remoteNonce=e.nonce,H.pack(H.MB("#header","8",J.AUTH_HMAC),H.MB("#id8",this._id8),H.MB("#nonce",this.localNonce),H.MB("#hmac32",this._hmac))}return false}check_auth_hmac(t){let e;if(t instanceof Uint8Array){if(e=H.unpack(t,Q.AUTH_HMAC),!e)return}else e=t;this.set_salt12(this.auth_salt12),this.generateHMAC(e.nonce);let r=this._hmac;if(H.equal(e.hmac32,r)){this.remoteNonce=e.nonce;let t=V.Buffer.concat([this.localNonce,this.remoteNonce,this.localNonce]);this.set_salt12(t),this.generateHMAC(e.nonce);let r=this._hmac,n=H.rawPack(H.MB("header","8",J.AUTH_ACK),H.MB("hmac32",r));return this.isAuthorized=true,n}return false}check_auth_ack_hmac(t){let e=H.unpack(t,Q.AUTH_ACK);if(e){let t=V.Buffer.concat([this.remoteNonce,this.localNonce,this.remoteNonce]);this.set_salt12(t),this.generateHMAC(this.localNonce);let r=this._hmac;if(H.equal(r,e.hmac32))return this.isAuthorized=true,true}}encrypt_488(t){if(!this.isAuthorized)return;t=H.B8(t),this.set_clock_nonce(this.remoteNonce),this.resetOTP();let e=this.getHMAC8(t),r=this.xotp(t);return H.pack(H.MB("#type","8",J.ENC_488),H.MB("#len","32L",t.byteLength),H.MB("#otpSrc8",this._otpSrc44.subarray(32,40)),H.MB("#hmac8",e),H.MB("#xdata",r))}decrypt_488(t){t=H.B8(t);let e=H.unpack(t,Q.ENC_488);if(e){let t=V.Buffer.concat([e.otpSrc8,this.localNonce]);this.set_salt12(t),this.resetOTP();let r=e.$OTHERS.subarray(0,e.len),n=this.xotp(r),i=this.getHMAC8(n);if(H.equal(i,e.hmac8))return n}}encryptPack(t){t=H.B8(t),this.set_clock_rand(),this.resetOTP();let e=this.getHMAC8(t),r=this.xotp(t);return H.pack(H.MB("#type","8",J.ENC_PACK),H.MB("#len","32L",t.byteLength),H.MB("#salt12",this._otpSrc44.subarray(32)),H.MB("#hmac8",e),H.MB("#xdata",r))}decryptPack(t){if(t[0]!==J.ENC_PACK)return;if(t.readUint32LE(1)==t.byteLength-W.ENC_PACK)try{let e=H.unpack(t,Q.ENC_PACK);if(!e)return;this.set_salt12(e.salt12),this.resetOTP();let r=e.$OTHERS,n=this.xotp(r),i=this.getHMAC8(n);if(H.equal(e.hmac,i))return e.data=n,e}catch(t){}}encrypt_e2e(t,e){let r=V.Buffer.alloc(32);r.set(this._otpSrc44.subarray(0,32)),this.set_key(e);let n=this.encryptPack(t);return this._otpSrc44.set(r),n}decrypt_e2e(t,e){let r=V.Buffer.alloc(32);r.set(this._otpSrc44.subarray(0,32)),this.set_key(e);let n=this.decryptPack(t);return this._otpSrc44.set(r),n}}tt.RAND=Z,tt.BohoMsg=J,tt.Meta=Q,tt.MetaSize=W,tt.sha256=F,tt.MBP=H,tt.Buffer=V.Buffer;
693
783
 
784
+ /**
785
+ * @typedef {import('meta-buffer-pack').MBP} MBP
786
+ * @typedef {import('../common/constants.js').IOMsg} IOMsg
787
+ * @typedef {import('../common/constants.js').PAYLOAD_TYPE} PAYLOAD_TYPE
788
+ * @typedef {import('../common/constants.js').SIZE_LIMIT} SIZE_LIMIT
789
+ * @typedef {import('../common/constants.js').ENC_MODE} ENC_MODE
790
+ * @typedef {import('../common/constants.js').STATES} STATES
791
+ * @typedef {import('../common/quotaTable.js').quotaTable} quotaTable
792
+
793
+ * @typedef {import('boho').Boho} Boho
794
+ * @typedef {import('boho').Buffer} Buffer
795
+ */
796
+
694
797
  const Buffer$1 = M$1.Buffer;
695
798
  const encoder$1 = new TextEncoder();
696
799
  const decoder$4 = new TextDecoder();
@@ -704,76 +807,292 @@ function byteToUrl(buffer) {
704
807
  return address + ':' + port.toString()
705
808
  }
706
809
 
810
+ /**
811
+ * Core class for handling WebSocket communication.
812
+ * @augments {EventEmitter}
813
+ */
707
814
  class IOCore extends EventEmitter {
815
+ /**
816
+ * @param {string} url - The WebSocket URL to connect to.
817
+ */
708
818
  constructor(url) {
709
819
  super();
820
+ /**
821
+ * Client ID received from the server.
822
+ * @type {string}
823
+ */
710
824
  this.cid = ""; // get from the server CID_RES
825
+ /**
826
+ * IP address received from the server.
827
+ * @type {string}
828
+ */
711
829
  this.ip = ""; // get from the server IAM_RES message.
830
+ /**
831
+ * The WebSocket instance.
832
+ * @type {WebSocket | null}
833
+ */
712
834
  this.socket = null;
835
+ /**
836
+ * The default server URL.
837
+ * @type {string}
838
+ */
713
839
  this.url = url; // init default server url
840
+ /**
841
+ * Current connection state (number).
842
+ * @type {number}
843
+ */
714
844
  this.state = STATES.CLOSED; // Number type
845
+ /**
846
+ * Current connection state (string).
847
+ * @type {string}
848
+ */
715
849
  this.stateName = this.getStateName(); // String type
716
850
 
851
+ /**
852
+ * Transmitted message counter.
853
+ * @type {number}
854
+ */
717
855
  this.txCounter = 0;
856
+ /**
857
+ * Received message counter.
858
+ * @type {number}
859
+ */
718
860
  this.rxCounter = 0;
861
+ /**
862
+ * Transmitted bytes counter.
863
+ * @type {number}
864
+ */
719
865
  this.txBytes = 0;
866
+ /**
867
+ * Received bytes counter.
868
+ * @type {number}
869
+ */
720
870
  this.rxBytes = 0;
721
871
 
872
+ /**
873
+ * Last transmit/receive time.
874
+ * @type {number}
875
+ */
722
876
  this.lastTxRxTime = Date.now();
877
+ /**
878
+ * Period for connection checker.
879
+ * @type {number}
880
+ */
723
881
  this.connectionCheckerPeriod = SIZE_LIMIT.CONNECTION_CHECKER_PERIOD;
882
+ /**
883
+ * Interval ID for connection checker.
884
+ * @type {NodeJS.Timeout | null}
885
+ */
724
886
  this.connectionCheckerIntervalID = null;
725
887
 
888
+ /**
889
+ * Boho instance for encryption/decryption.
890
+ * @type {Boho}
891
+ */
726
892
  this.boho = new tt();
893
+ /**
894
+ * Indicates if the connection is TLS (wss).
895
+ * @type {boolean}
896
+ */
727
897
  this.TLS = false; // true if protocol is wss(TLS)
898
+ /**
899
+ * Encryption mode.
900
+ * @type {number}
901
+ */
728
902
  this.encMode = ENC_MODE.AUTO;
903
+ /**
904
+ * Indicates if authentication is used.
905
+ * @type {boolean}
906
+ */
729
907
  this.useAuth = false;
730
908
 
909
+ /**
910
+ * Nickname.
911
+ * @type {string}
912
+ */
731
913
  this.nick = "";
914
+ /**
915
+ * Set of subscribed channels.
916
+ * @type {Set<string>}
917
+ */
732
918
  this.channels = new Set();
919
+ /**
920
+ * Map of promises for message responses.
921
+ * @type {Map<number, Array<Function>>}
922
+ */
733
923
  this.promiseMap = new Map();
924
+ /**
925
+ * Timeout for message promises.
926
+ * @type {number}
927
+ */
734
928
  this.promiseTimeOut = SIZE_LIMIT.PROMISE_TIMEOUT;
929
+ /**
930
+ * Message ID for promises.
931
+ * @type {number}
932
+ */
735
933
  this.mid = 0; // promise message id
736
934
 
935
+ /**
936
+ * Quota level.
937
+ * @type {number}
938
+ */
737
939
  this.level = 3; // also defaultQuotaLevel
940
+ /**
941
+ * Quota table for current level.
942
+ * @type {object}
943
+ */
738
944
  this.quota = quotaTable[this.level];
945
+ /**
946
+ * Server settings.
947
+ * @type {object}
948
+ */
739
949
  this.serverSet = {};
950
+ /**
951
+ * Map of linked channels.
952
+ * @type {Map<string, Set<string>>}
953
+ */
740
954
  this.linkMap = new Map();
741
955
 
956
+ /**
957
+ * Indicates if auto-reconnect is enabled.
958
+ * @type {boolean}
959
+ * @default true
960
+ * */
961
+ this.autoReconnect = true; // default true
962
+
963
+ /**
964
+ * A flag to prevent duplicate close operations.
965
+ * @type {boolean}
966
+ * @private
967
+ */
968
+ this._closed = false; // 중복 close 방지
969
+
742
970
  this.on('open', this.onOpen.bind(this));
743
971
  this.on('close', this.onClose.bind(this));
744
972
  this.on('socket_data', this.onData.bind(this));
745
973
  }
746
974
 
747
975
 
976
+
977
+ /**
978
+ * Performs common cleanup for the connection. It clears pending promises,
979
+ * resets the socket reference, and sets the state to closed.
980
+ * This method is guarded to only run once.
981
+ * If autoReconnect is false, it also clears the keep-alive timer.
982
+ */
983
+ close() {
984
+ if (this._closed) return;
985
+ this._closed = true;
986
+
987
+ // If auto-reconnect is disabled, we must stop the keep-alive timer.
988
+ if (this.autoReconnect === false) {
989
+ clearInterval(this.connectionCheckerIntervalID);
990
+ this.connectionCheckerIntervalID = null;
991
+ }
992
+
993
+ // socket clean
994
+ if (this.socket) {
995
+ // For WebSockets, readyState are: 0-CONNECTING, 1-OPEN, 2-CLOSING, 3-CLOSED
996
+ // Calling close() on a CONNECTING socket will cause a browser error.
997
+ if (this.socket.readyState === 0) { // 0 is WebSocket.CONNECTING
998
+ // To avoid the error, we wait for the connection to open, then immediately close it.
999
+ // We also clear other handlers to prevent any other logic from running.
1000
+ const socket = this.socket;
1001
+ socket.onopen = () => { if(socket) socket.close(); };
1002
+ socket.onmessage = null;
1003
+ socket.onerror = null;
1004
+ socket.onclose = null;
1005
+ } else {
1006
+ try {
1007
+ // For other sockets (like TCP) or other WebSocket states, close directly.
1008
+ this.socket.close?.();
1009
+ } catch {}
1010
+ }
1011
+ this.socket = null;
1012
+ }
1013
+ this.promiseMap.clear();
1014
+ this.emit('closed');
1015
+ this.stateChange('closed');
1016
+ }
1017
+
1018
+ /**
1019
+ * Disables auto-reconnect and closes the current connection.
1020
+ * The instance can be re-opened manually later. For complete cleanup, use destroy().
1021
+ */
1022
+ stop() {
1023
+ this.autoReconnect = false;
1024
+ this.close();
1025
+ }
1026
+
1027
+ /**
1028
+ * Permanently destroys the instance, cleaning up all resources.
1029
+ * The instance will not be usable after this.
1030
+ */
1031
+ destroy() {
1032
+ this.stop();
1033
+ this.removeAllListeners();
1034
+
1035
+ this.channels.clear();
1036
+ this.linkMap.clear();
1037
+
1038
+ // Help GC
1039
+ this.boho = null;
1040
+ }
1041
+
1042
+ /**
1043
+ * The core keep-alive logic. It checks if auto-reconnect is enabled.
1044
+ * The actual check for the socket's state is implemented in the child classes.
1045
+ */
1046
+ keepAlive() {
1047
+ if (!this.autoReconnect) return;
1048
+ // The specific logic for checking the socket's state and reconnecting
1049
+ // is implemented in the child classes (IOWS, IOCongSocket, etc.).
1050
+ }
1051
+
1052
+ /**
1053
+ * Redirects the connection to a new URL.
1054
+ * @param {string} url2 - The new URL to redirect to.
1055
+ */
748
1056
  redirect(url2) {
749
1057
  this.close();
750
1058
  this.stateChange('redirecting');
751
1059
  this.createConnection(url2);
752
1060
  }
753
1061
 
1062
+ /**
1063
+ * Opens the WebSocket connection.
1064
+ * @param {string} [url] - Optional URL to connect to. If not provided, uses the instance's URL.
1065
+ */
754
1066
  open(url) {
755
- if (!url && !this.url) return;
1067
+ // If a connection is already active or in progress, calling open() implies a reconnect.
1068
+ // Close the existing socket first to ensure a clean state.
1069
+ if (this.socket) {
1070
+ this.close();
1071
+ }
756
1072
 
757
1073
  if (url) {
758
- if (!this.url) { // default host url
759
- this.url = url;
760
- } else if (url !== this.url) { // default host url change
761
- this.url = url;
762
- if (this.socket) {
763
- this.close();
764
- return
765
- }
766
- }
1074
+ this.url = url;
767
1075
  }
768
1076
 
1077
+ if (!this.url) {
1078
+ this.emit('error', new Error('URL is not set.'));
1079
+ return;
1080
+ }
1081
+
1082
+ // The actual connection is created here.
769
1083
  this.createConnection(this.url);
770
1084
 
1085
+ // Ensure the keep-alive timer is running.
771
1086
  if (!this.connectionCheckerIntervalID) {
772
1087
  this.connectionCheckerIntervalID = setInterval(this.keepAlive.bind(this), this.connectionCheckerPeriod);
773
1088
  }
774
1089
  }
775
1090
 
1091
+ /**
1092
+ * Handles the 'open' event of the WebSocket. Resets the closed flag and sets the state to open.
1093
+ */
776
1094
  onOpen() {
1095
+ this._closed = false;
777
1096
  if (this.url.includes("wss://")) {
778
1097
  this.TLS = true;
779
1098
  } else {
@@ -782,39 +1101,40 @@ class IOCore extends EventEmitter {
782
1101
  this.stateChange('open');
783
1102
  }
784
1103
 
1104
+ /**
1105
+ * Handles the 'close' event of the WebSocket.
1106
+ */
785
1107
  onClose() {
786
1108
  this.boho.isAuthorized = false;
787
1109
  this.cid = "";
788
1110
  this.stateChange('closed');
789
1111
  }
790
1112
 
791
- // manual login
1113
+ /**
1114
+ * Manually logs in with provided ID and key.
1115
+ * @param {string} id - The user ID.
1116
+ * @param {string} key - The user key.
1117
+ * @returns {boolean}
1118
+ */
792
1119
  login(id, key) {
793
- if (!id && !key) {
794
- console.log('no id and key.');
795
- return
796
- }
797
- console.log('manual login: ', id);
1120
+ if (!this.auth(id, key)) return false;
798
1121
 
799
- if (!key && id.includes('.')) {
800
- this.boho.set_id_key(id);
801
- } else if (id && key) {
802
- this.boho.set_id8(id);
803
- this.boho.set_key(key);
804
- } else {
805
- console.log('no id or key.');
806
- return
807
- }
808
1122
  this.useAuth = true;
809
1123
  let auth_pack = this.boho.auth_req();
810
1124
  this.send(auth_pack);
1125
+ return true
811
1126
  }
812
1127
 
813
- // auto login
1128
+ /**
1129
+ * Sets up authentication for auto-login.
1130
+ * @param {string} id - The user ID.
1131
+ * @param {string} key - The user key.
1132
+ * @returns {boolean}
1133
+ */
814
1134
  auth(id, key) {
815
1135
  if (!id && !key) {
816
- console.log('no id and key.');
817
- return
1136
+ this.emit('error', new Error('auth failed. no id and key.'));
1137
+ return false
818
1138
  }
819
1139
 
820
1140
  if (!key && id.includes('.')) {
@@ -823,12 +1143,17 @@ class IOCore extends EventEmitter {
823
1143
  this.boho.set_id8(id);
824
1144
  this.boho.set_key(key);
825
1145
  } else {
826
- console.log('no id or key.');
827
- return
1146
+ this.emit('error', new Error('auth failed. no id or key.'));
1147
+ return false
828
1148
  }
829
1149
  this.useAuth = true;
1150
+ return true
830
1151
  }
831
1152
 
1153
+ /**
1154
+ * Handles incoming data from the WebSocket.
1155
+ * @param {Buffer} buffer - The incoming data buffer.
1156
+ */
832
1157
  onData(buffer) {
833
1158
  let msgType = buffer[0];
834
1159
  let decoded;
@@ -847,8 +1172,8 @@ class IOCore extends EventEmitter {
847
1172
  // console.log( 'ENC_E2E decoded ', decoded )
848
1173
  msgType = decoded[0];
849
1174
  // decoded has msg_header only.
850
- buffer.set(decoded, tt.MetaSize.ENC_488); // set decoded signal_e2e headaer.
851
- buffer = buffer.subarray(tt.MetaSize.ENC_488); // reset offset.
1175
+ buffer.set(decoded, tt.MetaSize.ENC_488); // set decoded signal_e2e headaer.
1176
+ buffer = buffer.subarray(tt.MetaSize.ENC_488); // reset offset.
852
1177
  // console.log('DECODED MsgType:', IOMsg[ msgType ] )
853
1178
  } else {
854
1179
  // console.log('488 DEC_FAIL', buffer)
@@ -886,10 +1211,8 @@ class IOCore extends EventEmitter {
886
1211
  if (jsonInfo.ip) {
887
1212
  this.ip = jsonInfo.ip;
888
1213
  }
889
- console.log('<IAM_RES>', JSON.stringify(jsonInfo));
890
- // console.log('<IAM_RES>', JSON.stringify(jsonInfo,null,2))
891
1214
  } catch (error) {
892
- // console.log('<IAM_RES> data error')
1215
+ this.emit('error', new Error('IAM_RES data error'));
893
1216
  }
894
1217
  break;
895
1218
 
@@ -953,7 +1276,7 @@ class IOCore extends EventEmitter {
953
1276
  }
954
1277
 
955
1278
  } catch (error) {
956
- // console.log('<SERVER_SIGNAL> parsing error')
1279
+ this.emit('error', new Error('SERVER_SIGNAL parsing error'));
957
1280
  }
958
1281
  break;
959
1282
 
@@ -964,7 +1287,7 @@ class IOCore extends EventEmitter {
964
1287
  this.emit(setPack.topic, ...setPack.args);
965
1288
  }
966
1289
  } catch (error) {
967
- // console.log('<SET> parsing error')
1290
+ this.emit('error', new Error('SET parsing error'));
968
1291
  }
969
1292
  break;
970
1293
 
@@ -993,7 +1316,10 @@ class IOCore extends EventEmitter {
993
1316
  case PAYLOAD_TYPE.TEXT:
994
1317
  // !! Must remove null char before decode in JS.
995
1318
  // string payload contains null char for the c/cpp devices.
996
- let payloadStringWithoutNull = payloadBuffer.subarray(0, payloadBuffer.byteLength - 1);
1319
+ let payloadStringWithoutNull = payloadBuffer;
1320
+ if (payloadBuffer[payloadBuffer.byteLength - 1] === 0) {
1321
+ payloadStringWithoutNull = payloadBuffer.subarray(0, payloadBuffer.byteLength - 1);
1322
+ }
997
1323
  let oneString = decoder$4.decode(payloadStringWithoutNull);
998
1324
  if (tag.indexOf('@') === 0) this.emit('@', oneString, tag);
999
1325
  if (tag !== '@') this.emit(tag, oneString, tag);
@@ -1029,7 +1355,7 @@ class IOCore extends EventEmitter {
1029
1355
  }
1030
1356
 
1031
1357
  } catch (err) {
1032
- // console.log('## signal parse err', err)
1358
+ this.emit('error', new Error('signal parse err'));
1033
1359
  }
1034
1360
  break;
1035
1361
 
@@ -1073,6 +1399,10 @@ class IOCore extends EventEmitter {
1073
1399
  }
1074
1400
  }
1075
1401
 
1402
+ /**
1403
+ * Sends an IAM (I Am) message to the server.
1404
+ * @param {string} [title] - Optional title for the IAM message.
1405
+ */
1076
1406
  iam(title) {
1077
1407
  // console.log('iam', title)
1078
1408
  if (title) {
@@ -1088,17 +1418,25 @@ class IOCore extends EventEmitter {
1088
1418
  }
1089
1419
 
1090
1420
 
1421
+ /**
1422
+ * Sends a PING message to the server.
1423
+ */
1091
1424
  ping() {
1092
1425
  this.send(Buffer$1.from([IOMsg.PING]));
1093
1426
  }
1094
1427
 
1428
+ /**
1429
+ * Sends a PONG message to the server.
1430
+ */
1095
1431
  pong() {
1096
1432
  this.send(Buffer$1.from([IOMsg.PONG]));
1097
1433
  }
1098
1434
 
1099
1435
 
1100
- // application level ping tool.
1101
- // simple message sending and reply.
1436
+ /**
1437
+ * Sends an ECHO message to the server.
1438
+ * @param {*} [args] - Optional arguments to echo.
1439
+ */
1102
1440
  echo(args) {
1103
1441
  if (args) {
1104
1442
  console.log('echo args:', args);
@@ -1113,10 +1451,18 @@ class IOCore extends EventEmitter {
1113
1451
  }
1114
1452
 
1115
1453
 
1454
+ /**
1455
+ * Sends binary data.
1456
+ * @param {...any} data - Data to send.
1457
+ */
1116
1458
  bin(...data) {
1117
1459
  this.send(M$1.U8pack(...data));
1118
1460
  }
1119
1461
 
1462
+ /**
1463
+ * Sends data over the WebSocket.
1464
+ * @param {Buffer} data - The data buffer to send.
1465
+ */
1120
1466
  send(data) {
1121
1467
  if (data.byteLength > this.quota.signalSize) {
1122
1468
  this.emit('over_size');
@@ -1127,22 +1473,10 @@ class IOCore extends EventEmitter {
1127
1473
  this.socket_send(data);
1128
1474
  }
1129
1475
 
1130
- /*
1131
- Policy. Should message do encrypt?
1132
-
1133
- if encMode == auto
1134
- NO. if connection using TLS line.
1135
- // ex. wss://url connection.
1136
- YES. if no TLS line.
1137
- // ex. ws://url connection.
1138
-
1139
- if encMode == YES
1140
- YES. encrypt the message.
1141
-
1142
- if encMode == NO
1143
- NO. do not ecnrypt message.
1144
-
1145
- */
1476
+ /**
1477
+ * Determines if encryption should be used based on current mode and TLS status.
1478
+ * @returns {boolean}
1479
+ */
1146
1480
  getEncryptionMode() {
1147
1481
  if (this.encMode === ENC_MODE.YES ||
1148
1482
  this.encMode === ENC_MODE.AUTO &&
@@ -1154,6 +1488,11 @@ class IOCore extends EventEmitter {
1154
1488
  }
1155
1489
  }
1156
1490
 
1491
+ /**
1492
+ * Sends data with encryption based on the encryption mode.
1493
+ * @param {Buffer} data - The data buffer to send.
1494
+ * @param {boolean} [useEncryption] - Optional. Force encryption or not. If undefined, uses default policy.
1495
+ */
1157
1496
  send_enc_mode(data, useEncryption) {
1158
1497
 
1159
1498
  // use default policy.
@@ -1182,6 +1521,11 @@ class IOCore extends EventEmitter {
1182
1521
  }
1183
1522
 
1184
1523
 
1524
+ /**
1525
+ * Sets a message promise for a given message ID.
1526
+ * @param {number} mid - The message ID.
1527
+ * @returns {Promise<any>}
1528
+ */
1185
1529
  setMsgPromise(mid) {
1186
1530
  return new Promise((resolve, reject) => {
1187
1531
  this.promiseMap.set(mid, [resolve, reject]);
@@ -1194,6 +1538,10 @@ class IOCore extends EventEmitter {
1194
1538
  })
1195
1539
  }
1196
1540
 
1541
+ /**
1542
+ * Tests and resolves/rejects a promise based on the incoming buffer.
1543
+ * @param {Buffer} buffer - The incoming data buffer.
1544
+ */
1197
1545
  testPromise(buffer) {
1198
1546
 
1199
1547
  let res = M$1.unpack(buffer);
@@ -1218,11 +1566,21 @@ class IOCore extends EventEmitter {
1218
1566
  }
1219
1567
 
1220
1568
 
1569
+ /**
1570
+ * Publishes a signal.
1571
+ * @param {...any} args - Arguments for the signal.
1572
+ */
1221
1573
  publish(...args) {
1222
1574
  this.signal(...args);
1223
1575
  }
1224
1576
 
1225
1577
 
1578
+ /**
1579
+ * Sends a signal with a tag and arguments.
1580
+ * @param {string} tag - The signal tag.
1581
+ * @param {...any} args - Arguments for the signal.
1582
+ * @throws {TypeError} If tag is not a string.
1583
+ */
1226
1584
  signal(tag, ...args) {
1227
1585
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1228
1586
 
@@ -1230,10 +1588,23 @@ class IOCore extends EventEmitter {
1230
1588
  this.send_enc_mode(signalPack);
1231
1589
  }
1232
1590
 
1591
+ /**
1592
+ * Decrypts E2E data.
1593
+ * @param {Buffer} data - The encrypted data.
1594
+ * @param {string} key - The decryption key.
1595
+ * @returns {Buffer}
1596
+ */
1233
1597
  decrypt_e2e(data, key) {
1234
1598
  return this.boho.decrypt_e2e(data, key)
1235
1599
  }
1236
1600
 
1601
+ /**
1602
+ * Sends an E2E (End-to-End) encrypted signal.
1603
+ * @param {string} tag - The signal tag.
1604
+ * @param {Buffer} data - The data to encrypt and send.
1605
+ * @param {string} key - The encryption key.
1606
+ * @throws {TypeError} If tag is not a string.
1607
+ */
1237
1608
  signal_e2e(tag, data, key) {
1238
1609
 
1239
1610
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
@@ -1257,6 +1628,12 @@ class IOCore extends EventEmitter {
1257
1628
 
1258
1629
 
1259
1630
 
1631
+ /**
1632
+ * Sets a value in the store.
1633
+ * @param {string} storeName - The name of the store.
1634
+ * @param {...any} args - Arguments to set.
1635
+ * @returns {Promise<any>}
1636
+ */
1260
1637
  set(storeName, ...args) {
1261
1638
  if (!storeName || args.length == 0) {
1262
1639
  return Promise.reject(new Error('set need storeName and value)'))
@@ -1264,6 +1641,11 @@ class IOCore extends EventEmitter {
1264
1641
  return this.req('store', 'set', storeName, ...args)
1265
1642
  }
1266
1643
 
1644
+ /**
1645
+ * Gets a value from the store.
1646
+ * @param {string} storeName - The name of the store.
1647
+ * @returns {Promise<any>}
1648
+ */
1267
1649
  async get(storeName) {
1268
1650
  if (!storeName) {
1269
1651
  return Promise.reject(new Error('store get need storeName)'))
@@ -1274,6 +1656,13 @@ class IOCore extends EventEmitter {
1274
1656
  }
1275
1657
 
1276
1658
 
1659
+ /**
1660
+ * Sends a request to a target and topic.
1661
+ * @param {string} target - The target of the request.
1662
+ * @param {string} topic - The topic of the request.
1663
+ * @param {...any} args - Optional arguments for the request.
1664
+ * @returns {Promise<any>}
1665
+ */
1277
1666
  req(target, topic, ...args) {
1278
1667
  if (!target || !topic)
1279
1668
  return Promise.reject(new Error('request need target and topic)'))
@@ -1299,6 +1688,11 @@ class IOCore extends EventEmitter {
1299
1688
  }
1300
1689
 
1301
1690
 
1691
+ /**
1692
+ * Subscribes to a channel or channels.
1693
+ * @param {string} tag - The tag(s) of the channel(s) to subscribe to (comma-separated).
1694
+ * @throws {TypeError} If tag is not a string or exceeds length limit.
1695
+ */
1302
1696
  subscribe(tag) {
1303
1697
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1304
1698
  if (this.state !== STATES.READY) return
@@ -1318,6 +1712,12 @@ class IOCore extends EventEmitter {
1318
1712
  tagEncoded]));
1319
1713
  }
1320
1714
 
1715
+ /**
1716
+ * Subscribes to a channel or channels with a promise.
1717
+ * @param {string} tag - The tag(s) of the channel(s) to subscribe to (comma-separated).
1718
+ * @returns {Promise<any>}
1719
+ * @throws {TypeError} If tag is not a string or exceeds length limit.
1720
+ */
1321
1721
  subscribe_promise(tag) {
1322
1722
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1323
1723
  if (this.state !== STATES.READY) {
@@ -1336,6 +1736,9 @@ class IOCore extends EventEmitter {
1336
1736
  return this.setMsgPromise(this.mid)
1337
1737
  }
1338
1738
 
1739
+ /**
1740
+ * Subscribes to channels stored in memory (local cache).
1741
+ */
1339
1742
  subscribe_memory_channels() { //local cache . auto_resubscribe
1340
1743
  if (this.channels.size == 0) return
1341
1744
  let chList = Array.from(this.channels).join(',');
@@ -1349,6 +1752,11 @@ class IOCore extends EventEmitter {
1349
1752
 
1350
1753
  }
1351
1754
 
1755
+ /**
1756
+ * Unsubscribes from a channel or channels.
1757
+ * @param {string} [tag=""] - The tag(s) of the channel(s) to unsubscribe from (comma-separated). If empty, unsubscribes from all.
1758
+ * @throws {TypeError} If tag is not a string or exceeds length limit.
1759
+ */
1352
1760
  unsubscribe(tag = "") {
1353
1761
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1354
1762
 
@@ -1371,6 +1779,12 @@ class IOCore extends EventEmitter {
1371
1779
  }
1372
1780
 
1373
1781
 
1782
+ /**
1783
+ * Listens for signals on a specific tag.
1784
+ * @param {string} tag - The tag to listen on.
1785
+ * @param {Function} handler - The callback function to handle the signal.
1786
+ * @throws {TypeError} If tag is not a string, handler is not a function, or tag length is invalid.
1787
+ */
1374
1788
  listen(tag, handler) {
1375
1789
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1376
1790
  if (tag.length > 255 || tag.length == 0) throw TypeError('tag string length range: 1~255')
@@ -1387,6 +1801,13 @@ class IOCore extends EventEmitter {
1387
1801
 
1388
1802
 
1389
1803
 
1804
+ /**
1805
+ * Links a local target to a remote tag and sets up a handler.
1806
+ * @param {string} to - The local link target.
1807
+ * @param {string} tag - The remote tag.
1808
+ * @param {Function} handler - The callback function to handle the signal.
1809
+ * @throws {TypeError} If 'to' or 'tag' are not strings, handler is not a function, or tag length is invalid.
1810
+ */
1390
1811
  link(to, tag, handler) {
1391
1812
  if (typeof to !== 'string') throw TypeError('to(local link target) is not a string.')
1392
1813
  if (typeof tag !== 'string') throw TypeError('tag is not a string.')
@@ -1412,44 +1833,54 @@ class IOCore extends EventEmitter {
1412
1833
  }
1413
1834
 
1414
1835
 
1836
+ /**
1837
+ * Unlinks a specific tag from a local target.
1838
+ * @param {string} to - The local link target.
1839
+ * @param {string} tag - The tag to unlink.
1840
+ * @throws {TypeError} If 'to' or 'tag' are not strings or tag length is invalid.
1841
+ */
1415
1842
  unlink(to, tag) {
1416
1843
  if (typeof to !== 'string') throw TypeError('to(local link target) is not a string.')
1417
1844
  if (typeof tag !== 'string') throw TypeError('tag is not a string.')
1418
1845
  if (tag.length > 255 || tag.length == 0) throw TypeError('tag string length range: 1~255')
1419
1846
 
1420
- if (!this.linkMap.has(to)) return;
1847
+ const linkSet = this.linkMap.get(to);
1848
+ if (!linkSet || !linkSet.has(tag)) return;
1421
1849
 
1422
- let linkSet = this.linkMap.get(to);
1423
- let tags = Array.from(linkSet);
1424
- for (let i = 0; i < tags.length; i++) {
1425
- if (tags[i] == tag) {
1426
- this.unsubscribe(tag);
1427
- this.removeAllListeners(tag);
1428
- linkSet.delete(tag);
1429
- this.linkMap.set(to, linkSet);
1430
- break;
1431
- }
1432
- }
1850
+ this.unsubscribe(tag);
1851
+ this.removeAllListeners(tag);
1852
+ linkSet.delete(tag);
1433
1853
 
1854
+ if (linkSet.size === 0) {
1855
+ this.linkMap.delete(to);
1856
+ }
1434
1857
  }
1435
1858
 
1859
+ /**
1860
+ * Unlinks all tags from a local target.
1861
+ * @param {string} to - The local link target.
1862
+ * @throws {TypeError} If 'to' is not a string.
1863
+ */
1436
1864
  unlinkAll(to) {
1437
1865
  if (typeof to !== 'string') throw TypeError('to(local link target) is not a string.')
1438
- if (!this.linkMap.has(to)) return;
1439
-
1440
- let linkSet = this.linkMap.get(to);
1441
- let tags = Array.from(linkSet);
1442
- for (let i = 0; i < tags.length; i++) {
1443
- this.unsubscribe(tags[i]);
1444
- this.removeAllListeners(tags[i]);
1445
- linkSet.delete(tags[i]);
1866
+
1867
+ const linkSet = this.linkMap.get(to);
1868
+ if (!linkSet) return;
1869
+
1870
+ for (const tag of linkSet) {
1871
+ this.unsubscribe(tag);
1872
+ this.removeAllListeners(tag);
1446
1873
  }
1447
- this.linkMap.delete(to);
1448
1874
 
1875
+ this.linkMap.delete(to);
1449
1876
  }
1450
1877
 
1451
1878
 
1452
1879
 
1880
+ /**
1881
+ * Gets connection metrics.
1882
+ * @returns {{tx: number, rx: number, txb: number, rxb: number, last: number}}
1883
+ */
1453
1884
  getMetric() {
1454
1885
  return {
1455
1886
  tx: this.txCounter,
@@ -1461,10 +1892,18 @@ class IOCore extends EventEmitter {
1461
1892
 
1462
1893
  }
1463
1894
 
1895
+ /**
1896
+ * Gets the current connection state.
1897
+ * @returns {number}
1898
+ */
1464
1899
  getState() {
1465
1900
  return this.state
1466
1901
  }
1467
1902
 
1903
+ /**
1904
+ * Gets the current connection state name.
1905
+ * @returns {string}
1906
+ */
1468
1907
  getStateName() {
1469
1908
  //state <number>
1470
1909
  //value of constant STATES.NAME < number >
@@ -1473,6 +1912,10 @@ class IOCore extends EventEmitter {
1473
1912
  return (STATES[this.state]).toLowerCase()
1474
1913
  }
1475
1914
 
1915
+ /**
1916
+ * Gets security-related information.
1917
+ * @returns {{useAuth: boolean, isTLS: boolean, isAuthorized: boolean, encMode: number, usingEncryption: boolean}}
1918
+ */
1476
1919
  getSecurity() {
1477
1920
  return {
1478
1921
  useAuth: this.useAuth,
@@ -1483,6 +1926,11 @@ class IOCore extends EventEmitter {
1483
1926
  }
1484
1927
  }
1485
1928
 
1929
+ /**
1930
+ * Changes the connection state and emits events.
1931
+ * @param {string} state - The new state name (e.g., 'ready', 'closed').
1932
+ * @param {string} [emitEventAndMessage] - Optional message to emit with the state change event.
1933
+ */
1486
1934
  stateChange(state, emitEventAndMessage) {
1487
1935
  // STATES constant name : string upperCase
1488
1936
  // eventName, .stateName : string lowerCase
@@ -1642,20 +2090,30 @@ class IOCongSocket extends IOCore {
1642
2090
  if (url) this.open();
1643
2091
  }
1644
2092
 
2093
+ /**
2094
+ * Closes TCP socket and cleans resources.
2095
+ */
1645
2096
  close() {
1646
- this.socket?.end();
1647
- this.socket = null;
2097
+ if (this.socket) {
2098
+ if (this.congRx) {
2099
+ this.socket.unpipe(this.congRx);
2100
+ this.congRx.destroy(); // Use destroy() for complete stream cleanup
2101
+ this.congRx = null;
2102
+ }
2103
+ this.socket.removeAllListeners();
2104
+ if (!this.socket.destroyed) {
2105
+ this.socket.destroy(); // destroy() is sufficient for forceful closing
2106
+ }
2107
+ }
2108
+ super.close();
1648
2109
  }
1649
2110
 
1650
- stop() {
1651
- this.close();
1652
- clearInterval(this.connectionCheckerIntervalID);
1653
- this.connectionCheckerIntervalID = null;
1654
- }
2111
+
1655
2112
 
1656
2113
  keepAlive() {
1657
- let state = this.socket?.readyState;
1658
- if (!this.socket || !(state === 'open' || state === 'opening')) {
2114
+ if (!this.autoReconnect) return;
2115
+ // Reconnect only if the socket is fully destroyed and the state is closed.
2116
+ if ((!this.socket || this.socket.destroyed) && this.state === STATES.CLOSED) {
1659
2117
  this.open();
1660
2118
  }
1661
2119
  }
@@ -7065,32 +7523,28 @@ class IOWS extends IOCore {
7065
7523
 
7066
7524
 
7067
7525
 
7526
+ /**
7527
+ * Closes ws WebSocket and cleans resources.
7528
+ */
7068
7529
  close() {
7069
7530
  if (this.socket) {
7070
- this.socket.onclose = null;
7071
- this.socket.onmessage = null;
7072
- this.socket.onerror = null;
7073
- this.socket.close();
7074
- this.socket = null;
7531
+ this.socket.removeAllListeners();
7532
+ if (this.socket.readyState !== WebSocket.CLOSED) {
7533
+ this.socket.close();
7534
+ }
7075
7535
  }
7076
- this.emit('close');
7536
+ super.close();
7077
7537
  }
7078
7538
 
7079
7539
 
7080
-
7081
- stop() {
7082
- this.close();
7083
- clearInterval(this.connectionCheckerIntervalID);
7084
- this.connectionCheckerIntervalID = null;
7085
- }
7086
-
7087
7540
  keepAlive() {
7088
- if (!this.socket || this.socket?.readyState === 3) {
7541
+ if (!this.autoReconnect) return;
7542
+ // Reconnect only if the socket is closed and the state reflects that.
7543
+ if ((!this.socket || this.socket.readyState === WebSocket.CLOSED) && this.state === STATES.CLOSED) {
7089
7544
  this.open();
7090
7545
  }
7091
7546
  }
7092
7547
 
7093
-
7094
7548
  createConnection(url) {
7095
7549
  // node WebSocket
7096
7550
  this.socket = new WebSocket(url);