iosignal 3.0.0 → 3.0.1

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 (35) hide show
  1. package/README.md +144 -1
  2. package/dist/io.d.ts +481 -0
  3. package/dist/io.js +3 -3
  4. package/dist/io.js.map +1 -1
  5. package/dist/io.min.js +3 -3
  6. package/dist/io.min.js.map +1 -1
  7. package/dist/iosignal.js +543 -102
  8. package/dist/types/client/IOCore.d.ts +408 -0
  9. package/dist/types/client/browser/IOWebSocket.d.ts +75 -0
  10. package/dist/types/common/constants.d.ts +169 -0
  11. package/dist/types/common/payload.d.ts +6 -0
  12. package/dist/types/common/quotaTable.d.ts +47 -0
  13. package/docs/{README.kr.md → README.ko.md} +143 -2
  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 +1628 -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.json +12 -0
  28. package/package.json +9 -3
  29. package/rollup.config.js +11 -4
  30. package/src/client/IOCongSocket.js +20 -9
  31. package/src/client/IOCore.js +422 -77
  32. package/src/client/IOWS.js +12 -15
  33. package/src/client/browser/IOWebSocket.js +112 -13
  34. package/src/common/constants.js +91 -1
  35. package/tsconfig.json +24 -0
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.0.1";
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,279 @@ 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
+ try {
996
+ this.socket.close?.();
997
+ } catch {}
998
+ this.socket = null;
999
+ }
1000
+ this.promiseMap.clear();
1001
+ this.emit('closed');
1002
+ this.stateChange('closed');
1003
+ }
1004
+
1005
+ /**
1006
+ * Disables auto-reconnect and closes the current connection.
1007
+ * The instance can be re-opened manually later. For complete cleanup, use destroy().
1008
+ */
1009
+ stop() {
1010
+ this.autoReconnect = false;
1011
+ this.close();
1012
+ }
1013
+
1014
+ /**
1015
+ * Permanently destroys the instance, cleaning up all resources.
1016
+ * The instance will not be usable after this.
1017
+ */
1018
+ destroy() {
1019
+ this.stop();
1020
+ this.removeAllListeners();
1021
+
1022
+ this.channels.clear();
1023
+ this.linkMap.clear();
1024
+
1025
+ // Help GC
1026
+ this.boho = null;
1027
+ }
1028
+
1029
+ /**
1030
+ * The core keep-alive logic. It checks if auto-reconnect is enabled.
1031
+ * The actual check for the socket's state is implemented in the child classes.
1032
+ */
1033
+ keepAlive() {
1034
+ if (!this.autoReconnect) return;
1035
+ // The specific logic for checking the socket's state and reconnecting
1036
+ // is implemented in the child classes (IOWS, IOCongSocket, etc.).
1037
+ }
1038
+
1039
+ /**
1040
+ * Redirects the connection to a new URL.
1041
+ * @param {string} url2 - The new URL to redirect to.
1042
+ */
748
1043
  redirect(url2) {
749
1044
  this.close();
750
1045
  this.stateChange('redirecting');
751
1046
  this.createConnection(url2);
752
1047
  }
753
1048
 
1049
+ /**
1050
+ * Opens the WebSocket connection.
1051
+ * @param {string} [url] - Optional URL to connect to. If not provided, uses the instance's URL.
1052
+ */
754
1053
  open(url) {
755
- if (!url && !this.url) return;
1054
+ // If a connection is already active or in progress, calling open() implies a reconnect.
1055
+ // Close the existing socket first to ensure a clean state.
1056
+ if (this.socket) {
1057
+ this.close();
1058
+ }
756
1059
 
757
1060
  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
- }
1061
+ this.url = url;
1062
+ }
1063
+
1064
+ if (!this.url) {
1065
+ this.emit('error', new Error('URL is not set.'));
1066
+ return;
767
1067
  }
768
1068
 
1069
+ // The actual connection is created here.
769
1070
  this.createConnection(this.url);
770
1071
 
1072
+ // Ensure the keep-alive timer is running.
771
1073
  if (!this.connectionCheckerIntervalID) {
772
1074
  this.connectionCheckerIntervalID = setInterval(this.keepAlive.bind(this), this.connectionCheckerPeriod);
773
1075
  }
774
1076
  }
775
1077
 
1078
+ /**
1079
+ * Handles the 'open' event of the WebSocket. Resets the closed flag and sets the state to open.
1080
+ */
776
1081
  onOpen() {
1082
+ this._closed = false;
777
1083
  if (this.url.includes("wss://")) {
778
1084
  this.TLS = true;
779
1085
  } else {
@@ -782,39 +1088,40 @@ class IOCore extends EventEmitter {
782
1088
  this.stateChange('open');
783
1089
  }
784
1090
 
1091
+ /**
1092
+ * Handles the 'close' event of the WebSocket.
1093
+ */
785
1094
  onClose() {
786
1095
  this.boho.isAuthorized = false;
787
1096
  this.cid = "";
788
1097
  this.stateChange('closed');
789
1098
  }
790
1099
 
791
- // manual login
1100
+ /**
1101
+ * Manually logs in with provided ID and key.
1102
+ * @param {string} id - The user ID.
1103
+ * @param {string} key - The user key.
1104
+ * @returns {boolean}
1105
+ */
792
1106
  login(id, key) {
793
- if (!id && !key) {
794
- console.log('no id and key.');
795
- return
796
- }
797
- console.log('manual login: ', id);
1107
+ if (!this.auth(id, key)) return false;
798
1108
 
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
1109
  this.useAuth = true;
809
1110
  let auth_pack = this.boho.auth_req();
810
1111
  this.send(auth_pack);
1112
+ return true
811
1113
  }
812
1114
 
813
- // auto login
1115
+ /**
1116
+ * Sets up authentication for auto-login.
1117
+ * @param {string} id - The user ID.
1118
+ * @param {string} key - The user key.
1119
+ * @returns {boolean}
1120
+ */
814
1121
  auth(id, key) {
815
1122
  if (!id && !key) {
816
- console.log('no id and key.');
817
- return
1123
+ this.emit('error', new Error('auth failed. no id and key.'));
1124
+ return false
818
1125
  }
819
1126
 
820
1127
  if (!key && id.includes('.')) {
@@ -823,12 +1130,17 @@ class IOCore extends EventEmitter {
823
1130
  this.boho.set_id8(id);
824
1131
  this.boho.set_key(key);
825
1132
  } else {
826
- console.log('no id or key.');
827
- return
1133
+ this.emit('error', new Error('auth failed. no id or key.'));
1134
+ return false
828
1135
  }
829
1136
  this.useAuth = true;
1137
+ return true
830
1138
  }
831
1139
 
1140
+ /**
1141
+ * Handles incoming data from the WebSocket.
1142
+ * @param {Buffer} buffer - The incoming data buffer.
1143
+ */
832
1144
  onData(buffer) {
833
1145
  let msgType = buffer[0];
834
1146
  let decoded;
@@ -886,10 +1198,8 @@ class IOCore extends EventEmitter {
886
1198
  if (jsonInfo.ip) {
887
1199
  this.ip = jsonInfo.ip;
888
1200
  }
889
- console.log('<IAM_RES>', JSON.stringify(jsonInfo));
890
- // console.log('<IAM_RES>', JSON.stringify(jsonInfo,null,2))
891
1201
  } catch (error) {
892
- // console.log('<IAM_RES> data error')
1202
+ this.emit('error', new Error('IAM_RES data error'));
893
1203
  }
894
1204
  break;
895
1205
 
@@ -953,7 +1263,7 @@ class IOCore extends EventEmitter {
953
1263
  }
954
1264
 
955
1265
  } catch (error) {
956
- // console.log('<SERVER_SIGNAL> parsing error')
1266
+ this.emit('error', new Error('SERVER_SIGNAL parsing error'));
957
1267
  }
958
1268
  break;
959
1269
 
@@ -964,7 +1274,7 @@ class IOCore extends EventEmitter {
964
1274
  this.emit(setPack.topic, ...setPack.args);
965
1275
  }
966
1276
  } catch (error) {
967
- // console.log('<SET> parsing error')
1277
+ this.emit('error', new Error('SET parsing error'));
968
1278
  }
969
1279
  break;
970
1280
 
@@ -993,7 +1303,10 @@ class IOCore extends EventEmitter {
993
1303
  case PAYLOAD_TYPE.TEXT:
994
1304
  // !! Must remove null char before decode in JS.
995
1305
  // string payload contains null char for the c/cpp devices.
996
- let payloadStringWithoutNull = payloadBuffer.subarray(0, payloadBuffer.byteLength - 1);
1306
+ let payloadStringWithoutNull = payloadBuffer;
1307
+ if (payloadBuffer[payloadBuffer.byteLength - 1] === 0) {
1308
+ payloadStringWithoutNull = payloadBuffer.subarray(0, payloadBuffer.byteLength - 1);
1309
+ }
997
1310
  let oneString = decoder$4.decode(payloadStringWithoutNull);
998
1311
  if (tag.indexOf('@') === 0) this.emit('@', oneString, tag);
999
1312
  if (tag !== '@') this.emit(tag, oneString, tag);
@@ -1029,7 +1342,7 @@ class IOCore extends EventEmitter {
1029
1342
  }
1030
1343
 
1031
1344
  } catch (err) {
1032
- // console.log('## signal parse err', err)
1345
+ this.emit('error', new Error('signal parse err'));
1033
1346
  }
1034
1347
  break;
1035
1348
 
@@ -1073,6 +1386,10 @@ class IOCore extends EventEmitter {
1073
1386
  }
1074
1387
  }
1075
1388
 
1389
+ /**
1390
+ * Sends an IAM (I Am) message to the server.
1391
+ * @param {string} [title] - Optional title for the IAM message.
1392
+ */
1076
1393
  iam(title) {
1077
1394
  // console.log('iam', title)
1078
1395
  if (title) {
@@ -1088,17 +1405,25 @@ class IOCore extends EventEmitter {
1088
1405
  }
1089
1406
 
1090
1407
 
1408
+ /**
1409
+ * Sends a PING message to the server.
1410
+ */
1091
1411
  ping() {
1092
1412
  this.send(Buffer$1.from([IOMsg.PING]));
1093
1413
  }
1094
1414
 
1415
+ /**
1416
+ * Sends a PONG message to the server.
1417
+ */
1095
1418
  pong() {
1096
1419
  this.send(Buffer$1.from([IOMsg.PONG]));
1097
1420
  }
1098
1421
 
1099
1422
 
1100
- // application level ping tool.
1101
- // simple message sending and reply.
1423
+ /**
1424
+ * Sends an ECHO message to the server.
1425
+ * @param {*} [args] - Optional arguments to echo.
1426
+ */
1102
1427
  echo(args) {
1103
1428
  if (args) {
1104
1429
  console.log('echo args:', args);
@@ -1113,10 +1438,18 @@ class IOCore extends EventEmitter {
1113
1438
  }
1114
1439
 
1115
1440
 
1441
+ /**
1442
+ * Sends binary data.
1443
+ * @param {...any} data - Data to send.
1444
+ */
1116
1445
  bin(...data) {
1117
1446
  this.send(M$1.U8pack(...data));
1118
1447
  }
1119
1448
 
1449
+ /**
1450
+ * Sends data over the WebSocket.
1451
+ * @param {Buffer} data - The data buffer to send.
1452
+ */
1120
1453
  send(data) {
1121
1454
  if (data.byteLength > this.quota.signalSize) {
1122
1455
  this.emit('over_size');
@@ -1127,22 +1460,10 @@ class IOCore extends EventEmitter {
1127
1460
  this.socket_send(data);
1128
1461
  }
1129
1462
 
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
- */
1463
+ /**
1464
+ * Determines if encryption should be used based on current mode and TLS status.
1465
+ * @returns {boolean}
1466
+ */
1146
1467
  getEncryptionMode() {
1147
1468
  if (this.encMode === ENC_MODE.YES ||
1148
1469
  this.encMode === ENC_MODE.AUTO &&
@@ -1154,6 +1475,11 @@ class IOCore extends EventEmitter {
1154
1475
  }
1155
1476
  }
1156
1477
 
1478
+ /**
1479
+ * Sends data with encryption based on the encryption mode.
1480
+ * @param {Buffer} data - The data buffer to send.
1481
+ * @param {boolean} [useEncryption] - Optional. Force encryption or not. If undefined, uses default policy.
1482
+ */
1157
1483
  send_enc_mode(data, useEncryption) {
1158
1484
 
1159
1485
  // use default policy.
@@ -1182,6 +1508,11 @@ class IOCore extends EventEmitter {
1182
1508
  }
1183
1509
 
1184
1510
 
1511
+ /**
1512
+ * Sets a message promise for a given message ID.
1513
+ * @param {number} mid - The message ID.
1514
+ * @returns {Promise<any>}
1515
+ */
1185
1516
  setMsgPromise(mid) {
1186
1517
  return new Promise((resolve, reject) => {
1187
1518
  this.promiseMap.set(mid, [resolve, reject]);
@@ -1194,6 +1525,10 @@ class IOCore extends EventEmitter {
1194
1525
  })
1195
1526
  }
1196
1527
 
1528
+ /**
1529
+ * Tests and resolves/rejects a promise based on the incoming buffer.
1530
+ * @param {Buffer} buffer - The incoming data buffer.
1531
+ */
1197
1532
  testPromise(buffer) {
1198
1533
 
1199
1534
  let res = M$1.unpack(buffer);
@@ -1218,11 +1553,21 @@ class IOCore extends EventEmitter {
1218
1553
  }
1219
1554
 
1220
1555
 
1556
+ /**
1557
+ * Publishes a signal.
1558
+ * @param {...any} args - Arguments for the signal.
1559
+ */
1221
1560
  publish(...args) {
1222
1561
  this.signal(...args);
1223
1562
  }
1224
1563
 
1225
1564
 
1565
+ /**
1566
+ * Sends a signal with a tag and arguments.
1567
+ * @param {string} tag - The signal tag.
1568
+ * @param {...any} args - Arguments for the signal.
1569
+ * @throws {TypeError} If tag is not a string.
1570
+ */
1226
1571
  signal(tag, ...args) {
1227
1572
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1228
1573
 
@@ -1230,10 +1575,23 @@ class IOCore extends EventEmitter {
1230
1575
  this.send_enc_mode(signalPack);
1231
1576
  }
1232
1577
 
1578
+ /**
1579
+ * Decrypts E2E data.
1580
+ * @param {Buffer} data - The encrypted data.
1581
+ * @param {string} key - The decryption key.
1582
+ * @returns {Buffer}
1583
+ */
1233
1584
  decrypt_e2e(data, key) {
1234
1585
  return this.boho.decrypt_e2e(data, key)
1235
1586
  }
1236
1587
 
1588
+ /**
1589
+ * Sends an E2E (End-to-End) encrypted signal.
1590
+ * @param {string} tag - The signal tag.
1591
+ * @param {Buffer} data - The data to encrypt and send.
1592
+ * @param {string} key - The encryption key.
1593
+ * @throws {TypeError} If tag is not a string.
1594
+ */
1237
1595
  signal_e2e(tag, data, key) {
1238
1596
 
1239
1597
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
@@ -1257,6 +1615,12 @@ class IOCore extends EventEmitter {
1257
1615
 
1258
1616
 
1259
1617
 
1618
+ /**
1619
+ * Sets a value in the store.
1620
+ * @param {string} storeName - The name of the store.
1621
+ * @param {...any} args - Arguments to set.
1622
+ * @returns {Promise<any>}
1623
+ */
1260
1624
  set(storeName, ...args) {
1261
1625
  if (!storeName || args.length == 0) {
1262
1626
  return Promise.reject(new Error('set need storeName and value)'))
@@ -1264,6 +1628,11 @@ class IOCore extends EventEmitter {
1264
1628
  return this.req('store', 'set', storeName, ...args)
1265
1629
  }
1266
1630
 
1631
+ /**
1632
+ * Gets a value from the store.
1633
+ * @param {string} storeName - The name of the store.
1634
+ * @returns {Promise<any>}
1635
+ */
1267
1636
  async get(storeName) {
1268
1637
  if (!storeName) {
1269
1638
  return Promise.reject(new Error('store get need storeName)'))
@@ -1274,6 +1643,13 @@ class IOCore extends EventEmitter {
1274
1643
  }
1275
1644
 
1276
1645
 
1646
+ /**
1647
+ * Sends a request to a target and topic.
1648
+ * @param {string} target - The target of the request.
1649
+ * @param {string} topic - The topic of the request.
1650
+ * @param {...any} args - Optional arguments for the request.
1651
+ * @returns {Promise<any>}
1652
+ */
1277
1653
  req(target, topic, ...args) {
1278
1654
  if (!target || !topic)
1279
1655
  return Promise.reject(new Error('request need target and topic)'))
@@ -1299,6 +1675,11 @@ class IOCore extends EventEmitter {
1299
1675
  }
1300
1676
 
1301
1677
 
1678
+ /**
1679
+ * Subscribes to a channel or channels.
1680
+ * @param {string} tag - The tag(s) of the channel(s) to subscribe to (comma-separated).
1681
+ * @throws {TypeError} If tag is not a string or exceeds length limit.
1682
+ */
1302
1683
  subscribe(tag) {
1303
1684
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1304
1685
  if (this.state !== STATES.READY) return
@@ -1318,6 +1699,12 @@ class IOCore extends EventEmitter {
1318
1699
  tagEncoded]));
1319
1700
  }
1320
1701
 
1702
+ /**
1703
+ * Subscribes to a channel or channels with a promise.
1704
+ * @param {string} tag - The tag(s) of the channel(s) to subscribe to (comma-separated).
1705
+ * @returns {Promise<any>}
1706
+ * @throws {TypeError} If tag is not a string or exceeds length limit.
1707
+ */
1321
1708
  subscribe_promise(tag) {
1322
1709
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1323
1710
  if (this.state !== STATES.READY) {
@@ -1336,6 +1723,9 @@ class IOCore extends EventEmitter {
1336
1723
  return this.setMsgPromise(this.mid)
1337
1724
  }
1338
1725
 
1726
+ /**
1727
+ * Subscribes to channels stored in memory (local cache).
1728
+ */
1339
1729
  subscribe_memory_channels() { //local cache . auto_resubscribe
1340
1730
  if (this.channels.size == 0) return
1341
1731
  let chList = Array.from(this.channels).join(',');
@@ -1349,6 +1739,11 @@ class IOCore extends EventEmitter {
1349
1739
 
1350
1740
  }
1351
1741
 
1742
+ /**
1743
+ * Unsubscribes from a channel or channels.
1744
+ * @param {string} [tag=""] - The tag(s) of the channel(s) to unsubscribe from (comma-separated). If empty, unsubscribes from all.
1745
+ * @throws {TypeError} If tag is not a string or exceeds length limit.
1746
+ */
1352
1747
  unsubscribe(tag = "") {
1353
1748
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1354
1749
 
@@ -1371,6 +1766,12 @@ class IOCore extends EventEmitter {
1371
1766
  }
1372
1767
 
1373
1768
 
1769
+ /**
1770
+ * Listens for signals on a specific tag.
1771
+ * @param {string} tag - The tag to listen on.
1772
+ * @param {Function} handler - The callback function to handle the signal.
1773
+ * @throws {TypeError} If tag is not a string, handler is not a function, or tag length is invalid.
1774
+ */
1374
1775
  listen(tag, handler) {
1375
1776
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1376
1777
  if (tag.length > 255 || tag.length == 0) throw TypeError('tag string length range: 1~255')
@@ -1387,6 +1788,13 @@ class IOCore extends EventEmitter {
1387
1788
 
1388
1789
 
1389
1790
 
1791
+ /**
1792
+ * Links a local target to a remote tag and sets up a handler.
1793
+ * @param {string} to - The local link target.
1794
+ * @param {string} tag - The remote tag.
1795
+ * @param {Function} handler - The callback function to handle the signal.
1796
+ * @throws {TypeError} If 'to' or 'tag' are not strings, handler is not a function, or tag length is invalid.
1797
+ */
1390
1798
  link(to, tag, handler) {
1391
1799
  if (typeof to !== 'string') throw TypeError('to(local link target) is not a string.')
1392
1800
  if (typeof tag !== 'string') throw TypeError('tag is not a string.')
@@ -1412,44 +1820,54 @@ class IOCore extends EventEmitter {
1412
1820
  }
1413
1821
 
1414
1822
 
1823
+ /**
1824
+ * Unlinks a specific tag from a local target.
1825
+ * @param {string} to - The local link target.
1826
+ * @param {string} tag - The tag to unlink.
1827
+ * @throws {TypeError} If 'to' or 'tag' are not strings or tag length is invalid.
1828
+ */
1415
1829
  unlink(to, tag) {
1416
1830
  if (typeof to !== 'string') throw TypeError('to(local link target) is not a string.')
1417
1831
  if (typeof tag !== 'string') throw TypeError('tag is not a string.')
1418
1832
  if (tag.length > 255 || tag.length == 0) throw TypeError('tag string length range: 1~255')
1419
1833
 
1420
- if (!this.linkMap.has(to)) return;
1834
+ const linkSet = this.linkMap.get(to);
1835
+ if (!linkSet || !linkSet.has(tag)) return;
1421
1836
 
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
- }
1837
+ this.unsubscribe(tag);
1838
+ this.removeAllListeners(tag);
1839
+ linkSet.delete(tag);
1433
1840
 
1841
+ if (linkSet.size === 0) {
1842
+ this.linkMap.delete(to);
1843
+ }
1434
1844
  }
1435
1845
 
1846
+ /**
1847
+ * Unlinks all tags from a local target.
1848
+ * @param {string} to - The local link target.
1849
+ * @throws {TypeError} If 'to' is not a string.
1850
+ */
1436
1851
  unlinkAll(to) {
1437
1852
  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]);
1853
+
1854
+ const linkSet = this.linkMap.get(to);
1855
+ if (!linkSet) return;
1856
+
1857
+ for (const tag of linkSet) {
1858
+ this.unsubscribe(tag);
1859
+ this.removeAllListeners(tag);
1446
1860
  }
1447
- this.linkMap.delete(to);
1448
1861
 
1862
+ this.linkMap.delete(to);
1449
1863
  }
1450
1864
 
1451
1865
 
1452
1866
 
1867
+ /**
1868
+ * Gets connection metrics.
1869
+ * @returns {{tx: number, rx: number, txb: number, rxb: number, last: number}}
1870
+ */
1453
1871
  getMetric() {
1454
1872
  return {
1455
1873
  tx: this.txCounter,
@@ -1461,10 +1879,18 @@ class IOCore extends EventEmitter {
1461
1879
 
1462
1880
  }
1463
1881
 
1882
+ /**
1883
+ * Gets the current connection state.
1884
+ * @returns {number}
1885
+ */
1464
1886
  getState() {
1465
1887
  return this.state
1466
1888
  }
1467
1889
 
1890
+ /**
1891
+ * Gets the current connection state name.
1892
+ * @returns {string}
1893
+ */
1468
1894
  getStateName() {
1469
1895
  //state <number>
1470
1896
  //value of constant STATES.NAME < number >
@@ -1473,6 +1899,10 @@ class IOCore extends EventEmitter {
1473
1899
  return (STATES[this.state]).toLowerCase()
1474
1900
  }
1475
1901
 
1902
+ /**
1903
+ * Gets security-related information.
1904
+ * @returns {{useAuth: boolean, isTLS: boolean, isAuthorized: boolean, encMode: number, usingEncryption: boolean}}
1905
+ */
1476
1906
  getSecurity() {
1477
1907
  return {
1478
1908
  useAuth: this.useAuth,
@@ -1483,6 +1913,11 @@ class IOCore extends EventEmitter {
1483
1913
  }
1484
1914
  }
1485
1915
 
1916
+ /**
1917
+ * Changes the connection state and emits events.
1918
+ * @param {string} state - The new state name (e.g., 'ready', 'closed').
1919
+ * @param {string} [emitEventAndMessage] - Optional message to emit with the state change event.
1920
+ */
1486
1921
  stateChange(state, emitEventAndMessage) {
1487
1922
  // STATES constant name : string upperCase
1488
1923
  // eventName, .stateName : string lowerCase
@@ -1642,20 +2077,30 @@ class IOCongSocket extends IOCore {
1642
2077
  if (url) this.open();
1643
2078
  }
1644
2079
 
2080
+ /**
2081
+ * Closes TCP socket and cleans resources.
2082
+ */
1645
2083
  close() {
1646
- this.socket?.end();
1647
- this.socket = null;
2084
+ if (this.socket) {
2085
+ if (this.congRx) {
2086
+ this.socket.unpipe(this.congRx);
2087
+ this.congRx.destroy(); // Use destroy() for complete stream cleanup
2088
+ this.congRx = null;
2089
+ }
2090
+ this.socket.removeAllListeners();
2091
+ if (!this.socket.destroyed) {
2092
+ this.socket.destroy(); // destroy() is sufficient for forceful closing
2093
+ }
2094
+ }
2095
+ super.close();
1648
2096
  }
1649
2097
 
1650
- stop() {
1651
- this.close();
1652
- clearInterval(this.connectionCheckerIntervalID);
1653
- this.connectionCheckerIntervalID = null;
1654
- }
2098
+
1655
2099
 
1656
2100
  keepAlive() {
1657
- let state = this.socket?.readyState;
1658
- if (!this.socket || !(state === 'open' || state === 'opening')) {
2101
+ if (!this.autoReconnect) return;
2102
+ // Reconnect only if the socket is fully destroyed and the state is closed.
2103
+ if ((!this.socket || this.socket.destroyed) && this.state === STATES.CLOSED) {
1659
2104
  this.open();
1660
2105
  }
1661
2106
  }
@@ -7065,32 +7510,28 @@ class IOWS extends IOCore {
7065
7510
 
7066
7511
 
7067
7512
 
7513
+ /**
7514
+ * Closes ws WebSocket and cleans resources.
7515
+ */
7068
7516
  close() {
7069
7517
  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;
7518
+ this.socket.removeAllListeners();
7519
+ if (this.socket.readyState !== WebSocket.CLOSED) {
7520
+ this.socket.close();
7521
+ }
7075
7522
  }
7076
- this.emit('close');
7523
+ super.close();
7077
7524
  }
7078
7525
 
7079
7526
 
7080
-
7081
- stop() {
7082
- this.close();
7083
- clearInterval(this.connectionCheckerIntervalID);
7084
- this.connectionCheckerIntervalID = null;
7085
- }
7086
-
7087
7527
  keepAlive() {
7088
- if (!this.socket || this.socket?.readyState === 3) {
7528
+ if (!this.autoReconnect) return;
7529
+ // Reconnect only if the socket is closed and the state reflects that.
7530
+ if ((!this.socket || this.socket.readyState === WebSocket.CLOSED) && this.state === STATES.CLOSED) {
7089
7531
  this.open();
7090
7532
  }
7091
7533
  }
7092
7534
 
7093
-
7094
7535
  createConnection(url) {
7095
7536
  // node WebSocket
7096
7537
  this.socket = new WebSocket(url);