@asyncswap/jsonrpc 0.4.1 → 0.4.3
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/CHANGELOG.md +15 -3
- package/README.md +92 -28
- package/dist/client.d.ts +3 -8
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +36 -10
- package/dist/client.js.map +1 -1
- package/dist/server.d.ts +0 -8
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +0 -9
- package/dist/server.js.map +1 -1
- package/example.ts +1 -1
- package/package.json +1 -1
- package/src/client.ts +47 -19
- package/src/server.ts +0 -8
- package/src/types/error.d.ts +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
# @asyncswap/jsonrpc
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.4.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 40a79dc: add support for batcing and streamlined error methods
|
|
8
|
+
|
|
9
|
+
## 0.4.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 9512db5: update documentation
|
|
14
|
+
|
|
15
|
+
## 0.4.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
6
18
|
|
|
7
|
-
- 7e8300c: changes api for jsonrpc
|
|
19
|
+
- 7e8300c: changes api for jsonrpc construction
|
|
8
20
|
|
|
9
21
|
### Patch Changes
|
|
10
22
|
|
|
11
23
|
- 43de065: update docs
|
|
12
|
-
- 7126afa: add `otherHeaders` to
|
|
24
|
+
- 7126afa: add `otherHeaders` to initializedClient calls
|
|
13
25
|
|
|
14
26
|
## 0.3.1
|
|
15
27
|
|
package/README.md
CHANGED
|
@@ -1,50 +1,114 @@
|
|
|
1
1
|
# jsonrpc
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A minimal JSON-RPC 2.0 server and client library.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
```
|
|
7
|
+
```bash
|
|
8
8
|
bun add @asyncswap/jsonrpc
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Quick Start
|
|
12
12
|
|
|
13
|
-
###
|
|
13
|
+
### Server
|
|
14
14
|
|
|
15
|
-
```
|
|
16
|
-
import { JsonRpcServer } from
|
|
15
|
+
```typescript
|
|
16
|
+
import { JsonRpcServer } from '@asyncswap/jsonrpc';
|
|
17
17
|
|
|
18
|
-
const server = new JsonRpcServer()
|
|
18
|
+
const server = new JsonRpcServer();
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
server.register(
|
|
20
|
+
// Register methods
|
|
21
|
+
server.register('add', ([a, b]: [number, number]) => a + b);
|
|
22
|
+
server.register('ping', () => 'pong');
|
|
23
|
+
|
|
24
|
+
// Handle requests
|
|
25
|
+
const response = await server.handle({
|
|
26
|
+
jsonrpc: '2.0',
|
|
27
|
+
method: 'add',
|
|
28
|
+
params: [2, 3],
|
|
29
|
+
id: 1
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
console.log(response); // { jsonrpc: '2.0', result: 5, id: 1 }
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Client
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { JsonRpcClient } from '@asyncswap/jsonrpc';
|
|
39
|
+
|
|
40
|
+
const client = new JsonRpcClient('http://localhost:4444');
|
|
41
|
+
|
|
42
|
+
// Make a call
|
|
43
|
+
const result = await client.call('add', [2, 3]);
|
|
44
|
+
console.log(result); // 5
|
|
45
|
+
|
|
46
|
+
// Send a notification (no response expected)
|
|
47
|
+
await client.notify('log', ['Hello world']);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## API Reference
|
|
51
|
+
|
|
52
|
+
### JsonRpcServer
|
|
53
|
+
|
|
54
|
+
#### Methods
|
|
55
|
+
|
|
56
|
+
- `register(method: string, handler: Handler<any>)` - Register a method handler
|
|
57
|
+
- `handle(request: any)` - Process a JSON-RPC request
|
|
58
|
+
|
|
59
|
+
#### Error Codes
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
enum JsonRpcErrorCodes {
|
|
63
|
+
INVALID_REQUEST = -32600,
|
|
64
|
+
METHOD_NOT_FOUND = -32601,
|
|
65
|
+
INVALID_PARAMS = -32602,
|
|
66
|
+
INTERNAL_ERROR = -32603,
|
|
67
|
+
PARSE_ERROR = -32700,
|
|
68
|
+
REQUEST_ABORTED = -32800,
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### JsonRpcClient
|
|
73
|
+
|
|
74
|
+
#### Constructor
|
|
75
|
+
|
|
76
|
+
- `new JsonRpcClient(url: string)` - Create a client instance
|
|
77
|
+
|
|
78
|
+
#### Methods
|
|
79
|
+
|
|
80
|
+
- `call<Method, Result, Error>(method, params?, headers?)` - Make a JSON-RPC call
|
|
81
|
+
- `notify<Method>(method, params?)` - Send a JSON-RPC notification
|
|
82
|
+
- `buildRequest(method, params?)` - Build a JSON-RPC request object
|
|
83
|
+
|
|
84
|
+
## Examples
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Server example
|
|
88
|
+
import { JsonRpcServer } from '@asyncswap/jsonrpc';
|
|
89
|
+
|
|
90
|
+
const server = new JsonRpcServer();
|
|
91
|
+
server.register('add', ([a, b]: [number, number]) => a + b);
|
|
22
92
|
|
|
23
93
|
Bun.serve({
|
|
24
94
|
port: 4444,
|
|
25
95
|
async fetch(req) {
|
|
26
|
-
if (req.method !== "POST") {
|
|
27
|
-
return new Response("JSON-RPC only", { status: 405 })
|
|
28
|
-
}
|
|
29
96
|
const payload = await req.json();
|
|
30
97
|
const response = await server.handle(payload);
|
|
31
|
-
if (!response) {
|
|
32
|
-
return new Response(null, { status: 204 })
|
|
33
|
-
}
|
|
34
98
|
return Response.json(response);
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
console.log("JSON-RPC running on http://localhost:4444")
|
|
99
|
+
},
|
|
100
|
+
});
|
|
39
101
|
```
|
|
40
102
|
|
|
41
|
-
|
|
103
|
+
```typescript
|
|
104
|
+
// Client example
|
|
105
|
+
import { JsonRpcClient } from '@asyncswap/jsonrpc';
|
|
42
106
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const url = "http://localhost:4444";
|
|
47
|
-
const client = new JsonRpcClient(url);
|
|
48
|
-
const result = await client.call("ping", []);
|
|
49
|
-
console.log(result);
|
|
107
|
+
const client = new JsonRpcClient('http://localhost:4444');
|
|
108
|
+
const result = await client.call('add', [2, 3]);
|
|
109
|
+
console.log(result); // 5
|
|
50
110
|
```
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT
|
package/dist/client.d.ts
CHANGED
|
@@ -2,14 +2,9 @@ export declare class JsonRpcClient {
|
|
|
2
2
|
private url;
|
|
3
3
|
private id;
|
|
4
4
|
constructor(url: string);
|
|
5
|
-
call<Method = string, Result = unknown, E = unknown>(
|
|
6
|
-
buildRequest<Method>(method: Method, params?: unknown[]):
|
|
7
|
-
jsonrpc: "2.0";
|
|
8
|
-
method: Method;
|
|
9
|
-
params: unknown[];
|
|
10
|
-
id: number;
|
|
11
|
-
};
|
|
5
|
+
call<Method = string, Result = unknown, E = unknown>(request: JsonRpcRequest<Method> | JsonRpcRequest<Method>[], headers?: Record<string, string>): Promise<Result | Result[] | E>;
|
|
6
|
+
buildRequest<Method>(method: Method, params?: unknown[]): JsonRpcRequest<Method>;
|
|
12
7
|
private request;
|
|
13
|
-
notify<Method = string>(method: Method, params?: unknown[]): Promise<
|
|
8
|
+
notify<Method = string>(method: Method, params?: unknown[]): Promise<void>;
|
|
14
9
|
}
|
|
15
10
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAa;IAGb,OAAO,CAAC,GAAG;IAFvB,OAAO,CAAC,EAAE,CAAK;gBAEK,GAAG,EAAE,MAAM;IAEzB,IAAI,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACxD,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAa;IAGb,OAAO,CAAC,GAAG;IAFvB,OAAO,CAAC,EAAE,CAAK;gBAEK,GAAG,EAAE,MAAM;IAEzB,IAAI,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACxD,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,EAAE,EAC1D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;IAgBjC,YAAY,CAAC,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,OAAO,EAAO,GACpB,cAAc,CAAC,MAAM,CAAC;YASX,OAAO;IA+Cf,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE;CAYhE"}
|
package/dist/client.js
CHANGED
|
@@ -4,21 +4,28 @@ export class JsonRpcClient {
|
|
|
4
4
|
constructor(url) {
|
|
5
5
|
this.url = url;
|
|
6
6
|
}
|
|
7
|
-
async call(
|
|
8
|
-
const request = this.buildRequest(method, params);
|
|
7
|
+
async call(request, headers) {
|
|
9
8
|
const response = await this.request(request, headers);
|
|
10
|
-
++this.id;
|
|
11
9
|
if ("error" in response) {
|
|
12
10
|
return response.error;
|
|
13
11
|
}
|
|
14
|
-
|
|
12
|
+
if ("result" in response) {
|
|
13
|
+
return response.result;
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(response)) {
|
|
16
|
+
return response;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
// what else can result be? maybe indefined
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
15
22
|
}
|
|
16
23
|
buildRequest(method, params = []) {
|
|
17
24
|
return {
|
|
18
25
|
jsonrpc: "2.0",
|
|
19
26
|
method,
|
|
20
27
|
params,
|
|
21
|
-
id: this.id,
|
|
28
|
+
id: ++this.id,
|
|
22
29
|
};
|
|
23
30
|
}
|
|
24
31
|
async request(req, customHeaders, timeout = 5000) {
|
|
@@ -33,24 +40,43 @@ export class JsonRpcClient {
|
|
|
33
40
|
method: "POST",
|
|
34
41
|
headers,
|
|
35
42
|
body: JSON.stringify(req),
|
|
43
|
+
signal: controller.signal,
|
|
36
44
|
});
|
|
37
45
|
return (await res.json());
|
|
38
46
|
}
|
|
39
47
|
catch (err) {
|
|
40
|
-
clearTimeout(timeoutId);
|
|
41
48
|
if (err instanceof Error && err.name === "AbortError") {
|
|
42
|
-
|
|
49
|
+
return {
|
|
50
|
+
jsonrpc: "2.0",
|
|
51
|
+
error: {
|
|
52
|
+
code: JsonRpcErrorCodes.REQUEST_ABORTED,
|
|
53
|
+
message: `Request Aborted. Timeout after ${timeout}ms.`,
|
|
54
|
+
},
|
|
55
|
+
id: null,
|
|
56
|
+
};
|
|
43
57
|
}
|
|
44
|
-
|
|
58
|
+
clearTimeout(timeoutId);
|
|
59
|
+
return {
|
|
60
|
+
jsonrpc: "2.0",
|
|
61
|
+
error: {
|
|
62
|
+
code: JsonRpcErrorCodes.REQUEST_FAILED,
|
|
63
|
+
message: `Request failed: ${err}`,
|
|
64
|
+
},
|
|
65
|
+
id: null,
|
|
66
|
+
};
|
|
45
67
|
}
|
|
46
68
|
}
|
|
47
|
-
notify(method, params) {
|
|
69
|
+
async notify(method, params) {
|
|
48
70
|
const request = {
|
|
49
71
|
jsonrpc: "2.0",
|
|
50
72
|
method,
|
|
51
73
|
params,
|
|
52
74
|
};
|
|
53
|
-
|
|
75
|
+
await fetch(this.url, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: { "Content-Type": "application/json" },
|
|
78
|
+
body: JSON.stringify(request),
|
|
79
|
+
});
|
|
54
80
|
}
|
|
55
81
|
}
|
|
56
82
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,aAAa;IAGL;IAFZ,EAAE,GAAG,CAAC,CAAC;IAEf,YAAoB,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;IAAI,CAAC;IAEpC,KAAK,CAAC,IAAI,CACT,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,aAAa;IAGL;IAFZ,EAAE,GAAG,CAAC,CAAC;IAEf,YAAoB,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;IAAI,CAAC;IAEpC,KAAK,CAAC,IAAI,CACT,OAA0D,EAC1D,OAAgC;QAEhC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACtD,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC,KAAU,CAAC;QAC5B,CAAC;QACD,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAC1B,OAAO,QAAQ,CAAC,MAAgB,CAAC;QAClC,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,QAAoB,CAAC;QAC7B,CAAC;aAAM,CAAC;YACP,2CAA2C;YAC3C,OAAO,QAAQ,CAAC;QACjB,CAAC;IACF,CAAC;IAED,YAAY,CACX,MAAc,EACd,SAAoB,EAAE;QAEtB,OAAO;YACN,OAAO,EAAE,KAAc;YACvB,MAAM;YACN,MAAM;YACN,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE;SACb,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,OAAO,CACpB,GAAwD,EACxD,aAAsC,EACtC,UAAkB,IAAI;QAItB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAChE,IAAI,CAAC;YACJ,MAAM,OAAO,GAA2B;gBACvC,cAAc,EAAE,kBAAkB;gBAClC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;aACxB,CAAC;YACF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;gBACjC,MAAM,EAAE,MAAM;gBACd,OAAO;gBACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;gBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;aACzB,CAAC,CAAC;YAEH,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAEa,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACvD,OAAO;oBACN,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACN,IAAI,EAAE,iBAAiB,CAAC,eAAe;wBACvC,OAAO,EAAE,kCAAkC,OAAO,KAAK;qBACvD;oBACD,EAAE,EAAE,IAAI;iBACR,CAAC;YACH,CAAC;YACD,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACN,IAAI,EAAE,iBAAiB,CAAC,cAAc;oBACtC,OAAO,EAAE,mBAAmB,GAAG,EAAE;iBACjC;gBACD,EAAE,EAAE,IAAI;aACR,CAAC;QACH,CAAC;IACF,CAAC;IAED,KAAK,CAAC,MAAM,CAAkB,MAAc,EAAE,MAAkB;QAC/D,MAAM,OAAO,GAA2B;YACvC,OAAO,EAAE,KAAK;YACd,MAAM;YACN,MAAM;SACN,CAAC;QACF,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;YACrB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC7B,CAAC,CAAC;IACJ,CAAC;CACD"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
export declare enum JsonRpcErrorCodes {
|
|
2
|
-
INVALID_REQUEST = -32600,
|
|
3
|
-
METHOD_NOT_FOUND = -32601,
|
|
4
|
-
INVALID_PARAMS = -32602,
|
|
5
|
-
INTERNAL_ERROR = -32603,
|
|
6
|
-
PARSE_ERROR = -32700,
|
|
7
|
-
REQUEST_ABORTED = -32800
|
|
8
|
-
}
|
|
9
1
|
export type Handler<Result> = (params: any) => any | Promise<Result>;
|
|
10
2
|
export declare class JsonRpcServer {
|
|
11
3
|
private methods;
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAErE,qBAAa,aAAa;IACzB,OAAO,CAAC,OAAO,CAAmC;IAElD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC;IAIxC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EACnC,GAAG,EAAE,OAAO,GACV,OAAO,CACP,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAAC,GACnD,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAAC,EAAE,GACrD,IAAI,CACN;IAsED,OAAO,CAAC,KAAK;CAYb"}
|
package/dist/server.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
export var JsonRpcErrorCodes;
|
|
2
|
-
(function (JsonRpcErrorCodes) {
|
|
3
|
-
JsonRpcErrorCodes[JsonRpcErrorCodes["INVALID_REQUEST"] = -32600] = "INVALID_REQUEST";
|
|
4
|
-
JsonRpcErrorCodes[JsonRpcErrorCodes["METHOD_NOT_FOUND"] = -32601] = "METHOD_NOT_FOUND";
|
|
5
|
-
JsonRpcErrorCodes[JsonRpcErrorCodes["INVALID_PARAMS"] = -32602] = "INVALID_PARAMS";
|
|
6
|
-
JsonRpcErrorCodes[JsonRpcErrorCodes["INTERNAL_ERROR"] = -32603] = "INTERNAL_ERROR";
|
|
7
|
-
JsonRpcErrorCodes[JsonRpcErrorCodes["PARSE_ERROR"] = -32700] = "PARSE_ERROR";
|
|
8
|
-
JsonRpcErrorCodes[JsonRpcErrorCodes["REQUEST_ABORTED"] = -32800] = "REQUEST_ABORTED";
|
|
9
|
-
})(JsonRpcErrorCodes || (JsonRpcErrorCodes = {}));
|
|
10
1
|
export class JsonRpcServer {
|
|
11
2
|
methods = new Map();
|
|
12
3
|
register(method, handler) {
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/example.ts
CHANGED
|
@@ -26,5 +26,5 @@ import { JsonRpcClient } from "./src";
|
|
|
26
26
|
|
|
27
27
|
const url = "http://localhost:4444";
|
|
28
28
|
const client = new JsonRpcClient(url);
|
|
29
|
-
const result = await client.call("ping", []);
|
|
29
|
+
const result = await client.call(client.buildRequest("ping", []));
|
|
30
30
|
console.log(result);
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -4,36 +4,43 @@ export class JsonRpcClient {
|
|
|
4
4
|
constructor(private url: string) { }
|
|
5
5
|
|
|
6
6
|
async call<Method = string, Result = unknown, E = unknown>(
|
|
7
|
-
|
|
8
|
-
params: unknown[] = [],
|
|
7
|
+
request: JsonRpcRequest<Method> | JsonRpcRequest<Method>[],
|
|
9
8
|
headers?: Record<string, string>,
|
|
10
|
-
): Promise<Result | E> {
|
|
11
|
-
const request: JsonRpcRequest<Method> = this.buildRequest<Method>(
|
|
12
|
-
method,
|
|
13
|
-
params,
|
|
14
|
-
);
|
|
9
|
+
): Promise<Result | Result[] | E> {
|
|
15
10
|
const response = await this.request(request, headers);
|
|
16
|
-
++this.id;
|
|
17
11
|
if ("error" in response) {
|
|
18
12
|
return response.error as E;
|
|
19
13
|
}
|
|
20
|
-
|
|
14
|
+
if ("result" in response) {
|
|
15
|
+
return response.result as Result;
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(response)) {
|
|
18
|
+
return response as Result[];
|
|
19
|
+
} else {
|
|
20
|
+
// what else can result be? maybe indefined
|
|
21
|
+
return response;
|
|
22
|
+
}
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
buildRequest<Method>(
|
|
25
|
+
buildRequest<Method>(
|
|
26
|
+
method: Method,
|
|
27
|
+
params: unknown[] = [],
|
|
28
|
+
): JsonRpcRequest<Method> {
|
|
24
29
|
return {
|
|
25
30
|
jsonrpc: "2.0" as const,
|
|
26
31
|
method,
|
|
27
32
|
params,
|
|
28
|
-
id: this.id,
|
|
33
|
+
id: ++this.id,
|
|
29
34
|
};
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
private async request(
|
|
33
|
-
req: JsonRpcRequest<unknown
|
|
38
|
+
req: JsonRpcRequest<unknown> | JsonRpcRequest<unknown>[],
|
|
34
39
|
customHeaders?: Record<string, string>,
|
|
35
40
|
timeout: number = 5000,
|
|
36
|
-
)
|
|
41
|
+
): Promise<
|
|
42
|
+
JsonRpcResponse<unknown, number> | JsonRpcResponse<unknown, number>[]
|
|
43
|
+
> {
|
|
37
44
|
const controller = new AbortController();
|
|
38
45
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
39
46
|
try {
|
|
@@ -45,24 +52,45 @@ export class JsonRpcClient {
|
|
|
45
52
|
method: "POST",
|
|
46
53
|
headers,
|
|
47
54
|
body: JSON.stringify(req),
|
|
55
|
+
signal: controller.signal,
|
|
48
56
|
});
|
|
49
57
|
|
|
50
|
-
return (await res.json()) as
|
|
58
|
+
return (await res.json()) as
|
|
59
|
+
| JsonRpcResponse<unknown, number>
|
|
60
|
+
| JsonRpcResponse<unknown, number>[];
|
|
51
61
|
} catch (err) {
|
|
52
|
-
clearTimeout(timeoutId);
|
|
53
62
|
if (err instanceof Error && err.name === "AbortError") {
|
|
54
|
-
|
|
63
|
+
return {
|
|
64
|
+
jsonrpc: "2.0",
|
|
65
|
+
error: {
|
|
66
|
+
code: JsonRpcErrorCodes.REQUEST_ABORTED,
|
|
67
|
+
message: `Request Aborted. Timeout after ${timeout}ms.`,
|
|
68
|
+
},
|
|
69
|
+
id: null,
|
|
70
|
+
};
|
|
55
71
|
}
|
|
56
|
-
|
|
72
|
+
clearTimeout(timeoutId);
|
|
73
|
+
return {
|
|
74
|
+
jsonrpc: "2.0",
|
|
75
|
+
error: {
|
|
76
|
+
code: JsonRpcErrorCodes.REQUEST_FAILED,
|
|
77
|
+
message: `Request failed: ${err}`,
|
|
78
|
+
},
|
|
79
|
+
id: null,
|
|
80
|
+
};
|
|
57
81
|
}
|
|
58
82
|
}
|
|
59
83
|
|
|
60
|
-
notify<Method = string>(method: Method, params?: unknown[]) {
|
|
84
|
+
async notify<Method = string>(method: Method, params?: unknown[]) {
|
|
61
85
|
const request: JsonRpcRequest<Method> = {
|
|
62
86
|
jsonrpc: "2.0",
|
|
63
87
|
method,
|
|
64
88
|
params,
|
|
65
89
|
};
|
|
66
|
-
|
|
90
|
+
await fetch(this.url, {
|
|
91
|
+
method: "POST",
|
|
92
|
+
headers: { "Content-Type": "application/json" },
|
|
93
|
+
body: JSON.stringify(request),
|
|
94
|
+
});
|
|
67
95
|
}
|
|
68
96
|
}
|
package/src/server.ts
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
export enum JsonRpcErrorCodes {
|
|
2
|
-
INVALID_REQUEST = -32600,
|
|
3
|
-
METHOD_NOT_FOUND = -32601,
|
|
4
|
-
INVALID_PARAMS = -32602,
|
|
5
|
-
INTERNAL_ERROR = -32603,
|
|
6
|
-
PARSE_ERROR = -32700,
|
|
7
|
-
REQUEST_ABORTED = -32800,
|
|
8
|
-
}
|
|
9
1
|
export type Handler<Result> = (params: any) => any | Promise<Result>;
|
|
10
2
|
|
|
11
3
|
export class JsonRpcServer {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
export enum JsonRpcErrorCodes {
|
|
3
|
+
INVALID_REQUEST = -32600,
|
|
4
|
+
METHOD_NOT_FOUND = -32601,
|
|
5
|
+
INVALID_PARAMS = -32602,
|
|
6
|
+
INTERNAL_ERROR = -32603,
|
|
7
|
+
PARSE_ERROR = -32700,
|
|
8
|
+
REQUEST_ABORTED = -32800,
|
|
9
|
+
REQUEST_FAILED = -32801,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { };
|