Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5328daa

Browse files
committedApr 2, 2021
Include files
1 parent 1f167e0 commit 5328daa

File tree

8 files changed

+228
-107
lines changed

8 files changed

+228
-107
lines changed
 

‎examples/go/server/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ func main() {
5151

5252
// time.Sleep(5 * time.Second)
5353

54-
reply := ""
54+
reply := struct{}{}
5555

56-
err = endpoint.Call("Peer.SayHello", &data.Incoming{From: "Sudhh", Message: "hello!"}, &reply)
56+
err = endpoint.Call("Peer.SayHello", &data.Incoming{From: "Sudhh", Message: "hello!"}, nil)
5757

5858
if err != nil {
5959
log.Println(err)

‎examples/js/client.js

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,30 @@
1-
import { WSRPC } from '../../js/index.js'
1+
const { WSRPC, WSClientTransport } = require('../../js/index.js')
22

3-
const rpc = new WSRPC('ws://localhost:8080/ws', async () => {
4-
console.log('connected')
3+
async function main() {
4+
const transport = new WSClientTransport(
5+
'ws://localhost:8080/ws',
6+
async () => {
7+
console.log('connected')
8+
},
9+
)
510

6-
// console.log('chat resp', await rpc.call('Chat.Notify', { From: `Tom Notify`, Message: 'hello!' }))
7-
// await new Promise(r => setTimeout(r, 500))
8-
// console.log('chat resp', await rpc.call('Chat.Notify', { From: `Tom Notify`, Message: 'hello!' }))
9-
})
11+
const rpc = new WSRPC(transport)
1012

11-
rpc.register('Peer.SayHello', async msg => {
12-
console.log('recv: ', msg)
13-
// throw new Error('llool')
14-
return 'llool'
15-
})
13+
transport.connect()
1614

17-
// for (let i = 0; i < 1000; i++) {
18-
// await new Promise(r => setTimeout(r, 500))
19-
// // console.log('chat resp', await rpc.call('Chat.Message', { From: `Tom ${i}`, Message: 'hello!' }))
20-
// rpc.notify('Chat.Message', { From: `Tom ${i}`, Message: 'hello!' })
21-
// }
15+
rpc.register('Peer.SayHello', async msg => {
16+
console.log('recv: ', msg)
17+
// throw new Error('llool')
18+
// return 'llool'
19+
})
20+
21+
for (let i = 0; i < 100; i++) {
22+
await new Promise(r => setTimeout(r, 50))
23+
// console.log('chat resp', await rpc.call('Chat.Message', { From: `Tom ${i}`, Message: 'hello!' }))
24+
rpc.notify('Chat.Message', { From: `Tom ${i}`, Message: 'hello!' })
25+
}
26+
27+
transport.close()
28+
}
29+
30+
main().catch(console.error)

‎examples/js/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "wsrpc-example",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"dependencies": {}
12+
}

‎js/index.d.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,45 @@ interface JsonRPC {
88
notify: (method: string, params?: any) => void;
99
}
1010
declare class WSRPC implements JsonRPC {
11+
private id;
12+
private transport;
13+
private methods;
14+
private pending;
15+
constructor(transport: WSTransport);
16+
private on;
17+
private send;
18+
register(method: string, handler: handlerFn): void;
19+
call(method: string, params?: any): Promise<any>;
20+
notify(method: string, params?: any): void;
21+
}
22+
interface WSTransport {
23+
setOnMessage(fn: (data: any) => void): void;
24+
send(msg: string): void;
25+
}
26+
declare class WSClientTransport implements WSTransport {
1127
private ws?;
1228
private url;
1329
private openCB;
1430
private errCB;
15-
private id;
1631
private sendBuffer;
17-
private methods;
18-
private pending;
32+
private onmessage;
1933
constructor(url: string, openCB?: () => void, errCB?: {
2034
(...data: any[]): void;
2135
(message?: any, ...optionalParams: any[]): void;
2236
});
23-
private on;
24-
private send;
2537
private onopen;
2638
private onclose;
2739
private onerror;
2840
connect(): void;
29-
register(method: string, handler: handlerFn): void;
30-
call(method: string, params?: any): Promise<any>;
31-
notify(method: string, params?: any): void;
41+
setOnMessage(fn: (data: any) => void): void;
42+
send(msg: string): void;
3243
close(code?: number): void;
3344
}
34-
export { JsonRPC, WSRPC };
45+
declare class WSServerTransport implements WSTransport {
46+
private ws;
47+
private onmessage;
48+
constructor(ws: WebSocket);
49+
setOnMessage(fn: (data: any) => void): void;
50+
send(msg: string): void;
51+
}
52+
export { JsonRPC, WSRPC, WSTransport, WSClientTransport, WSServerTransport };

‎js/index.js

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
exports.WSServerTransport = exports.WSClientTransport = exports.WSRPC = void 0;
14
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
2-
const WebSocket = isBrowser ? window.WebSocket : (await import('ws')).default;
5+
let WebSocket;
6+
if (!isBrowser) {
7+
// @ts-ignore
8+
WebSocket = require('ws');
9+
}
310
const MAX_BUF_SIZE = 100;
411
const RECONNECT_MS = 5000;
512
const NOISY_ERRS = new Set(['ECONNREFUSED']);
@@ -14,14 +21,12 @@ const NO_METHOD_ERRPR = {
1421
data: 'No such function. ',
1522
};
1623
class WSRPC {
17-
constructor(url, openCB = () => { }, errCB = console.error) {
24+
constructor(transport) {
1825
this.id = 0;
19-
this.sendBuffer = [];
2026
this.methods = new Map();
2127
this.pending = new Map();
22-
this.url = url;
23-
this.openCB = openCB;
24-
this.errCB = errCB;
28+
this.transport = transport;
29+
transport.setOnMessage(this.on.bind(this));
2530
}
2631
on(data) {
2732
const msg = JSON.parse(data);
@@ -75,15 +80,37 @@ class WSRPC {
7580
}
7681
}
7782
send(msg) {
78-
if (this.ws?.readyState !== WebSocket.OPEN) {
79-
this.sendBuffer.push(msg);
80-
console.log(this.sendBuffer.length);
81-
if (this.sendBuffer.length >= MAX_BUF_SIZE) {
82-
throw new Error(`sendBuffer is overflowing!. Max=${MAX_BUF_SIZE}`);
83-
}
84-
return;
83+
this.transport.send(msg);
84+
}
85+
register(method, handler) {
86+
this.methods.set(method, handler);
87+
}
88+
call(method, params) {
89+
const id = this.id++;
90+
const msg = JSON.stringify({ /*jsonrpc: '2.0',*/ id, method, params });
91+
try {
92+
this.send(msg);
8593
}
86-
this.ws?.send(msg);
94+
catch (err) {
95+
return Promise.reject(err);
96+
}
97+
return new Promise((resolve, reject) => {
98+
this.pending.set(id, { resolve, reject });
99+
});
100+
}
101+
notify(method, params) {
102+
const msg = JSON.stringify({ /*jsonrpc: '2.0',*/ method, params });
103+
this.send(msg);
104+
}
105+
}
106+
exports.WSRPC = WSRPC;
107+
class WSClientTransport {
108+
constructor(url, openCB = () => { }, errCB = console.error) {
109+
this.sendBuffer = [];
110+
this.onmessage = (data) => { };
111+
this.url = url;
112+
this.openCB = openCB;
113+
this.errCB = errCB;
87114
}
88115
onopen() {
89116
const bufSize = this.sendBuffer.length;
@@ -108,33 +135,41 @@ class WSRPC {
108135
}
109136
connect() {
110137
const ws = (this.ws = new WebSocket(this.url));
111-
ws.onmessage = (ev) => this.on(ev.data);
138+
ws.onmessage = (ev) => this.onmessage(ev.data);
112139
ws.onerror = (ev) => this.onerror(ev.error);
113140
ws.onopen = () => this.onopen();
114141
ws.onclose = this.onclose.bind(this);
115142
}
116-
register(method, handler) {
117-
this.methods.set(method, handler);
143+
setOnMessage(fn) {
144+
this.onmessage = fn;
118145
}
119-
call(method, params) {
120-
const id = this.id++;
121-
const msg = JSON.stringify({ /*jsonrpc: '2.0',*/ id, method, params });
122-
try {
123-
this.send(msg);
124-
}
125-
catch (err) {
126-
return Promise.reject(err);
146+
send(msg) {
147+
if (this.ws?.readyState !== WebSocket.OPEN) {
148+
this.sendBuffer.push(msg);
149+
console.log(this.sendBuffer.length);
150+
if (this.sendBuffer.length >= MAX_BUF_SIZE) {
151+
throw new Error(`sendBuffer is overflowing!. Max=${MAX_BUF_SIZE}`);
152+
}
153+
return;
127154
}
128-
return new Promise((resolve, reject) => {
129-
this.pending.set(id, { resolve, reject });
130-
});
131-
}
132-
notify(method, params) {
133-
const msg = JSON.stringify({ /*jsonrpc: '2.0',*/ method, params });
134-
this.send(msg);
155+
this.ws?.send(msg);
135156
}
136157
close(code = 1000) {
137158
this.ws?.close(code);
138159
}
139160
}
140-
export { WSRPC };
161+
exports.WSClientTransport = WSClientTransport;
162+
class WSServerTransport {
163+
constructor(ws) {
164+
this.onmessage = (data) => { };
165+
this.ws = ws;
166+
this.ws.onmessage = evt => this.onmessage(evt.data);
167+
}
168+
setOnMessage(fn) {
169+
this.onmessage = fn;
170+
}
171+
send(msg) {
172+
this.ws.send(msg);
173+
}
174+
}
175+
exports.WSServerTransport = WSServerTransport;

‎js/index.ts

Lines changed: 87 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ interface JsonRPC {
1212
notify: (method: string, params?: any) => void
1313
}
1414

15-
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined'
16-
const WebSocket = isBrowser ? window.WebSocket : (await import('ws')).default
15+
const isBrowser =
16+
typeof window !== 'undefined' && typeof window.document !== 'undefined'
17+
18+
let WebSocket: any
19+
if (!isBrowser) {
20+
// @ts-ignore
21+
WebSocket = require('ws')
22+
}
1723

1824
const MAX_BUF_SIZE = 100
1925
const RECONNECT_MS = 5000
@@ -32,20 +38,14 @@ const NO_METHOD_ERRPR = {
3238
}
3339

3440
class WSRPC implements JsonRPC {
35-
private ws?: WebSocket
36-
private url: string
37-
private openCB: () => void
38-
private errCB: (e: Error) => void
39-
4041
private id = 0
41-
private sendBuffer: string[] = []
42+
private transport: WSTransport
4243
private methods: Map<string, handlerFn> = new Map()
4344
private pending: Map<number, promisePair> = new Map()
4445

45-
constructor(url: string, openCB = () => {}, errCB = console.error) {
46-
this.url = url
47-
this.openCB = openCB
48-
this.errCB = errCB
46+
constructor(transport: WSTransport) {
47+
this.transport = transport
48+
transport.setOnMessage(this.on.bind(this))
4949
}
5050

5151
private on(data: string) {
@@ -106,15 +106,52 @@ class WSRPC implements JsonRPC {
106106
}
107107

108108
private send(msg: string) {
109-
if (this.ws?.readyState !== WebSocket.OPEN) {
110-
this.sendBuffer.push(msg)
111-
console.log(this.sendBuffer.length)
112-
if (this.sendBuffer.length >= MAX_BUF_SIZE) {
113-
throw new Error(`sendBuffer is overflowing!. Max=${MAX_BUF_SIZE}`)
114-
}
115-
return
109+
this.transport.send(msg)
110+
}
111+
112+
public register(method: string, handler: handlerFn) {
113+
this.methods.set(method, handler)
114+
}
115+
116+
public call(method: string, params?: any): Promise<any> {
117+
const id = this.id++
118+
const msg = JSON.stringify({ /*jsonrpc: '2.0',*/ id, method, params })
119+
120+
try {
121+
this.send(msg)
122+
} catch (err) {
123+
return Promise.reject(err)
116124
}
117-
this.ws?.send(msg)
125+
126+
return new Promise((resolve, reject) => {
127+
this.pending.set(id, { resolve, reject })
128+
})
129+
}
130+
131+
public notify(method: string, params?: any) {
132+
const msg = JSON.stringify({ /*jsonrpc: '2.0',*/ method, params })
133+
this.send(msg)
134+
}
135+
}
136+
137+
interface WSTransport {
138+
setOnMessage(fn: (data: any) => void): void
139+
send(msg: string): void
140+
}
141+
142+
class WSClientTransport implements WSTransport {
143+
private ws?: WebSocket
144+
145+
private url: string
146+
private openCB: () => void
147+
private errCB: (e: Error) => void
148+
private sendBuffer: string[] = []
149+
private onmessage = (data: any) => {}
150+
151+
constructor(url: string, openCB = () => {}, errCB = console.error) {
152+
this.url = url
153+
this.openCB = openCB
154+
this.errCB = errCB
118155
}
119156

120157
private onopen() {
@@ -144,39 +181,49 @@ class WSRPC implements JsonRPC {
144181

145182
public connect() {
146183
const ws = (this.ws = new WebSocket(this.url) as WebSocket)
147-
ws.onmessage = (ev: any) => this.on(ev.data)
184+
ws.onmessage = (ev: any) => this.onmessage(ev.data)
148185
ws.onerror = (ev: any) => this.onerror(ev.error)
149186
ws.onopen = () => this.onopen()
150187
ws.onclose = this.onclose.bind(this)
151188
}
152189

153-
public register(method: string, handler: handlerFn) {
154-
this.methods.set(method, handler)
190+
public setOnMessage(fn: (data: any) => void) {
191+
this.onmessage = fn
155192
}
156193

157-
public call(method: string, params?: any): Promise<any> {
158-
const id = this.id++
159-
const msg = JSON.stringify({ /*jsonrpc: '2.0',*/ id, method, params })
160-
161-
try {
162-
this.send(msg)
163-
} catch (err) {
164-
return Promise.reject(err)
194+
public send(msg: string) {
195+
if (this.ws?.readyState !== WebSocket.OPEN) {
196+
this.sendBuffer.push(msg)
197+
console.log(this.sendBuffer.length)
198+
if (this.sendBuffer.length >= MAX_BUF_SIZE) {
199+
throw new Error(`sendBuffer is overflowing!. Max=${MAX_BUF_SIZE}`)
200+
}
201+
return
165202
}
203+
this.ws?.send(msg)
204+
}
166205

167-
return new Promise((resolve, reject) => {
168-
this.pending.set(id, { resolve, reject })
169-
})
206+
public close(code = 1000) {
207+
this.ws?.close(code)
170208
}
209+
}
171210

172-
public notify(method: string, params?: any) {
173-
const msg = JSON.stringify({ /*jsonrpc: '2.0',*/ method, params })
174-
this.send(msg)
211+
class WSServerTransport implements WSTransport {
212+
private ws: WebSocket
213+
private onmessage = (data: any) => {}
214+
215+
constructor(ws: WebSocket) {
216+
this.ws = ws
217+
this.ws.onmessage = evt => this.onmessage(evt.data)
175218
}
176219

177-
public close(code = 1000) {
178-
this.ws?.close(code)
220+
public setOnMessage(fn: (data: any) => void) {
221+
this.onmessage = fn
222+
}
223+
224+
public send(msg: string) {
225+
this.ws.send(msg)
179226
}
180227
}
181228

182-
export { JsonRPC, WSRPC }
229+
export { JsonRPC, WSRPC, WSTransport, WSClientTransport, WSServerTransport }

‎package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
"name": "jsonrpc",
33
"version": "1.1.0",
44
"description": "jsonrpc over websocket for golang &amp; typescript",
5-
"type": "module",
6-
"main": "js/index.js",
7-
"types": "js/index.d.ts",
5+
"main": "./js/index.js",
6+
"typings": "./js/index.d.ts",
87
"scripts": {
98
"build": "tsc -p .",
109
"test": "echo \"Error: no test specified\" && exit 1"

‎tsconfig.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
22
"files": ["js/index.ts"],
33
"compilerOptions": {
4-
"declaration": true,
4+
"declaration": false,
55
"target": "ES2020",
6-
"module": "ESNext",
76
"strict": true,
87
"moduleResolution": "node",
9-
"allowSyntheticDefaultImports": true,
8+
"module": "CommonJS",
9+
"allowSyntheticDefaultImports": false,
1010
"skipLibCheck": false,
11+
"esModuleInterop": false,
1112
"forceConsistentCasingInFileNames": true
1213
}
1314
}

0 commit comments

Comments
 (0)
Please sign in to comment.