@rfkit/json-rpc-websocket 0.2.0 → 0.2.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.
- package/core/client.d.ts +107 -0
- package/core/client.d.ts.map +1 -0
- package/core/event-emitter.d.ts +31 -0
- package/core/event-emitter.d.ts.map +1 -0
- package/index.d.ts +11 -0
- package/index.d.ts.map +1 -0
- package/index.js +885 -1
- package/pack/deserializer.d.ts +10 -0
- package/pack/deserializer.d.ts.map +1 -0
- package/pack/index.d.ts +11 -0
- package/pack/index.d.ts.map +1 -0
- package/pack/serializer.d.ts +16 -0
- package/pack/serializer.d.ts.map +1 -0
- package/pack/types.d.ts +15 -0
- package/pack/types.d.ts.map +1 -0
- package/pack/utf8.d.ts +16 -0
- package/pack/utf8.d.ts.map +1 -0
- package/package.json +1 -1
- package/tools.d.ts +18 -0
- package/tools.d.ts.map +1 -0
- package/types/index.d.ts +6 -0
- package/types/index.d.ts.map +1 -0
- package/types/jsonrpc.d.ts +83 -0
- package/types/jsonrpc.d.ts.map +1 -0
- package/types/socket.d.ts +162 -0
- package/types/socket.d.ts.map +1 -0
package/index.js
CHANGED
|
@@ -1 +1,885 @@
|
|
|
1
|
-
function e(e){let t=e.length,n=!0;for(let r=0;r<t;r++)if(e.charCodeAt(r)>127){n=!1;break}if(n){let n=new Uint8Array(t);for(let r=0;r<t;r++)n[r]=e.charCodeAt(r);return n}let r=new Uint8Array(2*t),i=0;for(let n=0;n<t;n++){let s=e.charCodeAt(n);if(i+4>r.length){let e=new Uint8Array(Math.ceil(1.5*r.length));e.set(r),r=e}if(s<128)r[i++]=s;else if(s<2048)r[i++]=192|s>>>6,r[i++]=128|63&s;else if(s>=55296&&s<56320){if(n+1>=t)throw Error("UTF-8 encode: incomplete surrogate pair");let o=e.charCodeAt(++n);if(o<56320||o>57343)throw Error(`UTF-8 encode: second surrogate character 0x${o.toString(16)} at index ${n} out of range`);s=65536+((1023&s)<<10)+(1023&o),r[i++]=240|s>>>18,r[i++]=128|s>>>12&63,r[i++]=128|s>>>6&63,r[i++]=128|63&s}else r[i++]=224|s>>>12,r[i++]=128|s>>>6&63,r[i++]=128|63&s}return r.subarray(0,i)}function t(e,t,n){let r=t+n,i=!0;for(let n=t;n<r;n++)if(e[n]>127){i=!1;break}if(i)return String.fromCharCode(...e.subarray(t,r));let s="",o=t;for(;o<r;){let t=e[o++];if(t<128)s+=String.fromCharCode(t);else if(t<224){if(o>=r)throw Error("UTF-8 decode: incomplete 2-byte sequence");s+=String.fromCharCode((31&t)<<6|63&e[o++])}else if(t<240){if(o+1>=r)throw Error("UTF-8 decode: incomplete 3-byte sequence");s+=String.fromCharCode((15&t)<<12|(63&e[o++])<<6|63&e[o++])}else{if(o+2>=r)throw Error("UTF-8 decode: incomplete 4-byte sequence");let n=e[o++],i=(7&t)<<18|(63&n)<<12|(63&e[o++])<<6|63&e[o++];if(i<=65535)s+=String.fromCharCode(i);else if(i<=1114111)i-=65536,s+=String.fromCharCode(55296|i>>>10),s+=String.fromCharCode(56320|1023&i);else throw Error(`UTF-8 decode: code point 0x${i.toString(16)} exceeds UTF-16 reach`)}}return s}let n=0x100000000;function r(e,n){let r;if(e instanceof ArrayBuffer)r=new Uint8Array(e);else if(e instanceof Uint8Array)r=e;else if("object"==typeof e&&void 0!==e.length)r=new Uint8Array(e);else throw Error("Invalid argument type: Expected a byte array (Array or Uint8Array) to deserialize.");if(0===r.length)throw Error("Invalid argument: The byte array to deserialize is empty.");let i=0;if(null==n?void 0:n.multiple){let e=[];for(;i<r.length;)e.push(o());return e}return o();function s(e){if(i+e>r.length)throw Error(`Buffer overflow: trying to read ${e} bytes at position ${i}, but only ${r.length-i} bytes available`)}function o(){s(1);let e=r[i++];if(e>=0&&e<=127)return e;if(e>=128&&e<=143)return h(e-128);if(e>=144&&e<=159)return u(e-144);if(e>=160&&e<=191)return d(e-160);if(e>=224&&e<=255)return e-256;if(192===e)return null;if(194===e)return!1;if(195===e)return!0;if(196===e)return f(-1,1);if(197===e)return f(-1,2);if(198===e)return f(-1,4);if(199===e)return p(-1,1);if(200===e)return p(-1,2);if(201===e)return p(-1,4);if(212===e)return p(1);if(213===e)return p(2);if(214===e)return p(4);if(215===e)return p(8);if(216===e)return p(16);if(202===e)return c(4);if(203===e)return c(8);if(204===e)return a(1);if(205===e)return a(2);if(206===e)return a(4);if(207===e)return a(8);if(208===e)return l(1);if(209===e)return l(2);if(210===e)return l(4);if(211===e)return l(8);if(217===e)return d(-1,1);if(218===e)return d(-1,2);if(219===e)return d(-1,4);if(220===e)return u(-1,2);if(221===e)return u(-1,4);if(222===e)return h(-1,2);if(223===e)return h(-1,4);if(193===e)throw Error("Invalid byte code 0xc1 found.");throw Error(`Invalid byte value '${e}' at index ${i-1} in the MessagePack binary data (length ${r.length}): Expecting a range of 0 to 255. This is not a byte array.`)}function l(e){s(e);let t=0,n=!0;for(let s=0;s<e;s++)if(n){let e=r[i++];t+=127&e,128&e&&(t-=128),n=!1}else t=256*t+r[i++];return t}function a(e){s(e);let t=0;for(let n=0;n<e;n++)t=256*t+r[i++];return t}function c(e){s(e);let t=new DataView(r.buffer,i+r.byteOffset,e);return(i+=e,4===e)?t.getFloat32(0,!1):8===e?t.getFloat64(0,!1):0}function f(e,t){let n=e<0?a(t):e;s(n);let o=r.subarray(i,i+n);return i+=n,o}function h(e,t){let n=e<0&&void 0!==t?a(t):e,r={};for(let e=0;e<n;e++){let e=o();if("string"!=typeof e)throw Error(`Invalid map key type: expected string, got ${typeof e}`);r[e]=o()}return r}function u(e,t){let n=e<0&&void 0!==t?a(t):e,r=[];for(let e=0;e<n;e++)r.push(o());return r}function d(e,n){let o=e<0&&void 0!==n?a(n):e;s(o);let l=t(r,i,o);return i+=o,l}function p(e,t){let n=e<0&&void 0!==t?a(t):e;s(1+n);let r=a(1),o=f(n,0);return 255===r?function(e){if(4===e.length)return new Date(1e3*((e[0]<<24>>>0)+(e[1]<<16>>>0)+(e[2]<<8>>>0)+e[3]));if(8===e.length){let t=(e[0]<<22>>>0)+(e[1]<<14>>>0)+(e[2]<<6>>>0)+(e[3]>>>2);return new Date(1e3*((3&e[3])*0x100000000+(e[4]<<24>>>0)+(e[5]<<16>>>0)+(e[6]<<8>>>0)+e[7])+t/1e6)}if(12===e.length){let t=(e[0]<<24>>>0)+(e[1]<<16>>>0)+(e[2]<<8>>>0)+e[3];return i-=8,new Date(1e3*l(8)+t/1e6)}throw Error("Invalid data length for a date value.")}(o):{type:r,data:o}}}let i=0x100000000,s=0x1fffffffffffff;function o(t,n){let r,i;if((null==n?void 0:n.multiple)&&!Array.isArray(t))throw Error("Invalid argument type: Expected an Array to serialize multiple values.");let s=new Uint8Array(256),o=0;if((null==n?void 0:n.multiple)&&Array.isArray(t))for(let e of t)l(e);else l(t);return s.subarray(0,o);function l(t,s=!1){let o=typeof t;switch(o){case"undefined":c(192);break;case"boolean":c(t?195:194);break;case"number":!function(e){if(Number.isFinite(e)&&Math.floor(e)===e){if(e>=0&&e<=127)c(e);else if(e<0&&e>=-32)c(e);else if(e>0&&e<=255)f([204,e]);else if(e>=-128&&e<=127)f([208,e]);else if(e>0&&e<=65535)f([205,e>>>8,e]);else if(e>=-32768&&e<=32767)f([209,e>>>8,e]);else if(e>0&&e<=0xffffffff)f([206,e>>>24,e>>>16,e>>>8,e]);else if(e>=-0x80000000&&e<=0x7fffffff)f([210,e>>>24,e>>>16,e>>>8,e]);else if(e>0&&e<=0x1fffffffffffff){let t=Math.floor(e/0x100000000),n=Math.floor(e%0x100000000);f([211,t>>>24,t>>>16,t>>>8,t,n>>>24,n>>>16,n>>>8,n])}else e>=-0x1fffffffffffff&&e<=-0x80000001?(c(211),u(e)):e<0?f([211,128,0,0,0,0,0,0,0]):f([207,255,255,255,255,255,255,255,255])}else i||(i=new DataView(r=new ArrayBuffer(8))),i.setFloat64(0,e),c(203),f(new Uint8Array(r))}(t);break;case"string":!function(t){let n=e(t),r=n.length;r<=31?c(160+r):r<=255?f([217,r]):r<=65535?f([218,r>>>8,r]):f([219,r>>>24,r>>>16,r>>>8,r]),f(n)}(t);break;case"object":null===t?c(192):t instanceof Date?function(e){let t=e.getTime()/1e3;if(0===e.getMilliseconds()&&t>=0&&t<0x100000000){let e=Math.floor(t);f([214,255,e>>>24,e>>>16,e>>>8,e])}else if(t>=0&&t<0x400000000){let n=1e6*e.getMilliseconds(),r=Math.floor(t);f([215,255,n>>>22,n>>>14,n>>>6,n<<2>>>0|Math.floor(r/0x100000000),r>>>24,r>>>16,r>>>8,r])}else{let n=1e6*e.getMilliseconds();f([199,12,255,n>>>24,n>>>16,n>>>8,n]),u(t)}}(t):Array.isArray(t)?a(t):t instanceof Uint8Array||t instanceof Uint8ClampedArray?function(e){let t=e.length;t<=255?f([196,t]):t<=65535?f([197,t>>>8,t]):f([198,t>>>24,t>>>16,t>>>8,t]),f(e)}(t):t instanceof Int8Array||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array?a(Array.from(t)):function(e){let t=0;for(let n in e)void 0!==e[n]&&t++;for(let n in t<=15?c(128+t):t<=65535?f([222,t>>>8,t]):f([223,t>>>24,t>>>16,t>>>8,t]),e){let t=e[n];void 0!==t&&(l(n),l(t))}}(t);break;default:if(!s&&(null==n?void 0:n.invalidTypeReplacement))l("function"==typeof n.invalidTypeReplacement?n.invalidTypeReplacement(t):n.invalidTypeReplacement,!0);else throw Error(`Invalid argument type: The type '${o}' cannot be serialized.`)}}function a(e){let t=e.length;for(let n of(t<=15?c(144+t):t<=65535?f([220,t>>>8,t]):f([221,t>>>24,t>>>16,t>>>8,t]),e))l(n)}function c(e){s.length<o+1&&h(o+1),s[o++]=e}function f(e){let t=o+e.length;s.length<t&&h(t),s.set(e,o),o+=e.length}function h(e){let t=Math.ceil(1.5*s.length);for(;t<e;)t=Math.ceil(1.5*t);let n=new Uint8Array(t);n.set(s),s=n}function u(e){let t,n;if(e>=0)t=Math.floor(e/0x100000000),n=Math.floor(e%0x100000000);else{let r=Math.abs(e+1);t=~Math.floor(r/0x100000000),n=~Math.floor(r%0x100000000)}f([t>>>24,t>>>16,t>>>8,t,n>>>24,n>>>16,n>>>8,n])}}let l=o,a=r,c=o,f=r,h=()=>((1+Math.random())*65536|0).toString(16).substring(1),u=()=>[h()+h(),h(),h(),h(),h()+h()+h()].join("-"),d=(e=8)=>{let t="",n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",r=n.length;for(let i=0;i<e;i++)t+=n.charAt(Math.floor(Math.random()*r));return t};var p=/*#__PURE__*/function(e){return e[e.ParseError=-32700]="ParseError",e[e.InvalidRequest=-32600]="InvalidRequest",e[e.MethodNotFound=-32601]="MethodNotFound",e[e.InvalidParams=-32602]="InvalidParams",e[e.InternalError=-32603]="InternalError",e[e.ServerError=-32e3]="ServerError",e[e.Timeout=-32001]="Timeout",e[e.ConnectionClosed=-32002]="ConnectionClosed",e}({});function m(e,t,n,r){return{jsonrpc:"2.0",error:{code:t,message:n,data:r},id:e}}function g(e,t){return{jsonrpc:"2.0",result:t,id:e}}function y(e){return"error"in e}function b(e){return"result"in e}function v(e){return"method"in e&&!("id"in e)}var w=/*#__PURE__*/function(e){return e[e.Connecting=0]="Connecting",e[e.Open=1]="Open",e[e.Closing=2]="Closing",e[e.Closed=3]="Closed",e}({});let C={Open:"open",Close:"close",Error:"error",Message:"message",Reconnecting:"reconnecting",Reconnected:"reconnected",ReconnectFailed:"reconnect_failed"};function A(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class R{on(e,t){var n;return this.listeners.has(e)||this.listeners.set(e,new Set),null===(n=this.listeners.get(e))||void 0===n||n.add(t),()=>this.off(e,t)}once(e,t){let n=r=>{this.off(e,n),t(r)};return this.on(e,n)}off(e,t){let n=this.listeners.get(e);n&&(n.delete(t),0===n.size&&this.listeners.delete(e))}emit(e,t){let n=this.listeners.get(e);if(n)for(let r of n)try{r(t)}catch(t){console.error(`Error in event listener for "${String(e)}":`,t)}}removeAllListeners(e){e?this.listeners.delete(e):this.listeners.clear()}listenerCount(e){var t;return(null===(t=this.listeners.get(e))||void 0===t?void 0:t.size)??0}constructor(){A(this,"listeners",new Map)}}function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}let T={autoReconnect:!0,reconnectInterval:3e3,maxReconnectAttempts:5,defaultTimeout:15e3,heartbeatInterval:0,heartbeatMethod:"ping",debug:!1};class x extends R{get state(){var e;return(null===(e=this.ws)||void 0===e?void 0:e.readyState)??w.Closed}get isConnected(){return this.state===w.Open}getStats(){return{...this.stats,pendingRequests:this.pendingRequests.size}}connect(){if(!this.ws||this.ws.readyState!==w.Connecting)try{this.ws=new WebSocket(this.options.url,this.options.protocols),this.ws.binaryType="arraybuffer",this.ws.onopen=this.handleOpen.bind(this),this.ws.onmessage=this.handleMessage.bind(this),this.ws.onclose=this.handleClose.bind(this),this.ws.onerror=this.handleError.bind(this)}catch(e){this.log("Connection error:",e),this.scheduleReconnect()}}handleOpen(e){this.log("Connection opened"),this.reconnectAttempts=0,this.startHeartbeat(),this.emit(C.Open,e)}handleMessage(e){try{let t=e.data,n=f(new Uint8Array(t));if(this.log("Received:",n),this.stats.responsesReceived++,"error"in n&&this.stats.errors++,null!==n.id){let e=this.streamCallbacks.get(n.id);if(e){e(n),this.emit(C.Message,{data:n,rawData:t});return}let r=this.pendingRequests.get(n.id);if(r){clearTimeout(r.timeoutId),this.pendingRequests.delete(n.id);let e=Date.now()-r.timestamp;this.updateResponseTime(e),"error"in n?r.reject(Error(`${n.error.message} (${n.error.code})`)):r.resolve(n.result)}}this.emit(C.Message,{data:n,rawData:t})}catch(e){this.log("Failed to decode message:",e)}}handleClose(e){this.log("Connection closed:",e.code,e.reason),this.stopHeartbeat(),this.emit(C.Close,e),this.rejectAllPendingRequests(Error("Connection closed"),p.ConnectionClosed),this.options.autoReconnect&&this.scheduleReconnect()}handleError(e){this.log("Connection error:",e),this.emit(C.Error,e)}scheduleReconnect(){if(!this.reconnectTimeoutId){if(this.reconnectAttempts>=this.options.maxReconnectAttempts){this.log("Max reconnect attempts reached"),this.emit(C.ReconnectFailed,void 0);return}this.reconnectAttempts++,this.stats.reconnectCount++,this.log(`Reconnecting in ${this.options.reconnectInterval}ms (attempt ${this.reconnectAttempts}/${this.options.maxReconnectAttempts})`),this.emit(C.Reconnecting,{attempt:this.reconnectAttempts,maxAttempts:this.options.maxReconnectAttempts}),this.reconnectTimeoutId=setTimeout(()=>{this.reconnectTimeoutId=null,this.connect()},this.options.reconnectInterval)}}startHeartbeat(){!(this.options.heartbeatInterval<=0)&&null===this.heartbeatIntervalId&&(this.heartbeatIntervalId=setInterval(()=>{this.isConnected&&this.notify({method:this.options.heartbeatMethod}).catch(e=>{this.log("Heartbeat failed:",e)})},this.options.heartbeatInterval))}stopHeartbeat(){this.heartbeatIntervalId&&(clearInterval(this.heartbeatIntervalId),this.heartbeatIntervalId=null)}rejectAllPendingRequests(e,t){for(let[t,n]of this.pendingRequests)clearTimeout(n.timeoutId),n.reject(e);this.pendingRequests.clear()}updateResponseTime(e){this.responseTimes.push(e),this.responseTimes.length>100&&this.responseTimes.shift(),this.stats.averageResponseTime=this.responseTimes.reduce((e,t)=>e+t,0)/this.responseTimes.length}async request(e){if(!this.isConnected)throw Error("WebSocket is not connected");let t=e.id??u(),n={jsonrpc:"2.0",method:e.method,params:e.params,id:t};return new Promise((r,i)=>{let s=e.timeout??this.options.defaultTimeout,o=setTimeout(()=>{this.pendingRequests.delete(t),this.stats.timeouts++,i(Error(`Request timeout after ${s}ms`))},s);this.pendingRequests.set(t,{id:t,timestamp:Date.now(),timeoutId:o,resolve:r,reject:i});try{var l;let e=c(n);null===(l=this.ws)||void 0===l||l.send(e),this.stats.requestsSent++,this.log("Sent request:",n)}catch(e){clearTimeout(o),this.pendingRequests.delete(t),i(e)}})}async notify(e){var t;if(!this.isConnected)throw Error("WebSocket is not connected");let n={jsonrpc:"2.0",method:e.method,params:e.params},r=c(n);null===(t=this.ws)||void 0===t||t.send(r),this.log("Sent notification:",n)}stream(e,t){if(!this.isConnected)throw Error("WebSocket is not connected");let n=e.id??u(),r={jsonrpc:"2.0",method:e.method,params:e.params,id:n},i=!1;this.streamCallbacks.set(n,t);try{var s;let e=c(r);null===(s=this.ws)||void 0===s||s.send(e),this.stats.requestsSent++,this.log("Sent stream request:",r)}catch(e){throw this.streamCallbacks.delete(n),e}return{id:n,close:()=>{i||(i=!0,this.streamCallbacks.delete(n),this.log("Stream closed:",n))},get closed(){return i}}}sendRaw(e){var t;if(!this.isConnected)throw Error("WebSocket is not connected");null===(t=this.ws)||void 0===t||t.send(e),this.log("Sent raw data:",e.byteLength,"bytes")}close(e,t){this.options.autoReconnect=!1,this.reconnectTimeoutId&&(clearTimeout(this.reconnectTimeoutId),this.reconnectTimeoutId=null),this.stopHeartbeat(),this.ws&&(this.ws.close(e,t),this.ws=null),this.rejectAllPendingRequests(Error("Connection closed by client"),p.ConnectionClosed),this.removeAllListeners()}reconnectToUrl(e){this.close(),this.options.url=e,this.options.autoReconnect=!0,this.reconnectAttempts=0,this.connect()}log(...e){this.options.debug&&console.log("[JsonRpcWebSocket]",...e)}constructor(e){super(),I(this,"ws",null),I(this,"options",void 0),I(this,"pendingRequests",new Map),I(this,"streamCallbacks",new Map),I(this,"reconnectAttempts",0),I(this,"reconnectTimeoutId",null),I(this,"heartbeatIntervalId",null),I(this,"stats",{requestsSent:0,responsesReceived:0,timeouts:0,errors:0,averageResponseTime:0,pendingRequests:0,reconnectCount:0}),I(this,"responseTimes",[]),this.options={...T,...e},this.connect()}}export{x as JsonRpcWebSocketClient,f as decode,x as default,a as deserialize,c as encode,u as generateUUID,l as serialize};
|
|
1
|
+
function encodeUtf8(str) {
|
|
2
|
+
const length = str.length;
|
|
3
|
+
let ascii = true;
|
|
4
|
+
for(let i = 0; i < length; i++)if (str.charCodeAt(i) > 127) {
|
|
5
|
+
ascii = false;
|
|
6
|
+
break;
|
|
7
|
+
}
|
|
8
|
+
if (ascii) {
|
|
9
|
+
const bytes = new Uint8Array(length);
|
|
10
|
+
for(let i = 0; i < length; i++)bytes[i] = str.charCodeAt(i);
|
|
11
|
+
return bytes;
|
|
12
|
+
}
|
|
13
|
+
let bytes = new Uint8Array(2 * length);
|
|
14
|
+
let pos = 0;
|
|
15
|
+
for(let i = 0; i < length; i++){
|
|
16
|
+
let code = str.charCodeAt(i);
|
|
17
|
+
if (pos + 4 > bytes.length) {
|
|
18
|
+
const newBytes = new Uint8Array(Math.ceil(1.5 * bytes.length));
|
|
19
|
+
newBytes.set(bytes);
|
|
20
|
+
bytes = newBytes;
|
|
21
|
+
}
|
|
22
|
+
if (code < 0x80) bytes[pos++] = code;
|
|
23
|
+
else if (code < 0x800) {
|
|
24
|
+
bytes[pos++] = 0xc0 | code >>> 6;
|
|
25
|
+
bytes[pos++] = 0x80 | 0x3f & code;
|
|
26
|
+
} else if (code >= 0xd800 && code < 0xdc00) {
|
|
27
|
+
if (i + 1 >= length) throw new Error('UTF-8 encode: incomplete surrogate pair');
|
|
28
|
+
const code2 = str.charCodeAt(++i);
|
|
29
|
+
if (code2 < 0xdc00 || code2 > 0xdfff) throw new Error(`UTF-8 encode: second surrogate character 0x${code2.toString(16)} at index ${i} out of range`);
|
|
30
|
+
code = 0x10000 + ((0x3ff & code) << 10) + (0x3ff & code2);
|
|
31
|
+
bytes[pos++] = 0xf0 | code >>> 18;
|
|
32
|
+
bytes[pos++] = 0x80 | code >>> 12 & 0x3f;
|
|
33
|
+
bytes[pos++] = 0x80 | code >>> 6 & 0x3f;
|
|
34
|
+
bytes[pos++] = 0x80 | 0x3f & code;
|
|
35
|
+
} else {
|
|
36
|
+
bytes[pos++] = 0xe0 | code >>> 12;
|
|
37
|
+
bytes[pos++] = 0x80 | code >>> 6 & 0x3f;
|
|
38
|
+
bytes[pos++] = 0x80 | 0x3f & code;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return bytes.subarray(0, pos);
|
|
42
|
+
}
|
|
43
|
+
function decodeUtf8(bytes, start, length) {
|
|
44
|
+
const end = start + length;
|
|
45
|
+
let ascii = true;
|
|
46
|
+
for(let i = start; i < end; i++)if (bytes[i] > 127) {
|
|
47
|
+
ascii = false;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (ascii) return String.fromCharCode(...bytes.subarray(start, end));
|
|
51
|
+
let str = '';
|
|
52
|
+
let i = start;
|
|
53
|
+
while(i < end){
|
|
54
|
+
const byte1 = bytes[i++];
|
|
55
|
+
if (byte1 < 0x80) str += String.fromCharCode(byte1);
|
|
56
|
+
else if (byte1 < 0xe0) {
|
|
57
|
+
if (i >= end) throw new Error('UTF-8 decode: incomplete 2-byte sequence');
|
|
58
|
+
const byte2 = bytes[i++];
|
|
59
|
+
str += String.fromCharCode((0x1f & byte1) << 6 | 0x3f & byte2);
|
|
60
|
+
} else if (byte1 < 0xf0) {
|
|
61
|
+
if (i + 1 >= end) throw new Error('UTF-8 decode: incomplete 3-byte sequence');
|
|
62
|
+
const byte2 = bytes[i++];
|
|
63
|
+
const byte3 = bytes[i++];
|
|
64
|
+
str += String.fromCharCode((0x0f & byte1) << 12 | (0x3f & byte2) << 6 | 0x3f & byte3);
|
|
65
|
+
} else {
|
|
66
|
+
if (i + 2 >= end) throw new Error('UTF-8 decode: incomplete 4-byte sequence');
|
|
67
|
+
const byte2 = bytes[i++];
|
|
68
|
+
const byte3 = bytes[i++];
|
|
69
|
+
const byte4 = bytes[i++];
|
|
70
|
+
let code = (0x07 & byte1) << 18 | (0x3f & byte2) << 12 | (0x3f & byte3) << 6 | 0x3f & byte4;
|
|
71
|
+
if (code <= 0xffff) str += String.fromCharCode(code);
|
|
72
|
+
else if (code <= 0x10ffff) {
|
|
73
|
+
code -= 0x10000;
|
|
74
|
+
str += String.fromCharCode(0xd800 | code >>> 10);
|
|
75
|
+
str += String.fromCharCode(0xdc00 | 0x3ff & code);
|
|
76
|
+
} else throw new Error(`UTF-8 decode: code point 0x${code.toString(16)} exceeds UTF-16 reach`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return str;
|
|
80
|
+
}
|
|
81
|
+
const POW32 = 0x100000000;
|
|
82
|
+
function deserialize(array, options) {
|
|
83
|
+
let bytes;
|
|
84
|
+
if (array instanceof ArrayBuffer) bytes = new Uint8Array(array);
|
|
85
|
+
else if (array instanceof Uint8Array) bytes = array;
|
|
86
|
+
else if ('object' == typeof array && void 0 !== array.length) bytes = new Uint8Array(array);
|
|
87
|
+
else throw new Error('Invalid argument type: Expected a byte array (Array or Uint8Array) to deserialize.');
|
|
88
|
+
if (0 === bytes.length) throw new Error('Invalid argument: The byte array to deserialize is empty.');
|
|
89
|
+
let pos = 0;
|
|
90
|
+
if (null == options ? void 0 : options.multiple) {
|
|
91
|
+
const results = [];
|
|
92
|
+
while(pos < bytes.length)results.push(read());
|
|
93
|
+
return results;
|
|
94
|
+
}
|
|
95
|
+
return read();
|
|
96
|
+
function checkBounds(needed) {
|
|
97
|
+
if (pos + needed > bytes.length) throw new Error(`Buffer overflow: trying to read ${needed} bytes at position ${pos}, but only ${bytes.length - pos} bytes available`);
|
|
98
|
+
}
|
|
99
|
+
function read() {
|
|
100
|
+
checkBounds(1);
|
|
101
|
+
const byte = bytes[pos++];
|
|
102
|
+
if (byte >= 0x00 && byte <= 0x7f) return byte;
|
|
103
|
+
if (byte >= 0x80 && byte <= 0x8f) return readMap(byte - 0x80);
|
|
104
|
+
if (byte >= 0x90 && byte <= 0x9f) return readArray(byte - 0x90);
|
|
105
|
+
if (byte >= 0xa0 && byte <= 0xbf) return readStr(byte - 0xa0);
|
|
106
|
+
if (byte >= 0xe0 && byte <= 0xff) return byte - 256;
|
|
107
|
+
if (0xc0 === byte) return null;
|
|
108
|
+
if (0xc2 === byte) return false;
|
|
109
|
+
if (0xc3 === byte) return true;
|
|
110
|
+
if (0xc4 === byte) return readBin(-1, 1);
|
|
111
|
+
if (0xc5 === byte) return readBin(-1, 2);
|
|
112
|
+
if (0xc6 === byte) return readBin(-1, 4);
|
|
113
|
+
if (0xc7 === byte) return readExt(-1, 1);
|
|
114
|
+
if (0xc8 === byte) return readExt(-1, 2);
|
|
115
|
+
if (0xc9 === byte) return readExt(-1, 4);
|
|
116
|
+
if (0xd4 === byte) return readExt(1);
|
|
117
|
+
if (0xd5 === byte) return readExt(2);
|
|
118
|
+
if (0xd6 === byte) return readExt(4);
|
|
119
|
+
if (0xd7 === byte) return readExt(8);
|
|
120
|
+
if (0xd8 === byte) return readExt(16);
|
|
121
|
+
if (0xca === byte) return readFloat(4);
|
|
122
|
+
if (0xcb === byte) return readFloat(8);
|
|
123
|
+
if (0xcc === byte) return readUInt(1);
|
|
124
|
+
if (0xcd === byte) return readUInt(2);
|
|
125
|
+
if (0xce === byte) return readUInt(4);
|
|
126
|
+
if (0xcf === byte) return readUInt(8);
|
|
127
|
+
if (0xd0 === byte) return readInt(1);
|
|
128
|
+
if (0xd1 === byte) return readInt(2);
|
|
129
|
+
if (0xd2 === byte) return readInt(4);
|
|
130
|
+
if (0xd3 === byte) return readInt(8);
|
|
131
|
+
if (0xd9 === byte) return readStr(-1, 1);
|
|
132
|
+
if (0xda === byte) return readStr(-1, 2);
|
|
133
|
+
if (0xdb === byte) return readStr(-1, 4);
|
|
134
|
+
if (0xdc === byte) return readArray(-1, 2);
|
|
135
|
+
if (0xdd === byte) return readArray(-1, 4);
|
|
136
|
+
if (0xde === byte) return readMap(-1, 2);
|
|
137
|
+
if (0xdf === byte) return readMap(-1, 4);
|
|
138
|
+
if (0xc1 === byte) throw new Error('Invalid byte code 0xc1 found.');
|
|
139
|
+
throw new Error(`Invalid byte value '${byte}' at index ${pos - 1} in the MessagePack binary data (length ${bytes.length}): Expecting a range of 0 to 255. This is not a byte array.`);
|
|
140
|
+
}
|
|
141
|
+
function readInt(count) {
|
|
142
|
+
checkBounds(count);
|
|
143
|
+
let value = 0;
|
|
144
|
+
let first = true;
|
|
145
|
+
for(let i = 0; i < count; i++)if (first) {
|
|
146
|
+
const byte = bytes[pos++];
|
|
147
|
+
value += 0x7f & byte;
|
|
148
|
+
if (0x80 & byte) value -= 0x80;
|
|
149
|
+
first = false;
|
|
150
|
+
} else value = 256 * value + bytes[pos++];
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
153
|
+
function readUInt(count) {
|
|
154
|
+
checkBounds(count);
|
|
155
|
+
let value = 0;
|
|
156
|
+
for(let i = 0; i < count; i++)value = 256 * value + bytes[pos++];
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
159
|
+
function readFloat(size) {
|
|
160
|
+
checkBounds(size);
|
|
161
|
+
const view = new DataView(bytes.buffer, pos + bytes.byteOffset, size);
|
|
162
|
+
pos += size;
|
|
163
|
+
if (4 === size) return view.getFloat32(0, false);
|
|
164
|
+
if (8 === size) return view.getFloat64(0, false);
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
function readBin(length, lengthSize) {
|
|
168
|
+
const finalLength = length < 0 ? readUInt(lengthSize) : length;
|
|
169
|
+
checkBounds(finalLength);
|
|
170
|
+
const data = bytes.subarray(pos, pos + finalLength);
|
|
171
|
+
pos += finalLength;
|
|
172
|
+
return data;
|
|
173
|
+
}
|
|
174
|
+
function readMap(length, lengthSize) {
|
|
175
|
+
const finalLength = length < 0 && void 0 !== lengthSize ? readUInt(lengthSize) : length;
|
|
176
|
+
const data = {};
|
|
177
|
+
for(let i = 0; i < finalLength; i++){
|
|
178
|
+
const key = read();
|
|
179
|
+
if ('string' != typeof key) throw new Error(`Invalid map key type: expected string, got ${typeof key}`);
|
|
180
|
+
data[key] = read();
|
|
181
|
+
}
|
|
182
|
+
return data;
|
|
183
|
+
}
|
|
184
|
+
function readArray(length, lengthSize) {
|
|
185
|
+
const finalLength = length < 0 && void 0 !== lengthSize ? readUInt(lengthSize) : length;
|
|
186
|
+
const data = [];
|
|
187
|
+
for(let i = 0; i < finalLength; i++)data.push(read());
|
|
188
|
+
return data;
|
|
189
|
+
}
|
|
190
|
+
function readStr(length, lengthSize) {
|
|
191
|
+
const finalLength = length < 0 && void 0 !== lengthSize ? readUInt(lengthSize) : length;
|
|
192
|
+
checkBounds(finalLength);
|
|
193
|
+
const str = decodeUtf8(bytes, pos, finalLength);
|
|
194
|
+
pos += finalLength;
|
|
195
|
+
return str;
|
|
196
|
+
}
|
|
197
|
+
function readExt(length, lengthSize) {
|
|
198
|
+
const finalLength = length < 0 && void 0 !== lengthSize ? readUInt(lengthSize) : length;
|
|
199
|
+
checkBounds(1 + finalLength);
|
|
200
|
+
const type = readUInt(1);
|
|
201
|
+
const data = readBin(finalLength, 0);
|
|
202
|
+
if (255 === type) return readExtDate(data);
|
|
203
|
+
return {
|
|
204
|
+
type,
|
|
205
|
+
data
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function readExtDate(data) {
|
|
209
|
+
if (4 === data.length) {
|
|
210
|
+
const sec = (data[0] << 24 >>> 0) + (data[1] << 16 >>> 0) + (data[2] << 8 >>> 0) + data[3];
|
|
211
|
+
return new Date(1000 * sec);
|
|
212
|
+
}
|
|
213
|
+
if (8 === data.length) {
|
|
214
|
+
const ns = (data[0] << 22 >>> 0) + (data[1] << 14 >>> 0) + (data[2] << 6 >>> 0) + (data[3] >>> 2);
|
|
215
|
+
const sec = (0x3 & data[3]) * POW32 + (data[4] << 24 >>> 0) + (data[5] << 16 >>> 0) + (data[6] << 8 >>> 0) + data[7];
|
|
216
|
+
return new Date(1000 * sec + ns / 1000000);
|
|
217
|
+
}
|
|
218
|
+
if (12 === data.length) {
|
|
219
|
+
const ns = (data[0] << 24 >>> 0) + (data[1] << 16 >>> 0) + (data[2] << 8 >>> 0) + data[3];
|
|
220
|
+
pos -= 8;
|
|
221
|
+
const sec = readInt(8);
|
|
222
|
+
return new Date(1000 * sec + ns / 1000000);
|
|
223
|
+
}
|
|
224
|
+
throw new Error('Invalid data length for a date value.');
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const serializer_POW32 = 0x100000000;
|
|
228
|
+
const MAX_SAFE_INTEGER_HIGH = 0x1fffffffffffff;
|
|
229
|
+
function serialize(data, options) {
|
|
230
|
+
if ((null == options ? void 0 : options.multiple) && !Array.isArray(data)) throw new Error('Invalid argument type: Expected an Array to serialize multiple values.');
|
|
231
|
+
let floatBuffer;
|
|
232
|
+
let floatView;
|
|
233
|
+
let buffer = new Uint8Array(256);
|
|
234
|
+
let length = 0;
|
|
235
|
+
if ((null == options ? void 0 : options.multiple) && Array.isArray(data)) for (const item of data)append(item);
|
|
236
|
+
else append(data);
|
|
237
|
+
return buffer.subarray(0, length);
|
|
238
|
+
function append(value, isReplacement = false) {
|
|
239
|
+
const type = typeof value;
|
|
240
|
+
switch(type){
|
|
241
|
+
case 'undefined':
|
|
242
|
+
appendNull();
|
|
243
|
+
break;
|
|
244
|
+
case 'boolean':
|
|
245
|
+
appendBoolean(value);
|
|
246
|
+
break;
|
|
247
|
+
case 'number':
|
|
248
|
+
appendNumber(value);
|
|
249
|
+
break;
|
|
250
|
+
case 'string':
|
|
251
|
+
appendString(value);
|
|
252
|
+
break;
|
|
253
|
+
case 'object':
|
|
254
|
+
if (null === value) appendNull();
|
|
255
|
+
else if (value instanceof Date) appendDate(value);
|
|
256
|
+
else if (Array.isArray(value)) appendArray(value);
|
|
257
|
+
else if (value instanceof Uint8Array || value instanceof Uint8ClampedArray) appendBinArray(value);
|
|
258
|
+
else if (value instanceof Int8Array || value instanceof Int16Array || value instanceof Uint16Array || value instanceof Int32Array || value instanceof Uint32Array || value instanceof Float32Array || value instanceof Float64Array) appendArray(Array.from(value));
|
|
259
|
+
else appendObject(value);
|
|
260
|
+
break;
|
|
261
|
+
default:
|
|
262
|
+
if (!isReplacement && (null == options ? void 0 : options.invalidTypeReplacement)) {
|
|
263
|
+
const replacement = 'function' == typeof options.invalidTypeReplacement ? options.invalidTypeReplacement(value) : options.invalidTypeReplacement;
|
|
264
|
+
append(replacement, true);
|
|
265
|
+
} else throw new Error(`Invalid argument type: The type '${type}' cannot be serialized.`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function appendNull() {
|
|
269
|
+
appendByte(0xc0);
|
|
270
|
+
}
|
|
271
|
+
function appendBoolean(value) {
|
|
272
|
+
appendByte(value ? 0xc3 : 0xc2);
|
|
273
|
+
}
|
|
274
|
+
function appendNumber(value) {
|
|
275
|
+
if (Number.isFinite(value) && Math.floor(value) === value) {
|
|
276
|
+
if (value >= 0 && value <= 0x7f) appendByte(value);
|
|
277
|
+
else if (value < 0 && value >= -32) appendByte(value);
|
|
278
|
+
else if (value > 0 && value <= 0xff) appendBytes([
|
|
279
|
+
0xcc,
|
|
280
|
+
value
|
|
281
|
+
]);
|
|
282
|
+
else if (value >= -128 && value <= 0x7f) appendBytes([
|
|
283
|
+
0xd0,
|
|
284
|
+
value
|
|
285
|
+
]);
|
|
286
|
+
else if (value > 0 && value <= 0xffff) appendBytes([
|
|
287
|
+
0xcd,
|
|
288
|
+
value >>> 8,
|
|
289
|
+
value
|
|
290
|
+
]);
|
|
291
|
+
else if (value >= -32768 && value <= 0x7fff) appendBytes([
|
|
292
|
+
0xd1,
|
|
293
|
+
value >>> 8,
|
|
294
|
+
value
|
|
295
|
+
]);
|
|
296
|
+
else if (value > 0 && value <= 0xffffffff) appendBytes([
|
|
297
|
+
0xce,
|
|
298
|
+
value >>> 24,
|
|
299
|
+
value >>> 16,
|
|
300
|
+
value >>> 8,
|
|
301
|
+
value
|
|
302
|
+
]);
|
|
303
|
+
else if (value >= -2147483648 && value <= 0x7fffffff) appendBytes([
|
|
304
|
+
0xd2,
|
|
305
|
+
value >>> 24,
|
|
306
|
+
value >>> 16,
|
|
307
|
+
value >>> 8,
|
|
308
|
+
value
|
|
309
|
+
]);
|
|
310
|
+
else if (value > 0 && value <= MAX_SAFE_INTEGER_HIGH) {
|
|
311
|
+
const hi = Math.floor(value / serializer_POW32);
|
|
312
|
+
const lo = Math.floor(value % serializer_POW32);
|
|
313
|
+
appendBytes([
|
|
314
|
+
0xd3,
|
|
315
|
+
hi >>> 24,
|
|
316
|
+
hi >>> 16,
|
|
317
|
+
hi >>> 8,
|
|
318
|
+
hi,
|
|
319
|
+
lo >>> 24,
|
|
320
|
+
lo >>> 16,
|
|
321
|
+
lo >>> 8,
|
|
322
|
+
lo
|
|
323
|
+
]);
|
|
324
|
+
} else if (value >= -MAX_SAFE_INTEGER_HIGH && value <= -2147483649) {
|
|
325
|
+
appendByte(0xd3);
|
|
326
|
+
appendInt64(value);
|
|
327
|
+
} else value < 0 ? appendBytes([
|
|
328
|
+
0xd3,
|
|
329
|
+
0x80,
|
|
330
|
+
0,
|
|
331
|
+
0,
|
|
332
|
+
0,
|
|
333
|
+
0,
|
|
334
|
+
0,
|
|
335
|
+
0,
|
|
336
|
+
0
|
|
337
|
+
]) : appendBytes([
|
|
338
|
+
0xcf,
|
|
339
|
+
0xff,
|
|
340
|
+
0xff,
|
|
341
|
+
0xff,
|
|
342
|
+
0xff,
|
|
343
|
+
0xff,
|
|
344
|
+
0xff,
|
|
345
|
+
0xff,
|
|
346
|
+
0xff
|
|
347
|
+
]);
|
|
348
|
+
} else {
|
|
349
|
+
if (!floatView) {
|
|
350
|
+
floatBuffer = new ArrayBuffer(8);
|
|
351
|
+
floatView = new DataView(floatBuffer);
|
|
352
|
+
}
|
|
353
|
+
floatView.setFloat64(0, value);
|
|
354
|
+
appendByte(0xcb);
|
|
355
|
+
appendBytes(new Uint8Array(floatBuffer));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function appendString(value) {
|
|
359
|
+
const bytes = encodeUtf8(value);
|
|
360
|
+
const len = bytes.length;
|
|
361
|
+
if (len <= 0x1f) appendByte(0xa0 + len);
|
|
362
|
+
else if (len <= 0xff) appendBytes([
|
|
363
|
+
0xd9,
|
|
364
|
+
len
|
|
365
|
+
]);
|
|
366
|
+
else len <= 0xffff ? appendBytes([
|
|
367
|
+
0xda,
|
|
368
|
+
len >>> 8,
|
|
369
|
+
len
|
|
370
|
+
]) : appendBytes([
|
|
371
|
+
0xdb,
|
|
372
|
+
len >>> 24,
|
|
373
|
+
len >>> 16,
|
|
374
|
+
len >>> 8,
|
|
375
|
+
len
|
|
376
|
+
]);
|
|
377
|
+
appendBytes(bytes);
|
|
378
|
+
}
|
|
379
|
+
function appendArray(value) {
|
|
380
|
+
const len = value.length;
|
|
381
|
+
if (len <= 0xf) appendByte(0x90 + len);
|
|
382
|
+
else len <= 0xffff ? appendBytes([
|
|
383
|
+
0xdc,
|
|
384
|
+
len >>> 8,
|
|
385
|
+
len
|
|
386
|
+
]) : appendBytes([
|
|
387
|
+
0xdd,
|
|
388
|
+
len >>> 24,
|
|
389
|
+
len >>> 16,
|
|
390
|
+
len >>> 8,
|
|
391
|
+
len
|
|
392
|
+
]);
|
|
393
|
+
for (const item of value)append(item);
|
|
394
|
+
}
|
|
395
|
+
function appendBinArray(value) {
|
|
396
|
+
const len = value.length;
|
|
397
|
+
if (len <= 0xff) appendBytes([
|
|
398
|
+
0xc4,
|
|
399
|
+
len
|
|
400
|
+
]);
|
|
401
|
+
else len <= 0xffff ? appendBytes([
|
|
402
|
+
0xc5,
|
|
403
|
+
len >>> 8,
|
|
404
|
+
len
|
|
405
|
+
]) : appendBytes([
|
|
406
|
+
0xc6,
|
|
407
|
+
len >>> 24,
|
|
408
|
+
len >>> 16,
|
|
409
|
+
len >>> 8,
|
|
410
|
+
len
|
|
411
|
+
]);
|
|
412
|
+
appendBytes(value);
|
|
413
|
+
}
|
|
414
|
+
function appendObject(value) {
|
|
415
|
+
let count = 0;
|
|
416
|
+
for(const key in value)if (void 0 !== value[key]) count++;
|
|
417
|
+
if (count <= 0xf) appendByte(0x80 + count);
|
|
418
|
+
else count <= 0xffff ? appendBytes([
|
|
419
|
+
0xde,
|
|
420
|
+
count >>> 8,
|
|
421
|
+
count
|
|
422
|
+
]) : appendBytes([
|
|
423
|
+
0xdf,
|
|
424
|
+
count >>> 24,
|
|
425
|
+
count >>> 16,
|
|
426
|
+
count >>> 8,
|
|
427
|
+
count
|
|
428
|
+
]);
|
|
429
|
+
for(const key in value){
|
|
430
|
+
const val = value[key];
|
|
431
|
+
if (void 0 !== val) {
|
|
432
|
+
append(key);
|
|
433
|
+
append(val);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function appendDate(value) {
|
|
438
|
+
const sec = value.getTime() / 1000;
|
|
439
|
+
if (0 === value.getMilliseconds() && sec >= 0 && sec < serializer_POW32) {
|
|
440
|
+
const secInt = Math.floor(sec);
|
|
441
|
+
appendBytes([
|
|
442
|
+
0xd6,
|
|
443
|
+
0xff,
|
|
444
|
+
secInt >>> 24,
|
|
445
|
+
secInt >>> 16,
|
|
446
|
+
secInt >>> 8,
|
|
447
|
+
secInt
|
|
448
|
+
]);
|
|
449
|
+
} else if (sec >= 0 && sec < 4 * serializer_POW32) {
|
|
450
|
+
const ns = 1000000 * value.getMilliseconds();
|
|
451
|
+
const secInt = Math.floor(sec);
|
|
452
|
+
const secHigh = Math.floor(secInt / serializer_POW32);
|
|
453
|
+
appendBytes([
|
|
454
|
+
0xd7,
|
|
455
|
+
0xff,
|
|
456
|
+
ns >>> 22,
|
|
457
|
+
ns >>> 14,
|
|
458
|
+
ns >>> 6,
|
|
459
|
+
ns << 2 >>> 0 | secHigh,
|
|
460
|
+
secInt >>> 24,
|
|
461
|
+
secInt >>> 16,
|
|
462
|
+
secInt >>> 8,
|
|
463
|
+
secInt
|
|
464
|
+
]);
|
|
465
|
+
} else {
|
|
466
|
+
const ns = 1000000 * value.getMilliseconds();
|
|
467
|
+
appendBytes([
|
|
468
|
+
0xc7,
|
|
469
|
+
12,
|
|
470
|
+
0xff,
|
|
471
|
+
ns >>> 24,
|
|
472
|
+
ns >>> 16,
|
|
473
|
+
ns >>> 8,
|
|
474
|
+
ns
|
|
475
|
+
]);
|
|
476
|
+
appendInt64(sec);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
function appendByte(byte) {
|
|
480
|
+
if (buffer.length < length + 1) expandBuffer(length + 1);
|
|
481
|
+
buffer[length++] = byte;
|
|
482
|
+
}
|
|
483
|
+
function appendBytes(bytes) {
|
|
484
|
+
const needed = length + bytes.length;
|
|
485
|
+
if (buffer.length < needed) expandBuffer(needed);
|
|
486
|
+
buffer.set(bytes, length);
|
|
487
|
+
length += bytes.length;
|
|
488
|
+
}
|
|
489
|
+
function expandBuffer(minSize) {
|
|
490
|
+
let newSize = Math.ceil(1.5 * buffer.length);
|
|
491
|
+
while(newSize < minSize)newSize = Math.ceil(1.5 * newSize);
|
|
492
|
+
const newBuffer = new Uint8Array(newSize);
|
|
493
|
+
newBuffer.set(buffer);
|
|
494
|
+
buffer = newBuffer;
|
|
495
|
+
}
|
|
496
|
+
function appendInt64(num) {
|
|
497
|
+
let hi;
|
|
498
|
+
let lo;
|
|
499
|
+
if (num >= 0) {
|
|
500
|
+
hi = Math.floor(num / serializer_POW32);
|
|
501
|
+
lo = Math.floor(num % serializer_POW32);
|
|
502
|
+
} else {
|
|
503
|
+
const absValue = Math.abs(num + 1);
|
|
504
|
+
hi = ~Math.floor(absValue / serializer_POW32);
|
|
505
|
+
lo = ~Math.floor(absValue % serializer_POW32);
|
|
506
|
+
}
|
|
507
|
+
appendBytes([
|
|
508
|
+
hi >>> 24,
|
|
509
|
+
hi >>> 16,
|
|
510
|
+
hi >>> 8,
|
|
511
|
+
hi,
|
|
512
|
+
lo >>> 24,
|
|
513
|
+
lo >>> 16,
|
|
514
|
+
lo >>> 8,
|
|
515
|
+
lo
|
|
516
|
+
]);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
const pack_serialize = serialize;
|
|
520
|
+
const pack_deserialize = deserialize;
|
|
521
|
+
const encode = serialize;
|
|
522
|
+
const decode = deserialize;
|
|
523
|
+
const generateHexSegment = ()=>((1 + Math.random()) * 0x10000 | 0).toString(16).substring(1);
|
|
524
|
+
const generateUUID = ()=>[
|
|
525
|
+
generateHexSegment() + generateHexSegment(),
|
|
526
|
+
generateHexSegment(),
|
|
527
|
+
generateHexSegment(),
|
|
528
|
+
generateHexSegment(),
|
|
529
|
+
generateHexSegment() + generateHexSegment() + generateHexSegment()
|
|
530
|
+
].join('-');
|
|
531
|
+
var jsonrpc_JsonRpcErrorCode = /*#__PURE__*/ function(JsonRpcErrorCode) {
|
|
532
|
+
JsonRpcErrorCode[JsonRpcErrorCode["ParseError"] = -32700] = "ParseError";
|
|
533
|
+
JsonRpcErrorCode[JsonRpcErrorCode["InvalidRequest"] = -32600] = "InvalidRequest";
|
|
534
|
+
JsonRpcErrorCode[JsonRpcErrorCode["MethodNotFound"] = -32601] = "MethodNotFound";
|
|
535
|
+
JsonRpcErrorCode[JsonRpcErrorCode["InvalidParams"] = -32602] = "InvalidParams";
|
|
536
|
+
JsonRpcErrorCode[JsonRpcErrorCode["InternalError"] = -32603] = "InternalError";
|
|
537
|
+
JsonRpcErrorCode[JsonRpcErrorCode["ServerError"] = -32000] = "ServerError";
|
|
538
|
+
JsonRpcErrorCode[JsonRpcErrorCode["Timeout"] = -32001] = "Timeout";
|
|
539
|
+
JsonRpcErrorCode[JsonRpcErrorCode["ConnectionClosed"] = -32002] = "ConnectionClosed";
|
|
540
|
+
return JsonRpcErrorCode;
|
|
541
|
+
}({});
|
|
542
|
+
var socket_ConnectionState = /*#__PURE__*/ function(ConnectionState) {
|
|
543
|
+
ConnectionState[ConnectionState["Connecting"] = 0] = "Connecting";
|
|
544
|
+
ConnectionState[ConnectionState["Open"] = 1] = "Open";
|
|
545
|
+
ConnectionState[ConnectionState["Closing"] = 2] = "Closing";
|
|
546
|
+
ConnectionState[ConnectionState["Closed"] = 3] = "Closed";
|
|
547
|
+
return ConnectionState;
|
|
548
|
+
}({});
|
|
549
|
+
const SocketEvent = {
|
|
550
|
+
Open: 'open',
|
|
551
|
+
Close: 'close',
|
|
552
|
+
Error: 'error',
|
|
553
|
+
Message: 'message',
|
|
554
|
+
Reconnecting: 'reconnecting',
|
|
555
|
+
Reconnected: 'reconnected',
|
|
556
|
+
ReconnectFailed: 'reconnect_failed'
|
|
557
|
+
};
|
|
558
|
+
function _define_property(obj, key, value) {
|
|
559
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
560
|
+
value: value,
|
|
561
|
+
enumerable: true,
|
|
562
|
+
configurable: true,
|
|
563
|
+
writable: true
|
|
564
|
+
});
|
|
565
|
+
else obj[key] = value;
|
|
566
|
+
return obj;
|
|
567
|
+
}
|
|
568
|
+
class EventEmitter {
|
|
569
|
+
on(event, listener) {
|
|
570
|
+
var _this_listeners_get;
|
|
571
|
+
if (!this.listeners.has(event)) this.listeners.set(event, new Set());
|
|
572
|
+
null === (_this_listeners_get = this.listeners.get(event)) || void 0 === _this_listeners_get || _this_listeners_get.add(listener);
|
|
573
|
+
return ()=>this.off(event, listener);
|
|
574
|
+
}
|
|
575
|
+
once(event, listener) {
|
|
576
|
+
const wrapper = (data)=>{
|
|
577
|
+
this.off(event, wrapper);
|
|
578
|
+
listener(data);
|
|
579
|
+
};
|
|
580
|
+
return this.on(event, wrapper);
|
|
581
|
+
}
|
|
582
|
+
off(event, listener) {
|
|
583
|
+
const eventListeners = this.listeners.get(event);
|
|
584
|
+
if (eventListeners) {
|
|
585
|
+
eventListeners.delete(listener);
|
|
586
|
+
if (0 === eventListeners.size) this.listeners.delete(event);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
emit(event, data) {
|
|
590
|
+
const eventListeners = this.listeners.get(event);
|
|
591
|
+
if (eventListeners) for (const listener of eventListeners)try {
|
|
592
|
+
listener(data);
|
|
593
|
+
} catch (error) {
|
|
594
|
+
console.error(`Error in event listener for "${String(event)}":`, error);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
removeAllListeners(event) {
|
|
598
|
+
if (event) this.listeners.delete(event);
|
|
599
|
+
else this.listeners.clear();
|
|
600
|
+
}
|
|
601
|
+
listenerCount(event) {
|
|
602
|
+
var _this_listeners_get;
|
|
603
|
+
return (null === (_this_listeners_get = this.listeners.get(event)) || void 0 === _this_listeners_get ? void 0 : _this_listeners_get.size) ?? 0;
|
|
604
|
+
}
|
|
605
|
+
constructor(){
|
|
606
|
+
_define_property(this, "listeners", new Map());
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
function client_define_property(obj, key, value) {
|
|
610
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
611
|
+
value: value,
|
|
612
|
+
enumerable: true,
|
|
613
|
+
configurable: true,
|
|
614
|
+
writable: true
|
|
615
|
+
});
|
|
616
|
+
else obj[key] = value;
|
|
617
|
+
return obj;
|
|
618
|
+
}
|
|
619
|
+
const DEFAULT_OPTIONS = {
|
|
620
|
+
autoReconnect: true,
|
|
621
|
+
reconnectInterval: 3000,
|
|
622
|
+
maxReconnectAttempts: 5,
|
|
623
|
+
defaultTimeout: 15000,
|
|
624
|
+
heartbeatInterval: 0,
|
|
625
|
+
heartbeatMethod: 'ping',
|
|
626
|
+
debug: false
|
|
627
|
+
};
|
|
628
|
+
class JsonRpcWebSocketClient extends EventEmitter {
|
|
629
|
+
get state() {
|
|
630
|
+
var _this_ws;
|
|
631
|
+
return (null === (_this_ws = this.ws) || void 0 === _this_ws ? void 0 : _this_ws.readyState) ?? socket_ConnectionState.Closed;
|
|
632
|
+
}
|
|
633
|
+
get isConnected() {
|
|
634
|
+
return this.state === socket_ConnectionState.Open;
|
|
635
|
+
}
|
|
636
|
+
getStats() {
|
|
637
|
+
return {
|
|
638
|
+
...this.stats,
|
|
639
|
+
pendingRequests: this.pendingRequests.size
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
connect() {
|
|
643
|
+
if (this.ws && this.ws.readyState === socket_ConnectionState.Connecting) return;
|
|
644
|
+
try {
|
|
645
|
+
this.ws = new WebSocket(this.options.url, this.options.protocols);
|
|
646
|
+
this.ws.binaryType = 'arraybuffer';
|
|
647
|
+
this.ws.onopen = this.handleOpen.bind(this);
|
|
648
|
+
this.ws.onmessage = this.handleMessage.bind(this);
|
|
649
|
+
this.ws.onclose = this.handleClose.bind(this);
|
|
650
|
+
this.ws.onerror = this.handleError.bind(this);
|
|
651
|
+
} catch (error) {
|
|
652
|
+
this.log('Connection error:', error);
|
|
653
|
+
this.scheduleReconnect();
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
handleOpen(event) {
|
|
657
|
+
this.log('Connection opened');
|
|
658
|
+
this.reconnectAttempts = 0;
|
|
659
|
+
this.startHeartbeat();
|
|
660
|
+
this.emit(SocketEvent.Open, event);
|
|
661
|
+
}
|
|
662
|
+
handleMessage(event) {
|
|
663
|
+
try {
|
|
664
|
+
const rawData = event.data;
|
|
665
|
+
const response = decode(new Uint8Array(rawData));
|
|
666
|
+
this.log('Received:', response);
|
|
667
|
+
this.stats.responsesReceived++;
|
|
668
|
+
if ('error' in response) this.stats.errors++;
|
|
669
|
+
if (null !== response.id) {
|
|
670
|
+
const streamCallback = this.streamCallbacks.get(response.id);
|
|
671
|
+
if (streamCallback) {
|
|
672
|
+
streamCallback(response);
|
|
673
|
+
this.emit(SocketEvent.Message, {
|
|
674
|
+
data: response,
|
|
675
|
+
rawData
|
|
676
|
+
});
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
const metadata = this.pendingRequests.get(response.id);
|
|
680
|
+
if (metadata) {
|
|
681
|
+
clearTimeout(metadata.timeoutId);
|
|
682
|
+
this.pendingRequests.delete(response.id);
|
|
683
|
+
const responseTime = Date.now() - metadata.timestamp;
|
|
684
|
+
this.updateResponseTime(responseTime);
|
|
685
|
+
if ('error' in response) metadata.reject(new Error(`${response.error.message} (${response.error.code})`));
|
|
686
|
+
else metadata.resolve(response.result);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
this.emit(SocketEvent.Message, {
|
|
690
|
+
data: response,
|
|
691
|
+
rawData
|
|
692
|
+
});
|
|
693
|
+
} catch (error) {
|
|
694
|
+
this.log('Failed to decode message:', error);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
handleClose(event) {
|
|
698
|
+
this.log('Connection closed:', event.code, event.reason);
|
|
699
|
+
this.stopHeartbeat();
|
|
700
|
+
this.emit(SocketEvent.Close, event);
|
|
701
|
+
this.rejectAllPendingRequests(new Error('Connection closed'), jsonrpc_JsonRpcErrorCode.ConnectionClosed);
|
|
702
|
+
if (this.options.autoReconnect) this.scheduleReconnect();
|
|
703
|
+
}
|
|
704
|
+
handleError(event) {
|
|
705
|
+
this.log('Connection error:', event);
|
|
706
|
+
this.emit(SocketEvent.Error, event);
|
|
707
|
+
}
|
|
708
|
+
scheduleReconnect() {
|
|
709
|
+
if (this.reconnectTimeoutId) return;
|
|
710
|
+
if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
|
|
711
|
+
this.log('Max reconnect attempts reached');
|
|
712
|
+
this.emit(SocketEvent.ReconnectFailed, void 0);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
this.reconnectAttempts++;
|
|
716
|
+
this.stats.reconnectCount++;
|
|
717
|
+
this.log(`Reconnecting in ${this.options.reconnectInterval}ms (attempt ${this.reconnectAttempts}/${this.options.maxReconnectAttempts})`);
|
|
718
|
+
this.emit(SocketEvent.Reconnecting, {
|
|
719
|
+
attempt: this.reconnectAttempts,
|
|
720
|
+
maxAttempts: this.options.maxReconnectAttempts
|
|
721
|
+
});
|
|
722
|
+
this.reconnectTimeoutId = setTimeout(()=>{
|
|
723
|
+
this.reconnectTimeoutId = null;
|
|
724
|
+
this.connect();
|
|
725
|
+
}, this.options.reconnectInterval);
|
|
726
|
+
}
|
|
727
|
+
startHeartbeat() {
|
|
728
|
+
if (this.options.heartbeatInterval <= 0 || null !== this.heartbeatIntervalId) return;
|
|
729
|
+
this.heartbeatIntervalId = setInterval(()=>{
|
|
730
|
+
if (this.isConnected) this.notify({
|
|
731
|
+
method: this.options.heartbeatMethod
|
|
732
|
+
}).catch((error)=>{
|
|
733
|
+
this.log('Heartbeat failed:', error);
|
|
734
|
+
});
|
|
735
|
+
}, this.options.heartbeatInterval);
|
|
736
|
+
}
|
|
737
|
+
stopHeartbeat() {
|
|
738
|
+
if (this.heartbeatIntervalId) {
|
|
739
|
+
clearInterval(this.heartbeatIntervalId);
|
|
740
|
+
this.heartbeatIntervalId = null;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
rejectAllPendingRequests(error, code) {
|
|
744
|
+
for (const [id, metadata] of this.pendingRequests){
|
|
745
|
+
clearTimeout(metadata.timeoutId);
|
|
746
|
+
metadata.reject(error);
|
|
747
|
+
}
|
|
748
|
+
this.pendingRequests.clear();
|
|
749
|
+
}
|
|
750
|
+
updateResponseTime(time) {
|
|
751
|
+
this.responseTimes.push(time);
|
|
752
|
+
if (this.responseTimes.length > 100) this.responseTimes.shift();
|
|
753
|
+
this.stats.averageResponseTime = this.responseTimes.reduce((sum, t)=>sum + t, 0) / this.responseTimes.length;
|
|
754
|
+
}
|
|
755
|
+
async request(options) {
|
|
756
|
+
if (!this.isConnected) throw new Error('WebSocket is not connected');
|
|
757
|
+
const id = options.id ?? generateUUID();
|
|
758
|
+
const request = {
|
|
759
|
+
jsonrpc: '2.0',
|
|
760
|
+
method: options.method,
|
|
761
|
+
params: options.params,
|
|
762
|
+
id
|
|
763
|
+
};
|
|
764
|
+
return new Promise((resolve, reject)=>{
|
|
765
|
+
const timeout = options.timeout ?? this.options.defaultTimeout;
|
|
766
|
+
const timeoutId = setTimeout(()=>{
|
|
767
|
+
this.pendingRequests.delete(id);
|
|
768
|
+
this.stats.timeouts++;
|
|
769
|
+
reject(new Error(`Request timeout after ${timeout}ms`));
|
|
770
|
+
}, timeout);
|
|
771
|
+
this.pendingRequests.set(id, {
|
|
772
|
+
id,
|
|
773
|
+
timestamp: Date.now(),
|
|
774
|
+
timeoutId,
|
|
775
|
+
resolve: resolve,
|
|
776
|
+
reject
|
|
777
|
+
});
|
|
778
|
+
try {
|
|
779
|
+
var _this_ws;
|
|
780
|
+
const encoded = encode(request);
|
|
781
|
+
null === (_this_ws = this.ws) || void 0 === _this_ws || _this_ws.send(encoded);
|
|
782
|
+
this.stats.requestsSent++;
|
|
783
|
+
this.log('Sent request:', request);
|
|
784
|
+
} catch (error) {
|
|
785
|
+
clearTimeout(timeoutId);
|
|
786
|
+
this.pendingRequests.delete(id);
|
|
787
|
+
reject(error);
|
|
788
|
+
}
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
async notify(options) {
|
|
792
|
+
var _this_ws;
|
|
793
|
+
if (!this.isConnected) throw new Error('WebSocket is not connected');
|
|
794
|
+
const notification = {
|
|
795
|
+
jsonrpc: '2.0',
|
|
796
|
+
method: options.method,
|
|
797
|
+
params: options.params
|
|
798
|
+
};
|
|
799
|
+
const encoded = encode(notification);
|
|
800
|
+
null === (_this_ws = this.ws) || void 0 === _this_ws || _this_ws.send(encoded);
|
|
801
|
+
this.log('Sent notification:', notification);
|
|
802
|
+
}
|
|
803
|
+
stream(options, callback) {
|
|
804
|
+
if (!this.isConnected) throw new Error('WebSocket is not connected');
|
|
805
|
+
const id = options.id ?? generateUUID();
|
|
806
|
+
const request = {
|
|
807
|
+
jsonrpc: '2.0',
|
|
808
|
+
method: options.method,
|
|
809
|
+
params: options.params,
|
|
810
|
+
id
|
|
811
|
+
};
|
|
812
|
+
let closed = false;
|
|
813
|
+
this.streamCallbacks.set(id, callback);
|
|
814
|
+
try {
|
|
815
|
+
var _this_ws;
|
|
816
|
+
const encoded = encode(request);
|
|
817
|
+
null === (_this_ws = this.ws) || void 0 === _this_ws || _this_ws.send(encoded);
|
|
818
|
+
this.stats.requestsSent++;
|
|
819
|
+
this.log('Sent stream request:', request);
|
|
820
|
+
} catch (error) {
|
|
821
|
+
this.streamCallbacks.delete(id);
|
|
822
|
+
throw error;
|
|
823
|
+
}
|
|
824
|
+
return {
|
|
825
|
+
id,
|
|
826
|
+
close: ()=>{
|
|
827
|
+
if (!closed) {
|
|
828
|
+
closed = true;
|
|
829
|
+
this.streamCallbacks.delete(id);
|
|
830
|
+
this.log('Stream closed:', id);
|
|
831
|
+
}
|
|
832
|
+
},
|
|
833
|
+
get closed () {
|
|
834
|
+
return closed;
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
sendRaw(data) {
|
|
839
|
+
var _this_ws;
|
|
840
|
+
if (!this.isConnected) throw new Error('WebSocket is not connected');
|
|
841
|
+
null === (_this_ws = this.ws) || void 0 === _this_ws || _this_ws.send(data);
|
|
842
|
+
this.log('Sent raw data:', data.byteLength, 'bytes');
|
|
843
|
+
}
|
|
844
|
+
close(code, reason) {
|
|
845
|
+
this.options.autoReconnect = false;
|
|
846
|
+
if (this.reconnectTimeoutId) {
|
|
847
|
+
clearTimeout(this.reconnectTimeoutId);
|
|
848
|
+
this.reconnectTimeoutId = null;
|
|
849
|
+
}
|
|
850
|
+
this.stopHeartbeat();
|
|
851
|
+
if (this.ws) {
|
|
852
|
+
this.ws.close(code, reason);
|
|
853
|
+
this.ws = null;
|
|
854
|
+
}
|
|
855
|
+
this.rejectAllPendingRequests(new Error('Connection closed by client'), jsonrpc_JsonRpcErrorCode.ConnectionClosed);
|
|
856
|
+
this.removeAllListeners();
|
|
857
|
+
}
|
|
858
|
+
reconnectToUrl(url) {
|
|
859
|
+
this.close();
|
|
860
|
+
this.options.url = url;
|
|
861
|
+
this.options.autoReconnect = true;
|
|
862
|
+
this.reconnectAttempts = 0;
|
|
863
|
+
this.connect();
|
|
864
|
+
}
|
|
865
|
+
log(...args) {
|
|
866
|
+
if (this.options.debug) console.log('[JsonRpcWebSocket]', ...args);
|
|
867
|
+
}
|
|
868
|
+
constructor(options){
|
|
869
|
+
super(), client_define_property(this, "ws", null), client_define_property(this, "options", void 0), client_define_property(this, "pendingRequests", new Map()), client_define_property(this, "streamCallbacks", new Map()), client_define_property(this, "reconnectAttempts", 0), client_define_property(this, "reconnectTimeoutId", null), client_define_property(this, "heartbeatIntervalId", null), client_define_property(this, "stats", {
|
|
870
|
+
requestsSent: 0,
|
|
871
|
+
responsesReceived: 0,
|
|
872
|
+
timeouts: 0,
|
|
873
|
+
errors: 0,
|
|
874
|
+
averageResponseTime: 0,
|
|
875
|
+
pendingRequests: 0,
|
|
876
|
+
reconnectCount: 0
|
|
877
|
+
}), client_define_property(this, "responseTimes", []);
|
|
878
|
+
this.options = {
|
|
879
|
+
...DEFAULT_OPTIONS,
|
|
880
|
+
...options
|
|
881
|
+
};
|
|
882
|
+
this.connect();
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
export { JsonRpcWebSocketClient, decode, JsonRpcWebSocketClient as default, pack_deserialize as deserialize, encode, generateUUID, pack_serialize as serialize };
|