@rfkit/json-rpc-websocket 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # [json-rpc-websocket](https://github.com/Hxgh/json-rpc-websocket)
2
+
3
+ 基于WebSocket+JSONRPC+msgpack+TypeScript封装的实时通讯函数
4
+ - [msgpack-lite](https://github.com/kawanet/msgpack-lite/)
5
+ - [JSON-RPC 2.0](http://wiki.geekdream.com/Specification/json-rpc_2.0.html)
6
+
7
+ ### 安装
8
+
9
+ ```sh
10
+ pnpm add json-rpc-websocket
11
+ ```
12
+ ### 使用
13
+ ```
14
+ import Socket, { SocketType } from 'json-rpc-websocket';
15
+
16
+ const socket: SocketType = new Socket({ url: 'ws://url' });
17
+
18
+ // 普通模式
19
+ socket.send({
20
+ method: 'msg',
21
+ callback: e => {
22
+ console.log(e);
23
+ },
24
+ });
25
+
26
+ // 流模式
27
+ const stream = socket.stream({
28
+ method: 'start',
29
+ callback: e => {
30
+ console.log(e);
31
+ },
32
+ onerror: e => {
33
+ console.log('处理超时 || 处理send无法启动');
34
+ },
35
+ });
36
+ stream.close();
37
+
38
+ // 接收所有消息
39
+ const socket = new Socket({
40
+ url: 'ws://url',
41
+ onmessage: (res: Object) => console.log(res),
42
+ });
43
+
44
+ ```
package/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import Socket from './socket';
2
+ import type { SocketType } from './type';
3
+ export default Socket;
4
+ export type { SocketType };
package/index.js ADDED
@@ -0,0 +1 @@
1
+ var __webpack_modules__={"./src/msgpack/index.js":function(module,__unused_webpack_exports,__webpack_require__){module=__webpack_require__.nmd(module);(function(){"use strict";function serialize(data,options){if(options&&options.multiple&&!Array.isArray(data))throw new Error("Invalid argument type: Expected an Array to serialize multiple values.");const pow32=0x100000000;let floatBuffer,floatView;let array=new Uint8Array(128);let length=0;if(options&&options.multiple)for(let i=0;i<data.length;i++)append(data[i]);else append(data);return array.subarray(0,length);function append(data,isReplacement){switch(typeof data){case"undefined":appendNull(data);break;case"boolean":appendBoolean(data);break;case"number":appendNumber(data);break;case"string":appendString(data);break;case"object":if(null===data)appendNull(data);else if(data instanceof Date)appendDate(data);else if(Array.isArray(data))appendArray(data);else if(data instanceof Uint8Array||data instanceof Uint8ClampedArray)appendBinArray(data);else if(data instanceof Int8Array||data instanceof Int16Array||data instanceof Uint16Array||data instanceof Int32Array||data instanceof Uint32Array||data instanceof Float32Array||data instanceof Float64Array)appendArray(data);else appendObject(data);break;default:if(!isReplacement&&options&&options.invalidTypeReplacement)"function"==typeof options.invalidTypeReplacement?append(options.invalidTypeReplacement(data),true):append(options.invalidTypeReplacement,true);else throw new Error("Invalid argument type: The type '"+typeof data+"' cannot be serialized.")}}function appendNull(data){appendByte(192)}function appendBoolean(data){appendByte(data?195:194)}function appendNumber(data){if(isFinite(data)&&Math.floor(data)===data){if(data>=0&&data<=127)appendByte(data);else if(data<0&&data>=-32)appendByte(data);else if(data>0&&data<=255)appendBytes([204,data]);else if(data>=-128&&data<=127)appendBytes([208,data]);else if(data>0&&data<=65535)appendBytes([205,data>>>8,data]);else if(data>=-32768&&data<=32767)appendBytes([209,data>>>8,data]);else if(data>0&&data<=0xffffffff)appendBytes([206,data>>>24,data>>>16,data>>>8,data]);else if(data>=-0x80000000&&data<=0x7fffffff)appendBytes([210,data>>>24,data>>>16,data>>>8,data]);else if(data>0&&data<=0xffffffffffffffff){let hi=data/pow32;let lo=data%pow32;appendBytes([211,hi>>>24,hi>>>16,hi>>>8,hi,lo>>>24,lo>>>16,lo>>>8,lo])}else if(data>=-0x8000000000000000&&data<=0x8000000000000000){appendByte(211);appendInt64(data)}else data<0?appendBytes([211,128,0,0,0,0,0,0,0]):appendBytes([207,255,255,255,255,255,255,255,255])}else{if(!floatView){floatBuffer=new ArrayBuffer(8);floatView=new DataView(floatBuffer)}floatView.setFloat64(0,data);appendByte(203);appendBytes(new Uint8Array(floatBuffer))}}function appendString(data){let bytes=encodeUtf8(data);let length=bytes.length;if(length<=31)appendByte(160+length);else if(length<=255)appendBytes([217,length]);else length<=65535?appendBytes([218,length>>>8,length]):appendBytes([219,length>>>24,length>>>16,length>>>8,length]);appendBytes(bytes)}function appendArray(data){let length=data.length;if(length<=15)appendByte(144+length);else length<=65535?appendBytes([220,length>>>8,length]):appendBytes([221,length>>>24,length>>>16,length>>>8,length]);for(let index=0;index<length;index++)append(data[index])}function appendBinArray(data){let length=data.length;if(length<=15)appendBytes([196,length]);else length<=65535?appendBytes([197,length>>>8,length]):appendBytes([198,length>>>24,length>>>16,length>>>8,length]);appendBytes(data)}function appendObject(data){let length=0;for(let key in data)if(void 0!==data[key])length++;if(length<=15)appendByte(128+length);else length<=65535?appendBytes([222,length>>>8,length]):appendBytes([223,length>>>24,length>>>16,length>>>8,length]);for(let key in data){let value=data[key];if(void 0!==value){append(key);append(value)}}}function appendDate(data){let sec=data.getTime()/1e3;if(0===data.getMilliseconds()&&sec>=0&&sec<0x100000000)appendBytes([214,255,sec>>>24,sec>>>16,sec>>>8,sec]);else if(sec>=0&&sec<0x400000000){let ns=1e6*data.getMilliseconds();appendBytes([215,255,ns>>>22,ns>>>14,ns>>>6,ns<<2>>>0|sec/pow32,sec>>>24,sec>>>16,sec>>>8,sec])}else{let ns=1e6*data.getMilliseconds();appendBytes([199,12,255,ns>>>24,ns>>>16,ns>>>8,ns]);appendInt64(sec)}}function appendByte(byte){if(array.length<length+1){let newLength=2*array.length;while(newLength<length+1)newLength*=2;let newArray=new Uint8Array(newLength);newArray.set(array);array=newArray}array[length]=byte;length++}function appendBytes(bytes){if(array.length<length+bytes.length){let newLength=2*array.length;while(newLength<length+bytes.length)newLength*=2;let newArray=new Uint8Array(newLength);newArray.set(array);array=newArray}array.set(bytes,length);length+=bytes.length}function appendInt64(value){let hi,lo;if(value>=0){hi=value/pow32;lo=value%pow32}else{value++;hi=Math.abs(value)/pow32;lo=Math.abs(value)%pow32;hi=~hi;lo=~lo}appendBytes([hi>>>24,hi>>>16,hi>>>8,hi,lo>>>24,lo>>>16,lo>>>8,lo])}}function deserialize(array,options){const pow32=0x100000000;let pos=0;if(array instanceof ArrayBuffer)array=new Uint8Array(array);if("object"!=typeof array||void 0===array.length)throw new Error("Invalid argument type: Expected a byte array (Array or Uint8Array) to deserialize.");if(!array.length)throw new Error("Invalid argument: The byte array to deserialize is empty.");if(!(array instanceof Uint8Array))array=new Uint8Array(array);let data;if(options&&options.multiple){data=[];while(pos<array.length)data.push(read())}else data=read();return data;function read(){const byte=array[pos++];if(byte>=0&&byte<=127)return byte;if(byte>=128&&byte<=143)return readMap(byte-128);if(byte>=144&&byte<=159)return readArray(byte-144);if(byte>=160&&byte<=191)return readStr(byte-160);if(192===byte)return null;if(193===byte)throw new Error("Invalid byte code 0xc1 found.");if(194===byte)return false;if(195===byte)return true;if(196===byte)return readBin(-1,1);if(197===byte)return readBin(-1,2);if(198===byte)return readBin(-1,4);if(199===byte)return readExt(-1,1);if(200===byte)return readExt(-1,2);if(201===byte)return readExt(-1,4);if(202===byte)return readFloat(4);if(203===byte)return readFloat(8);if(204===byte)return readUInt(1);if(205===byte)return readUInt(2);if(206===byte)return readUInt(4);if(207===byte)return readUInt(8);if(208===byte)return readInt(1);if(209===byte)return readInt(2);if(210===byte)return readInt(4);if(211===byte)return readInt(8);if(212===byte)return readExt(1);if(213===byte)return readExt(2);if(214===byte)return readExt(4);if(215===byte)return readExt(8);if(216===byte)return readExt(16);if(217===byte)return readStr(-1,1);if(218===byte)return readStr(-1,2);if(219===byte)return readStr(-1,4);if(220===byte)return readArray(-1,2);if(221===byte)return readArray(-1,4);if(222===byte)return readMap(-1,2);if(223===byte)return readMap(-1,4);if(byte>=224&&byte<=255)return byte-256;console.debug("msgpack array:",array);throw new Error("Invalid byte value '"+byte+"' at index "+(pos-1)+" in the MessagePack binary data (length "+array.length+"): Expecting a range of 0 to 255. This is not a byte array.")}function readInt(size){let value=0;let first=true;while(size-- >0)if(first){let byte=array[pos++];value+=127&byte;if(128&byte)value-=128;first=false}else{value*=256;value+=array[pos++]}return value}function readUInt(size){let value=0;while(size-- >0){value*=256;value+=array[pos++]}return value}function readFloat(size){let view=new DataView(array.buffer,pos+array.byteOffset,size);pos+=size;if(4===size)return view.getFloat32(0,false);if(8===size)return view.getFloat64(0,false)}function readBin(size,lengthSize){if(size<0)size=readUInt(lengthSize);let data=array.subarray(pos,pos+size);pos+=size;return data}function readMap(size,lengthSize){if(size<0)size=readUInt(lengthSize);let data={};while(size-- >0){let key=read();data[key]=read()}return data}function readArray(size,lengthSize){if(size<0)size=readUInt(lengthSize);let data=[];while(size-- >0)data.push(read());return data}function readStr(size,lengthSize){if(size<0)size=readUInt(lengthSize);let start=pos;pos+=size;return decodeUtf8(array,start,size)}function readExt(size,lengthSize){if(size<0)size=readUInt(lengthSize);let type=readUInt(1);let data=readBin(size);switch(type){case 255:return readExtDate(data)}return{type:type,data:data}}function readExtDate(data){if(4===data.length){let sec=(data[0]<<24>>>0)+(data[1]<<16>>>0)+(data[2]<<8>>>0)+data[3];return new Date(1e3*sec)}if(8===data.length){let ns=(data[0]<<22>>>0)+(data[1]<<14>>>0)+(data[2]<<6>>>0)+(data[3]>>>2);let sec=(3&data[3])*pow32+(data[4]<<24>>>0)+(data[5]<<16>>>0)+(data[6]<<8>>>0)+data[7];return new Date(1e3*sec+ns/1e6)}if(12===data.length){let ns=(data[0]<<24>>>0)+(data[1]<<16>>>0)+(data[2]<<8>>>0)+data[3];pos-=8;let sec=readInt(8);return new Date(1e3*sec+ns/1e6)}throw new Error("Invalid data length for a date value.")}}function encodeUtf8(str){let ascii=true,length=str.length;for(let x=0;x<length;x++)if(str.charCodeAt(x)>127){ascii=false;break}let i=0,bytes=new Uint8Array(str.length*(ascii?1:4));for(let ci=0;ci!==length;ci++){let c=str.charCodeAt(ci);if(c<128){bytes[i++]=c;continue}if(c<2048)bytes[i++]=c>>6|192;else{if(c>55295&&c<56320){if(++ci>=length)throw new Error("UTF-8 encode: incomplete surrogate pair");let c2=str.charCodeAt(ci);if(c2<56320||c2>57343)throw new Error("UTF-8 encode: second surrogate character 0x"+c2.toString(16)+" at index "+ci+" out of range");c=65536+((1023&c)<<10)+(1023&c2);bytes[i++]=c>>18|240;bytes[i++]=c>>12&63|128}else bytes[i++]=c>>12|224;bytes[i++]=c>>6&63|128}bytes[i++]=63&c|128}return ascii?bytes:bytes.subarray(0,i)}function decodeUtf8(bytes,start,length){let i=start,str="";length+=start;while(i<length){let c=bytes[i++];if(c>127){if(c>191&&c<224){if(i>=length)throw new Error("UTF-8 decode: incomplete 2-byte sequence");c=(31&c)<<6|63&bytes[i++]}else if(c>223&&c<240){if(i+1>=length)throw new Error("UTF-8 decode: incomplete 3-byte sequence");c=(15&c)<<12|(63&bytes[i++])<<6|63&bytes[i++]}else if(c>239&&c<248){if(i+2>=length)throw new Error("UTF-8 decode: incomplete 4-byte sequence");c=(7&c)<<18|(63&bytes[i++])<<12|(63&bytes[i++])<<6|63&bytes[i++]}else throw new Error("UTF-8 decode: unknown multibyte start 0x"+c.toString(16)+" at index "+(i-1))}if(c<=65535)str+=String.fromCharCode(c);else if(c<=1114111){c-=65536;str+=String.fromCharCode(c>>10|55296);str+=String.fromCharCode(1023&c|56320)}else throw new Error("UTF-8 decode: code point 0x"+c.toString(16)+" exceeds UTF-16 reach")}return str}let msgpack={serialize:serialize,deserialize:deserialize,encode:serialize,decode:deserialize};if(module&&"object"==typeof module.exports)module.exports=msgpack;else window[window.msgpackJsName||"msgpack"]=msgpack})()}};var __webpack_module_cache__={};function __webpack_require__(moduleId){var cachedModule=__webpack_module_cache__[moduleId];if(void 0!==cachedModule)return cachedModule.exports;var module=__webpack_module_cache__[moduleId]={id:moduleId,loaded:false,exports:{}};__webpack_modules__[moduleId](module,module.exports,__webpack_require__);module.loaded=true;return module.exports}(()=>{__webpack_require__.nmd=function(module){module.paths=[];if(!module.children)module.children=[];return module}})();var msgpack=__webpack_require__("./src/msgpack/index.js");const generateHexSegment=()=>((1+Math.random())*65536|0).toString(16).substring(1);const generateUUID=()=>[generateHexSegment()+generateHexSegment(),generateHexSegment(),generateHexSegment(),generateHexSegment(),generateHexSegment()+generateHexSegment()+generateHexSegment()].join("-");const generateId=(length=8)=>{let result="";const characters="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";const charactersLength=characters.length;for(let i=0;i<length;i++)result+=characters.charAt(Math.floor(Math.random()*charactersLength));return result};const defaultProps={onopen:()=>{},onmessage:()=>{},onclose:()=>{},onerror:()=>{}};class Socket{props;guidStorage=[];callbackStorage={};ws;streamID="";constructor(props){this.props={jsonrpc:"2.0",...defaultProps,...props};this.ws=this.setupWS()}setupWS(){const ws=new WebSocket(this.props.url,this.props.protocols);ws.binaryType="arraybuffer";ws.onopen=e=>this.props.onopen(e);ws.onmessage=e=>this.onmessage(e);ws.onclose=e=>this.props.onclose(e);ws.onerror=e=>this.props.onerror(e);return ws}saveGUID(guid){this.guidStorage.push(guid);return guid}deleteGUID(guid){const arr=this.guidStorage;const index=arr.indexOf(guid);if(-1!==index){arr.splice(index,1);return true}return false}touchTimeout(id,time=15e3,onerror=()=>{}){setTimeout(()=>{if(this.guidStorage.includes(id)){onerror({code:408,message:"发送数据链接超时"});this.deleteGUID(id)}},time)}saveResponse(callback,id){this.callbackStorage[id]=callback}finishResponse(res,id){const callback=this.callbackStorage[id];if(void 0!==this.callbackStorage[id]&&callback){callback(res);if(id!==this.streamID)delete this.callbackStorage[id]}return id}onmessage(e){const response=(0,msgpack.decode)(Array.prototype.slice.call(new Uint8Array(e.data)));if(!response)return;const{id}=response;if(id&&this.deleteGUID(id))this.finishResponse(response,id);this.props.onmessage(response)}send=data=>{const{id:paramId,method,isInform,callback,onerror,params,timeout}=data;if(1!==this.ws.readyState){if(onerror)onerror({code:3,message:"连接已关闭或者没有链接成功"});return}if(void 0===method)return;let guid={};const id=this.saveGUID(paramId||generateUUID());if(!isInform){guid={id};if(callback)this.saveResponse(callback,id)}this.touchTimeout(id,timeout,onerror);this.ws.send((0,msgpack.encode)({jsonrpc:this.props.jsonrpc,params,method,...guid}))};stream=data=>{const{id:paramId,method,callback,params}=data;if(void 0===method||!callback||1!==this.ws.readyState)return;const id=this.saveGUID(paramId||generateUUID());if(callback)this.saveResponse(callback,id);this.ws.send((0,msgpack.encode)({jsonrpc:this.props.jsonrpc,params,method,id:this.streamID}));return{id:this.streamID,close:(code,reason)=>{this.streamID="";this.close(code,reason)}}};close=(code,reason)=>this.ws.close(code,reason);withUrl=url=>{this.close();this.guidStorage=[];this.callbackStorage={};this.streamID="";this.props.url=url;this.ws=this.setupWS()}}const src=Socket;export{src as default};
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@rfkit/json-rpc-websocket",
3
+ "description": "A lightweight JSON-RPC 2.0 client implementation over WebSocket, supporting request-response, notifications, and batch processing",
4
+ "module": "index.js",
5
+ "types": "index.d.ts",
6
+ "author": "Hxgh",
7
+ "license": "MIT",
8
+ "version": "0.1.0",
9
+ "private": false,
10
+ "keywords": [
11
+ "json-rpc",
12
+ "websocket",
13
+ "rpc",
14
+ "client",
15
+ "remote-procedure-call",
16
+ "typescript",
17
+ "real-time",
18
+ "communication",
19
+ "async"
20
+ ]
21
+ }
package/socket.d.ts ADDED
@@ -0,0 +1,103 @@
1
+ import type { PropsType, SocketType, WithUrl } from './type';
2
+ /**
3
+ * Socket
4
+ * 基于WebSocket、msgpack、JSONRPC封装的实时通讯函数
5
+ * @export
6
+ * @class Socket
7
+ */
8
+ export default class Socket {
9
+ private props;
10
+ private guidStorage;
11
+ private callbackStorage;
12
+ ws: WebSocket;
13
+ private streamID;
14
+ constructor(props: PropsType);
15
+ /**
16
+ * 初始化链接
17
+ *
18
+ * @private
19
+ * @returns {WebSocket}
20
+ * @memberof Socket
21
+ */
22
+ private setupWS;
23
+ /**
24
+ * 存储guid
25
+ *
26
+ * @private
27
+ * @param {string} guid
28
+ * @returns {string}
29
+ * @memberof Socket
30
+ */
31
+ private saveGUID;
32
+ /**
33
+ * 删除guid
34
+ *
35
+ * @private
36
+ * @param {string} guid
37
+ * @returns {boolean}
38
+ * @memberof Socket
39
+ */
40
+ private deleteGUID;
41
+ /**
42
+ * send时触发超时函数
43
+ *
44
+ * @private
45
+ * @param {string} guid
46
+ * @memberof Socket
47
+ */
48
+ private touchTimeout;
49
+ /**
50
+ * 存储回调方法
51
+ *
52
+ * @private
53
+ * @param {Communicate['callback']} callback
54
+ * @param {string} id
55
+ * @memberof Socket
56
+ */
57
+ private saveResponse;
58
+ /**
59
+ * 执行回调方法并移除
60
+ *
61
+ * @private
62
+ * @param {string} id
63
+ * @returns
64
+ * @memberof Socket
65
+ */
66
+ private finishResponse;
67
+ /**
68
+ * 接收数据
69
+ *
70
+ * @param {MessageEvent} buffer
71
+ * @returns
72
+ * @memberof Socket
73
+ */
74
+ private onmessage;
75
+ /**
76
+ * 发送数据
77
+ *
78
+ * @param {Communicate} params
79
+ * @returns
80
+ * @memberof Socket
81
+ */
82
+ send: SocketType['send'];
83
+ /**
84
+ * 启用流模式
85
+ *
86
+ * @type {SocketType['stream']}
87
+ * @memberof Socket
88
+ */
89
+ stream: SocketType['stream'];
90
+ /**
91
+ * 关闭链接
92
+ *
93
+ * @memberof Socket
94
+ */
95
+ close: SocketType['close'];
96
+ /**
97
+ * 更换url
98
+ *
99
+ * @type {WithUrl}
100
+ * @memberof Socket
101
+ */
102
+ withUrl: WithUrl;
103
+ }
package/tools.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 生成四位随机数(十六进制)
3
+ * @returns {string} 四位十六进制随机数
4
+ */
5
+ export declare const generateHexSegment: () => string;
6
+ /**
7
+ * 生成全局唯一标识符(UUID)
8
+ * 格式: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
9
+ * @returns {string} 符合RFC4122标准的UUID字符串
10
+ */
11
+ export declare const generateUUID: () => string;
12
+ /**
13
+ * 生成简单的唯一ID(更短的标识符)
14
+ * @param {number} [length=8] ID的长度
15
+ * @returns {string} 指定长度的随机ID
16
+ */
17
+ export declare const generateId: (length?: number) => string;
package/type.d.ts ADDED
@@ -0,0 +1,138 @@
1
+ /**
2
+ * 发送数据时回调函数参数类型
3
+ *
4
+ * @export
5
+ * @interface ResType
6
+ */
7
+ export interface ResType {
8
+ jsonrpc: string;
9
+ result: object;
10
+ id: string;
11
+ error?: object;
12
+ message?: string;
13
+ data?: string | object;
14
+ res?: ResType['result'] | ResType['error'] | {
15
+ message: ResType['message'];
16
+ data: ResType['data'];
17
+ };
18
+ }
19
+ /**
20
+ * 发送数据的参数类型
21
+ *
22
+ * @export
23
+ * @interface Communicate
24
+ */
25
+ export interface Communicate {
26
+ jsonrpc?: string;
27
+ method: string;
28
+ params?: Record<string, unknown>;
29
+ id?: string;
30
+ timeout?: number;
31
+ isInform?: boolean | undefined;
32
+ callback?: (res: ResType['res']) => void;
33
+ onerror?: (res: {
34
+ code?: string | number;
35
+ message?: string;
36
+ }) => void;
37
+ }
38
+ /**
39
+ * Socket的事件类型
40
+ *
41
+ * @export
42
+ * @interface PropsFuncType
43
+ */
44
+ export interface PropsFuncType {
45
+ onopen: (e?: Event) => void;
46
+ onmessage: (e?: unknown) => void;
47
+ onclose: (e?: CloseEvent) => void;
48
+ onerror: (e?: Event) => void;
49
+ }
50
+ /**
51
+ * Socket的websocket参数类型
52
+ *
53
+ * @export
54
+ * @interface PropsType
55
+ */
56
+ export interface PropsType {
57
+ url: string;
58
+ protocols?: string | string[] | undefined;
59
+ onopen?: PropsFuncType['onopen'];
60
+ onmessage?: PropsFuncType['onmessage'];
61
+ onclose?: PropsFuncType['onclose'];
62
+ onerror?: PropsFuncType['onerror'];
63
+ jsonrpc?: string;
64
+ }
65
+ /**
66
+ * 发送数据时回调函数存储的类型
67
+ *
68
+ * @export
69
+ * @interface CallbackStorage
70
+ */
71
+ export interface CallbackStorage {
72
+ [propName: string]: Communicate['callback'];
73
+ }
74
+ /**
75
+ * 更换url函数的数据类型
76
+ *
77
+ * @export
78
+ * @interface WithUrl
79
+ */
80
+ export type WithUrl = (url: string) => void;
81
+ /**
82
+ * stream的类型
83
+ *
84
+ * @export
85
+ * @interface SocketStrem
86
+ */
87
+ export interface SocketStrem {
88
+ close: (code?: number, reason?: string) => void;
89
+ }
90
+ /**
91
+ * 实时通讯函暴露的API类型:public
92
+ *
93
+ * @export
94
+ * @interface SocketType
95
+ */
96
+ export interface SocketType {
97
+ send: (send: Communicate) => void;
98
+ close: (code?: number, reason?: string) => void;
99
+ stream: (send: Communicate) => {
100
+ id: string;
101
+ close: SocketStrem['close'];
102
+ } | undefined;
103
+ }
104
+ /**
105
+ * JSON-RPC 2.0 请求对象
106
+ */
107
+ export interface JsonRpcRequest {
108
+ jsonrpc: '2.0';
109
+ method: string;
110
+ params?: unknown;
111
+ id?: string | number | null;
112
+ }
113
+ /**
114
+ * JSON-RPC 2.0 响应对象
115
+ */
116
+ export interface JsonRpcResponse {
117
+ jsonrpc: '2.0';
118
+ result?: unknown;
119
+ error?: JsonRpcError;
120
+ id: string | number | null;
121
+ }
122
+ /**
123
+ * JSON-RPC 2.0 错误对象
124
+ */
125
+ export interface JsonRpcError {
126
+ code: number;
127
+ message: string;
128
+ data?: unknown;
129
+ }
130
+ /**
131
+ * 连接选项
132
+ */
133
+ export interface ConnectionOptions {
134
+ reconnect?: boolean;
135
+ reconnectInterval?: number;
136
+ maxReconnectAttempts?: number;
137
+ timeout?: number;
138
+ }