@msaki/jsonrpc 0.1.1 → 0.1.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/README.md +5 -30
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -2
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +10 -6
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +32 -31
- package/src/client.ts +39 -34
- package/src/index.ts +2 -2
- package/src/server.ts +94 -75
- package/src/types.ts +17 -15
package/README.md
CHANGED
|
@@ -38,40 +38,15 @@ Bun.serve({
|
|
|
38
38
|
console.log("JSON-RPC sever on http://localhost:4444")
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
###
|
|
41
|
+
### RPC Client
|
|
42
42
|
|
|
43
43
|
```ts
|
|
44
44
|
import { initializeRpcClient } from "@msaki/jsonrpc";
|
|
45
45
|
const url = "http://localhost:4444";
|
|
46
46
|
const client = initializeRpcClient(url);
|
|
47
|
-
const result = client.call(
|
|
48
|
-
"
|
|
49
|
-
[
|
|
50
|
-
);
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Or
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
import { JsonRpcClient } from "@msaki/jsonrpc";
|
|
57
|
-
import type {
|
|
58
|
-
JsonRpcRequest,
|
|
59
|
-
JsonRpcResponse
|
|
60
|
-
} from "@msaki/jsonrpc";
|
|
61
|
-
|
|
62
|
-
const url = "http://localhost:4444";
|
|
63
|
-
|
|
64
|
-
const client = new JsonRpcClient(async (req: JsonRpcRequest<unknown>) => {
|
|
65
|
-
const res = await fetch(url, {
|
|
66
|
-
method: "POST",
|
|
67
|
-
headers: { "Content-Type": "application/json" },
|
|
68
|
-
body: JSON.stringify(req)
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
return (await res.json()) as JsonRpcResponse<unknown, number>
|
|
72
|
-
});
|
|
73
|
-
const result = client.call(
|
|
74
|
-
"rpc_method",
|
|
75
|
-
[1, 2]
|
|
47
|
+
const result = await client.call(
|
|
48
|
+
"ping",
|
|
49
|
+
[]
|
|
76
50
|
);
|
|
51
|
+
console.log(result)
|
|
77
52
|
```
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/D,qBAAa,aAAa;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/D,qBAAa,aAAa;IAIxB,OAAO,CAAC,IAAI;IAHb,OAAO,CAAC,EAAE,CAAK;gBAGN,IAAI,EAAE,CACb,GAAG,EAAE,cAAc,CAAC,OAAO,CAAC,KACxB,OAAO,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAGzC,IAAI,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACxD,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,OAAO,EAAE,GAChB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IActB,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE;CAQ1D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAW9D"}
|
package/dist/client.js
CHANGED
|
@@ -21,7 +21,7 @@ export class JsonRpcClient {
|
|
|
21
21
|
const request = {
|
|
22
22
|
jsonrpc: "2.0",
|
|
23
23
|
method,
|
|
24
|
-
params
|
|
24
|
+
params,
|
|
25
25
|
};
|
|
26
26
|
return this.send(request);
|
|
27
27
|
}
|
|
@@ -31,7 +31,7 @@ export function initializeRpcClient(url) {
|
|
|
31
31
|
const res = await fetch(url, {
|
|
32
32
|
method: "POST",
|
|
33
33
|
headers: { "Content-Type": "application/json" },
|
|
34
|
-
body: JSON.stringify(req)
|
|
34
|
+
body: JSON.stringify(req),
|
|
35
35
|
});
|
|
36
36
|
return (await res.json());
|
|
37
37
|
});
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;IAIhB;IAHD,EAAE,GAAG,CAAC,CAAC;IAEf,YACS,IAEsC;QAFtC,SAAI,GAAJ,IAAI,CAEkC;IAC5C,CAAC;IAEJ,KAAK,CAAC,IAAI,CACT,MAAc,EACd,MAAkB;QAElB,MAAM,OAAO,GAA2B;YACvC,OAAO,EAAE,KAAK;YACd,MAAM;YACN,MAAM;YACN,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE;SACb,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC,KAAU,CAAC;QAC5B,CAAC;QACD,OAAO,QAAQ,CAAC,MAAgB,CAAC;IAClC,CAAC;IAED,MAAM,CAAkB,MAAc,EAAE,MAAkB;QACzD,MAAM,OAAO,GAA2B;YACvC,OAAO,EAAE,KAAK;YACd,MAAM;YACN,MAAM;SACN,CAAC;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;CACD;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC9C,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,KAAK,EAAE,GAA4B,EAAE,EAAE;QACvE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;SACzB,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAqC,CAAC;IAC/D,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AACf,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/D,oBAAY,iBAAiB;IAC5B,eAAe,SAAS;IACxB,gBAAgB,SAAS;IACzB,cAAc,SAAS;IACvB,cAAc,SAAS;IACvB,WAAW,SAAS;IACpB,eAAe,SAAS;CACxB;AACD,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
|
@@ -18,12 +18,12 @@ export class JsonRpcServer {
|
|
|
18
18
|
if (raw.length === 0) {
|
|
19
19
|
return this.error(null, JsonRpcErrorCodes.INVALID_REQUEST, "Invalid request");
|
|
20
20
|
}
|
|
21
|
-
const responses = await Promise.all(raw.map(item => this.handle(item)));
|
|
21
|
+
const responses = await Promise.all(raw.map((item) => this.handle(item)));
|
|
22
22
|
const filtered = responses.filter((r) => r !== null);
|
|
23
23
|
return filtered.length > 0 ? filtered : null;
|
|
24
24
|
}
|
|
25
25
|
// handle single response
|
|
26
|
-
|
|
26
|
+
const req = raw;
|
|
27
27
|
if (typeof req !== "object" ||
|
|
28
28
|
req === null ||
|
|
29
29
|
req.jsonrpc !== "2.0" ||
|
|
@@ -32,10 +32,14 @@ export class JsonRpcServer {
|
|
|
32
32
|
}
|
|
33
33
|
const id = typeof req?.id === "string" ||
|
|
34
34
|
typeof req?.id === "number" ||
|
|
35
|
-
req?.id === null
|
|
35
|
+
req?.id === null
|
|
36
|
+
? req.id
|
|
37
|
+
: null;
|
|
36
38
|
const handler = this.methods.get(req.method);
|
|
37
39
|
if (!handler) {
|
|
38
|
-
return id === null
|
|
40
|
+
return id === null
|
|
41
|
+
? null
|
|
42
|
+
: this.error(req.id, JsonRpcErrorCodes.METHOD_NOT_FOUND, "Method not found");
|
|
39
43
|
}
|
|
40
44
|
try {
|
|
41
45
|
const result = await handler(req.params);
|
|
@@ -44,7 +48,7 @@ export class JsonRpcServer {
|
|
|
44
48
|
return {
|
|
45
49
|
jsonrpc: "2.0",
|
|
46
50
|
result,
|
|
47
|
-
id: req.id
|
|
51
|
+
id: req.id,
|
|
48
52
|
};
|
|
49
53
|
}
|
|
50
54
|
catch (err) {
|
|
@@ -55,7 +59,7 @@ export class JsonRpcServer {
|
|
|
55
59
|
return {
|
|
56
60
|
jsonrpc: "2.0",
|
|
57
61
|
error: { code, message, data },
|
|
58
|
-
id: id ?? null
|
|
62
|
+
id: id ?? null,
|
|
59
63
|
};
|
|
60
64
|
}
|
|
61
65
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,iBAOX;AAPD,WAAY,iBAAiB;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAE/C,MAAM,WAAW,cAAc,CAAC,MAAM;IACrC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,EAAE,CAAC,EAAE,SAAS,CAAC;CACf;AAED,MAAM,WAAW,cAAc,CAAC,MAAM;IACrC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,SAAS,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB,CAAC,SAAS;IAC5C,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,YAAY,CAAC,SAAS;IACtC,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACrC,EAAE,EAAE,SAAS,CAAC;CACd;AAED,MAAM,MAAM,eAAe,CAAC,MAAM,EAAE,SAAS,IAC1C,cAAc,CAAC,MAAM,CAAC,GACtB,YAAY,CAAC,SAAS,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
2
|
+
"name": "@msaki/jsonrpc",
|
|
3
|
+
"author": "Meek Msaki",
|
|
4
|
+
"version": "0.1.3",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"src"
|
|
12
|
+
],
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/mmsaki/libs.git",
|
|
16
|
+
"directory": "packages/jsonrpc"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public",
|
|
20
|
+
"directory": "dist"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc -p tsconfig.json",
|
|
24
|
+
"publish": "bun run build && bun publish --access public",
|
|
25
|
+
"format": "bun biome format --write"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@biomejs/biome": "2.3.11",
|
|
29
|
+
"@types/bun": "latest"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"typescript": "^5"
|
|
33
|
+
}
|
|
33
34
|
}
|
package/src/client.ts
CHANGED
|
@@ -1,45 +1,50 @@
|
|
|
1
1
|
import type { JsonRpcRequest, JsonRpcResponse } from "./types";
|
|
2
2
|
|
|
3
3
|
export class JsonRpcClient {
|
|
4
|
-
|
|
4
|
+
private id = 0;
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
constructor(
|
|
7
|
+
private send: (
|
|
8
|
+
req: JsonRpcRequest<unknown>,
|
|
9
|
+
) => Promise<JsonRpcResponse<unknown, number>>,
|
|
10
|
+
) {}
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
async call<Method = string, Result = unknown, E = unknown>(
|
|
13
|
+
method: Method,
|
|
14
|
+
params?: unknown[],
|
|
15
|
+
): Promise<Result | E> {
|
|
16
|
+
const request: JsonRpcRequest<Method> = {
|
|
17
|
+
jsonrpc: "2.0",
|
|
18
|
+
method,
|
|
19
|
+
params,
|
|
20
|
+
id: ++this.id,
|
|
21
|
+
};
|
|
22
|
+
const response = await this.send(request);
|
|
23
|
+
if ("error" in response) {
|
|
24
|
+
return response.error as E;
|
|
25
|
+
}
|
|
26
|
+
return response.result as Result;
|
|
27
|
+
}
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
notify<Method = string>(method: Method, params?: unknown[]) {
|
|
30
|
+
const request: JsonRpcRequest<Method> = {
|
|
31
|
+
jsonrpc: "2.0",
|
|
32
|
+
method,
|
|
33
|
+
params,
|
|
34
|
+
};
|
|
35
|
+
return this.send(request);
|
|
36
|
+
}
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
export function initializeRpcClient(url: string): JsonRpcClient {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
const client = new JsonRpcClient(async (req: JsonRpcRequest<unknown>) => {
|
|
41
|
+
const res = await fetch(url, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: { "Content-Type": "application/json" },
|
|
44
|
+
body: JSON.stringify(req),
|
|
45
|
+
});
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
return (await res.json()) as JsonRpcResponse<unknown, number>;
|
|
48
|
+
});
|
|
49
|
+
return client;
|
|
45
50
|
}
|
package/src/index.ts
CHANGED
package/src/server.ts
CHANGED
|
@@ -1,89 +1,108 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { JsonRpcRequest, JsonRpcResponse } from "./types";
|
|
2
2
|
|
|
3
3
|
export enum JsonRpcErrorCodes {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
INVALID_REQUEST = -32600,
|
|
5
|
+
METHOD_NOT_FOUND = -32601,
|
|
6
|
+
INVALID_PARAMS = -32602,
|
|
7
|
+
INTERNAL_ERROR = -32603,
|
|
8
|
+
PARSE_ERROR = -32700,
|
|
9
|
+
REQUEST_ABORTED = -32800,
|
|
10
10
|
}
|
|
11
|
-
export type Handler<Result> = (params: any) => any | Promise<Result
|
|
11
|
+
export type Handler<Result> = (params: any) => any | Promise<Result>;
|
|
12
12
|
|
|
13
13
|
export class JsonRpcServer {
|
|
14
|
-
|
|
14
|
+
private methods = new Map<string, Handler<any>>();
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
register(method: string, handler: Handler<any>) {
|
|
17
|
+
this.methods.set(method, handler);
|
|
18
|
+
}
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
20
|
+
async handle<Result, Method = string>(
|
|
21
|
+
raw: unknown,
|
|
22
|
+
): Promise<
|
|
23
|
+
| JsonRpcResponse<Result, JsonRpcErrorCodes | number>
|
|
24
|
+
| JsonRpcResponse<Result, JsonRpcErrorCodes | number>[]
|
|
25
|
+
| null
|
|
26
|
+
> {
|
|
27
|
+
// handle batch
|
|
28
|
+
if (Array.isArray(raw)) {
|
|
29
|
+
if (raw.length === 0) {
|
|
30
|
+
return this.error(
|
|
31
|
+
null,
|
|
32
|
+
JsonRpcErrorCodes.INVALID_REQUEST,
|
|
33
|
+
"Invalid request",
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const responses = await Promise.all(raw.map((item) => this.handle(item)));
|
|
37
|
+
const filtered = responses.filter(
|
|
38
|
+
(r): r is JsonRpcResponse<Result, JsonRpcErrorCodes | number> =>
|
|
39
|
+
r !== null,
|
|
40
|
+
);
|
|
41
|
+
return filtered.length > 0 ? filtered : null;
|
|
42
|
+
}
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
// handle single response
|
|
45
|
+
const req = raw as Partial<JsonRpcRequest<Method>>;
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
if (
|
|
48
|
+
typeof req !== "object" ||
|
|
49
|
+
req === null ||
|
|
50
|
+
req.jsonrpc !== "2.0" ||
|
|
51
|
+
typeof req.method !== "string"
|
|
52
|
+
) {
|
|
53
|
+
return this.error(
|
|
54
|
+
null,
|
|
55
|
+
JsonRpcErrorCodes.INVALID_REQUEST,
|
|
56
|
+
"Invalid request",
|
|
57
|
+
);
|
|
58
|
+
}
|
|
48
59
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
const id =
|
|
61
|
+
typeof (req as any)?.id === "string" ||
|
|
62
|
+
typeof (req as any)?.id === "number" ||
|
|
63
|
+
(req as any)?.id === null
|
|
64
|
+
? (req as any).id
|
|
65
|
+
: null;
|
|
53
66
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
const handler = this.methods.get(req.method);
|
|
68
|
+
if (!handler) {
|
|
69
|
+
return id === null
|
|
70
|
+
? null
|
|
71
|
+
: this.error(
|
|
72
|
+
req.id,
|
|
73
|
+
JsonRpcErrorCodes.METHOD_NOT_FOUND,
|
|
74
|
+
"Method not found",
|
|
75
|
+
);
|
|
76
|
+
}
|
|
58
77
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
try {
|
|
79
|
+
const result = await handler(req.params);
|
|
80
|
+
if (req.id === undefined) return null; // notification
|
|
81
|
+
return {
|
|
82
|
+
jsonrpc: "2.0",
|
|
83
|
+
result,
|
|
84
|
+
id: req.id,
|
|
85
|
+
};
|
|
86
|
+
} catch (err) {
|
|
87
|
+
return this.error(
|
|
88
|
+
req.id ?? null,
|
|
89
|
+
JsonRpcErrorCodes.INTERNAL_ERROR,
|
|
90
|
+
"Internal error",
|
|
91
|
+
err instanceof Error ? err.message : err,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
76
95
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
96
|
+
private error<Result, Method = string>(
|
|
97
|
+
id: JsonRpcRequest<Method>["id"],
|
|
98
|
+
code: JsonRpcErrorCodes | number,
|
|
99
|
+
message: string,
|
|
100
|
+
data?: unknown,
|
|
101
|
+
): JsonRpcResponse<Result, JsonRpcErrorCodes | number> {
|
|
102
|
+
return {
|
|
103
|
+
jsonrpc: "2.0",
|
|
104
|
+
error: { code, message, data },
|
|
105
|
+
id: id ?? null,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
89
108
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
|
-
export type JsonRpcId = string | number | null
|
|
1
|
+
export type JsonRpcId = string | number | null;
|
|
2
2
|
|
|
3
3
|
export interface JsonRpcRequest<Method> {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
jsonrpc: "2.0";
|
|
5
|
+
method: Method;
|
|
6
|
+
params?: unknown[];
|
|
7
|
+
id?: JsonRpcId;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface JsonRpcSuccess<Result> {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
jsonrpc: "2.0";
|
|
12
|
+
result: Result;
|
|
13
|
+
id: JsonRpcId;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface JsonRpcErrorObject<ErrorCode> {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
code: ErrorCode;
|
|
18
|
+
message: string;
|
|
19
|
+
data?: unknown;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export interface JsonRpcError<ErrorCode> {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
jsonrpc: "2.0";
|
|
24
|
+
error: JsonRpcErrorObject<ErrorCode>;
|
|
25
|
+
id: JsonRpcId;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export type JsonRpcResponse<Result, ErrorCode> =
|
|
28
|
+
export type JsonRpcResponse<Result, ErrorCode> =
|
|
29
|
+
| JsonRpcSuccess<Result>
|
|
30
|
+
| JsonRpcError<ErrorCode>;
|