@msaki/jsonrpc 0.0.4 → 0.1.2

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # jsonrpc
2
2
 
3
+ ## `@msaki/jsonrpc`
4
+
5
+ A minimal jsonrpc server and client library.
6
+
7
+ ```sh
8
+ bun add @msaki/jsonrpc
9
+ ```
10
+
3
11
  ## Usage
4
12
 
5
13
  ### RPC Server
@@ -30,24 +38,15 @@ Bun.serve({
30
38
  console.log("JSON-RPC sever on http://localhost:4444")
31
39
  ```
32
40
 
33
- ### PRC Client
41
+ ### RPC Client
34
42
 
35
43
  ```ts
36
- import { JsonRpcClient } from "@msaki/jsonrpc";
37
- import type {
38
- JsonRpcRequest,
39
- JsonRpcResponse
40
- } from "@msaki/jsonrpc";
41
-
44
+ import { initializeRpcClient } from "@msaki/jsonrpc";
42
45
  const url = "http://localhost:4444";
43
-
44
- const client = new JsonRpcClient(async (req: JsonRpcRequest) => {
45
- const res = await fetch(url, {
46
- method: "POST",
47
- headers: { "Content-Type": "application/json" },
48
- body: JSON.stringify(req)
49
- });
50
-
51
- return (await res.json()) as JsonRpcResponse
52
- });
46
+ const client = initializeRpcClient(url);
47
+ const result = await client.call(
48
+ "ping",
49
+ []
50
+ );
51
+ console.log(result)
53
52
  ```
package/dist/client.d.ts CHANGED
@@ -2,8 +2,9 @@ import type { JsonRpcRequest, JsonRpcResponse } from "./types";
2
2
  export declare class JsonRpcClient {
3
3
  private send;
4
4
  private id;
5
- constructor(send: (req: JsonRpcRequest) => Promise<JsonRpcResponse>);
6
- call<T = unknown>(method: string, params?: unknown): Promise<T>;
7
- notify(method: string, params?: unknown): Promise<JsonRpcResponse>;
5
+ constructor(send: (req: JsonRpcRequest<unknown>) => Promise<JsonRpcResponse<unknown, number>>);
6
+ call<Method = string, Result = unknown, E = unknown>(method: Method, params?: unknown[]): Promise<Result | E>;
7
+ notify<Method = string>(method: Method, params?: unknown[]): Promise<JsonRpcResponse<unknown, number>>;
8
8
  }
9
+ export declare function initializeRpcClient(url: string): JsonRpcClient;
9
10
  //# sourceMappingURL=client.d.ts.map
@@ -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;IAItB,OAAO,CAAC,IAAI;IAHd,OAAO,CAAC,EAAE,CAAI;gBAGJ,IAAI,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC;IAG3D,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAerE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO;CAQxC"}
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;IAItB,OAAO,CAAC,IAAI;IAHd,OAAO,CAAC,EAAE,CAAI;gBAGJ,IAAI,EAAE,CAAC,GAAG,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAGrF,IAAI,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAcnH,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE;CAQ3D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAW9D"}
package/dist/client.js CHANGED
@@ -13,8 +13,7 @@ export class JsonRpcClient {
13
13
  };
14
14
  const response = await this.send(request);
15
15
  if ("error" in response) {
16
- const e = response.error;
17
- throw new Error(`RPC error ${e.code} ${e.message}`);
16
+ return response.error;
18
17
  }
19
18
  return response.result;
20
19
  }
@@ -27,4 +26,15 @@ export class JsonRpcClient {
27
26
  return this.send(request);
28
27
  }
29
28
  }
29
+ export function initializeRpcClient(url) {
30
+ const client = new JsonRpcClient(async (req) => {
31
+ const res = await fetch(url, {
32
+ method: "POST",
33
+ headers: { "Content-Type": "application/json" },
34
+ body: JSON.stringify(req)
35
+ });
36
+ return (await res.json());
37
+ });
38
+ return client;
39
+ }
30
40
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;IAId;IAHF,EAAE,GAAG,CAAC,CAAA;IAEd,YACU,IAAuD;QAAvD,SAAI,GAAJ,IAAI,CAAmD;IAC9D,CAAC;IAEJ,KAAK,CAAC,IAAI,CAAc,MAAc,EAAE,MAAgB;QACtD,MAAM,OAAO,GAAmB;YAC9B,OAAO,EAAE,KAAK;YACd,MAAM;YACN,MAAM;YACN,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE;SACd,CAAA;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAA;YACxB,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;QACrD,CAAC;QACD,OAAO,QAAQ,CAAC,MAAW,CAAA;IAC7B,CAAC;IAED,MAAM,CAAC,MAAc,EAAE,MAAgB;QACrC,MAAM,OAAO,GAAmB;YAC9B,OAAO,EAAE,KAAK;YACd,MAAM;YACN,MAAM;SACP,CAAA;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC3B,CAAC;CACF"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;IAId;IAHF,EAAE,GAAG,CAAC,CAAA;IAEd,YACU,IAAiF;QAAjF,SAAI,GAAJ,IAAI,CAA6E;IACxF,CAAC;IAEJ,KAAK,CAAC,IAAI,CAAiD,MAAc,EAAE,MAAkB;QAC3F,MAAM,OAAO,GAA2B;YACtC,OAAO,EAAE,KAAK;YACd,MAAM;YACN,MAAM;YACN,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE;SACd,CAAA;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;YACxB,OAAO,QAAQ,CAAC,KAAU,CAAA;QAC5B,CAAC;QACD,OAAO,QAAQ,CAAC,MAAgB,CAAA;IAClC,CAAC;IAED,MAAM,CAAkB,MAAc,EAAE,MAAkB;QACxD,MAAM,OAAO,GAA2B;YACtC,OAAO,EAAE,KAAK;YACd,MAAM;YACN,MAAM;SACP,CAAA;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC3B,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,KAAK,EAAE,GAA4B,EAAE,EAAE;QACtE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;SAC1B,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAqC,CAAA;IAC/D,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/dist/server.d.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  import type { JsonRpcResponse } from "./types";
2
- export declare const INVALID_REQUEST = -32600;
3
- export declare const METHOD_NOT_FOUND = -32601;
4
- export declare const INVALID_PARAMS = -32602;
5
- export declare const INTERNAL_ERROR = -32603;
6
- export declare const PARSE_ERROR = -32700;
7
- export declare const REQUEST_ABORTED = -32800;
8
- export type Handler = (params: any) => any | Promise<any>;
2
+ export declare 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
+ }
10
+ export type Handler<Result> = (params: any) => any | Promise<Result>;
9
11
  export declare class JsonRpcServer {
10
12
  private methods;
11
- register(method: string, handler: Handler): void;
12
- handle(raw: unknown): Promise<JsonRpcResponse | JsonRpcResponse[] | null>;
13
+ register(method: string, handler: Handler<any>): void;
14
+ handle<Result, Method = string>(raw: unknown): Promise<JsonRpcResponse<Result, JsonRpcErrorCodes | number> | JsonRpcResponse<Result, JsonRpcErrorCodes | number>[] | null>;
13
15
  private error;
14
16
  }
15
17
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,SAAS,CAAC;AAEhE,eAAO,MAAM,eAAe,SAAU,CAAC;AACvC,eAAO,MAAM,gBAAgB,SAAS,CAAC;AACvC,eAAO,MAAM,cAAc,SAAW,CAAC;AACvC,eAAO,MAAM,cAAc,SAAW,CAAC;AACvC,eAAO,MAAM,WAAW,SAAc,CAAC;AACvC,eAAO,MAAM,eAAe,SAAU,CAAC;AAEvC,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;AAEzD,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA6B;IAE5C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAInC,MAAM,CACV,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,eAAe,GAAG,eAAe,EAAE,GAAG,IAAI,CAAC;IAuDtD,OAAO,CAAC,KAAK;CAYd"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAC;AAE/D,oBAAY,iBAAiB;IAC3B,eAAe,SAAS;IACxB,gBAAgB,SAAS;IACzB,cAAc,SAAS;IACvB,cAAc,SAAS;IACvB,WAAW,SAAS;IACpB,eAAe,SAAS;CACzB;AACD,MAAM,MAAM,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AAEpE,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAkC;IAEjD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC;IAIxC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAClC,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC;IAuD9H,OAAO,CAAC,KAAK;CAYd"}
package/dist/server.js CHANGED
@@ -1,9 +1,12 @@
1
- export const INVALID_REQUEST = -32600;
2
- export const METHOD_NOT_FOUND = -32601;
3
- export const INVALID_PARAMS = -32602; // unused
4
- export const INTERNAL_ERROR = -32603;
5
- export const PARSE_ERROR = -32700; // unused
6
- export const REQUEST_ABORTED = -32800; // unused
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 = {}));
7
10
  export class JsonRpcServer {
8
11
  methods = new Map();
9
12
  register(method, handler) {
@@ -13,7 +16,7 @@ export class JsonRpcServer {
13
16
  // handle batch
14
17
  if (Array.isArray(raw)) {
15
18
  if (raw.length === 0) {
16
- return this.error(null, INVALID_REQUEST, "Invalid request");
19
+ return this.error(null, JsonRpcErrorCodes.INVALID_REQUEST, "Invalid request");
17
20
  }
18
21
  const responses = await Promise.all(raw.map(item => this.handle(item)));
19
22
  const filtered = responses.filter((r) => r !== null);
@@ -25,14 +28,14 @@ export class JsonRpcServer {
25
28
  req === null ||
26
29
  req.jsonrpc !== "2.0" ||
27
30
  typeof req.method !== "string") {
28
- return this.error(null, INVALID_REQUEST, "Invalid request");
31
+ return this.error(null, JsonRpcErrorCodes.INVALID_REQUEST, "Invalid request");
29
32
  }
30
33
  const id = typeof req?.id === "string" ||
31
34
  typeof req?.id === "number" ||
32
35
  req?.id === null ? req.id : null;
33
36
  const handler = this.methods.get(req.method);
34
37
  if (!handler) {
35
- return id === null ? null : this.error(req.id, METHOD_NOT_FOUND, "Method not found");
38
+ return id === null ? null : this.error(req.id, JsonRpcErrorCodes.METHOD_NOT_FOUND, "Method not found");
36
39
  }
37
40
  try {
38
41
  const result = await handler(req.params);
@@ -45,7 +48,7 @@ export class JsonRpcServer {
45
48
  };
46
49
  }
47
50
  catch (err) {
48
- return this.error(req.id ?? null, INTERNAL_ERROR, "Internal error", err instanceof Error ? err.message : err);
51
+ return this.error(req.id ?? null, JsonRpcErrorCodes.INTERNAL_ERROR, "Internal error", err instanceof Error ? err.message : err);
49
52
  }
50
53
  }
51
54
  error(id, code, message, data) {
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,iBAOX;AAPD,WAAY,iBAAiB;IAC3B,oFAAwB,CAAA;IACxB,sFAAyB,CAAA;IACzB,kFAAuB,CAAA;IACvB,kFAAuB,CAAA;IACvB,4EAAoB,CAAA;IACpB,oFAAwB,CAAA;AAC1B,CAAC,EAPW,iBAAiB,KAAjB,iBAAiB,QAO5B;AAGD,MAAM,OAAO,aAAa;IAChB,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAA;IAEjD,QAAQ,CAAC,MAAc,EAAE,OAAqB;QAC5C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,CAAC;IAED,KAAK,CAAC,MAAM,CACV,GAAY;QAEZ,eAAe;QACf,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACrB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAA;YAC/E,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CACnC,CAAA;YACD,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAC/B,CAAC,CAAC,EAA4D,EAAE,CAAC,CAAC,KAAK,IAAI,CAC5E,CAAA;YACD,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA;QAC9C,CAAC;QAED,yBAAyB;QACzB,IAAI,GAAG,GAAG,GAAsC,CAAA;QAEhD,IACE,OAAO,GAAG,KAAK,QAAQ;YACvB,GAAG,KAAK,IAAI;YACZ,GAAG,CAAC,OAAO,KAAK,KAAK;YACrB,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,EAC9B,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAA;QAC/E,CAAC;QAED,MAAM,EAAE,GACN,OAAQ,GAAW,EAAE,EAAE,KAAK,QAAQ;YAClC,OAAQ,GAAW,EAAE,EAAE,KAAK,QAAQ;YACnC,GAAW,EAAE,EAAE,KAAK,IAAI,CAAC,CAAC,CAAE,GAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QAEtD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,iBAAiB,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAA;QACxG,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACxC,IAAI,GAAG,CAAC,EAAE,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAA,CAAC,eAAe;YACrD,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM;gBACN,EAAE,EAAE,GAAG,CAAC,EAAE;aACX,CAAA;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,KAAK,CACf,GAAG,CAAC,EAAE,IAAI,IAAI,EACd,iBAAiB,CAAC,cAAc,EAChC,gBAAgB,EAChB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAA;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CACX,EAAgC,EAChC,IAAgC,EAChC,OAAe,EACf,IAAc;QAEd,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;YAC9B,EAAE,EAAE,EAAE,IAAI,IAAI;SACf,CAAA;IACH,CAAC;CACF"}
package/dist/types.d.ts CHANGED
@@ -1,24 +1,24 @@
1
1
  export type JsonRpcId = string | number | null;
2
- export interface JsonRpcRequest {
2
+ export interface JsonRpcRequest<Method> {
3
3
  jsonrpc: "2.0";
4
- method: string;
5
- params?: unknown;
4
+ method: Method;
5
+ params?: unknown[];
6
6
  id?: JsonRpcId;
7
7
  }
8
- export interface JsonRpcSuccess {
8
+ export interface JsonRpcSuccess<Result> {
9
9
  jsonrpc: "2.0";
10
- result: unknown;
10
+ result: Result;
11
11
  id: JsonRpcId;
12
12
  }
13
- export interface JsonRpcErrorObject {
14
- code: number;
13
+ export interface JsonRpcErrorObject<ErrorCode> {
14
+ code: ErrorCode;
15
15
  message: string;
16
16
  data?: unknown;
17
17
  }
18
- export interface JsonRpcError {
18
+ export interface JsonRpcError<ErrorCode> {
19
19
  jsonrpc: "2.0";
20
- error: JsonRpcErrorObject;
20
+ error: JsonRpcErrorObject<ErrorCode>;
21
21
  id: JsonRpcId;
22
22
  }
23
- export type JsonRpcResponse = JsonRpcSuccess | JsonRpcError;
23
+ export type JsonRpcResponse<Result, ErrorCode> = JsonRpcSuccess<Result> | JsonRpcError<ErrorCode>;
24
24
  //# sourceMappingURL=types.d.ts.map
@@ -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,CAAA;AAE9C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,EAAE,CAAC,EAAE,SAAS,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,EAAE,EAAE,SAAS,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAA;IACd,KAAK,EAAE,kBAAkB,CAAA;IACzB,EAAE,EAAE,SAAS,CAAA;CACd;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,YAAY,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;AAE9C,MAAM,WAAW,cAAc,CAAC,MAAM;IACpC,OAAO,EAAE,KAAK,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,OAAO,EAAE,CAAA;IAClB,EAAE,CAAC,EAAE,SAAS,CAAA;CACf;AAED,MAAM,WAAW,cAAc,CAAC,MAAM;IACpC,OAAO,EAAE,KAAK,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,EAAE,EAAE,SAAS,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB,CAAC,SAAS;IAC3C,IAAI,EAAE,SAAS,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,YAAY,CAAC,SAAS;IACrC,OAAO,EAAE,KAAK,CAAA;IACd,KAAK,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAA;IACpC,EAAE,EAAE,SAAS,CAAA;CACd;AAED,MAAM,MAAM,eAAe,CAAC,MAAM,EAAE,SAAS,IAAI,cAAc,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@msaki/jsonrpc",
3
3
  "author": "Meek Msaki",
4
- "version": "0.0.4",
4
+ "version": "0.1.2",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "scripts": {
23
23
  "build": "tsc -p tsconfig.json",
24
- "publish": "bun run build && bun run npm login && bun run npm publish --access public",
24
+ "publish": "bun run build && bun publish --access public",
25
25
  "lint": "tsc"
26
26
  },
27
27
  "devDependencies": {
package/src/client.ts CHANGED
@@ -4,11 +4,11 @@ export class JsonRpcClient {
4
4
  private id = 0
5
5
 
6
6
  constructor(
7
- private send: (req: JsonRpcRequest) => Promise<JsonRpcResponse>
7
+ private send: (req: JsonRpcRequest<unknown>) => Promise<JsonRpcResponse<unknown, number>>
8
8
  ) {}
9
9
 
10
- async call<T = unknown>(method: string, params?: unknown): Promise<T> {
11
- const request: JsonRpcRequest = {
10
+ async call<Method = string, Result = unknown, E = unknown>(method: Method, params?: unknown[]): Promise<Result | E> {
11
+ const request: JsonRpcRequest<Method> = {
12
12
  jsonrpc: "2.0",
13
13
  method,
14
14
  params,
@@ -16,14 +16,13 @@ export class JsonRpcClient {
16
16
  }
17
17
  const response = await this.send(request);
18
18
  if ("error" in response) {
19
- const e = response.error
20
- throw new Error(`RPC error ${e.code} ${e.message}`)
19
+ return response.error as E
21
20
  }
22
- return response.result as T
21
+ return response.result as Result
23
22
  }
24
23
 
25
- notify(method: string, params?: unknown) {
26
- const request: JsonRpcRequest = {
24
+ notify<Method = string>(method: Method, params?: unknown[]) {
25
+ const request: JsonRpcRequest<Method> = {
27
26
  jsonrpc: "2.0",
28
27
  method,
29
28
  params
@@ -31,3 +30,16 @@ export class JsonRpcClient {
31
30
  return this.send(request)
32
31
  }
33
32
  }
33
+
34
+ export function initializeRpcClient(url: string): JsonRpcClient {
35
+ const client = new JsonRpcClient(async (req: JsonRpcRequest<unknown>) => {
36
+ const res = await fetch(url, {
37
+ method: "POST",
38
+ headers: { "Content-Type": "application/json" },
39
+ body: JSON.stringify(req)
40
+ });
41
+
42
+ return (await res.json()) as JsonRpcResponse<unknown, number>
43
+ });
44
+ return client;
45
+ }
package/src/server.ts CHANGED
@@ -1,58 +1,59 @@
1
- import type { JsonRpcResponse, JsonRpcRequest } from "./types";
1
+ import type { JsonRpcResponse, JsonRpcRequest } from "./types";
2
2
 
3
- export const INVALID_REQUEST = -32600;
4
- export const METHOD_NOT_FOUND = -32601;
5
- export const INVALID_PARAMS = -32602; // unused
6
- export const INTERNAL_ERROR = -32603;
7
- export const PARSE_ERROR = -32700; // unused
8
- export const REQUEST_ABORTED = -32800; // unused
9
-
10
- export type Handler = (params: any) => any | Promise<any>
3
+ export enum JsonRpcErrorCodes {
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
+ }
11
+ export type Handler<Result> = (params: any) => any | Promise<Result>
11
12
 
12
13
  export class JsonRpcServer {
13
- private methods = new Map<string, Handler>()
14
+ private methods = new Map<string, Handler<any>>()
14
15
 
15
- register(method: string, handler: Handler) {
16
+ register(method: string, handler: Handler<any>) {
16
17
  this.methods.set(method, handler)
17
18
  }
18
19
 
19
- async handle(
20
- raw: unknown,
21
- ): Promise<JsonRpcResponse | JsonRpcResponse[] | null> {
20
+ async handle<Result, Method = string>(
21
+ raw: unknown,
22
+ ): Promise<JsonRpcResponse<Result, JsonRpcErrorCodes | number> | JsonRpcResponse<Result, JsonRpcErrorCodes | number>[] | null> {
22
23
  // handle batch
23
24
  if (Array.isArray(raw)) {
24
25
  if (raw.length === 0) {
25
- return this.error(null, INVALID_REQUEST, "Invalid request")
26
+ return this.error(null, JsonRpcErrorCodes.INVALID_REQUEST, "Invalid request")
26
27
  }
27
28
  const responses = await Promise.all(
28
29
  raw.map(item => this.handle(item))
29
30
  )
30
- const filtered = responses.filter(
31
- (r): r is JsonRpcResponse => r !== null
31
+ const filtered = responses.filter(
32
+ (r): r is JsonRpcResponse<Result, JsonRpcErrorCodes | number> => r !== null
32
33
  )
33
34
  return filtered.length > 0 ? filtered : null
34
35
  }
35
36
 
36
37
  // handle single response
37
- let req = raw as Partial<JsonRpcRequest>
38
+ let req = raw as Partial<JsonRpcRequest<Method>>
38
39
 
39
40
  if (
40
41
  typeof req !== "object" ||
41
- req === null ||
42
- req.jsonrpc !== "2.0" ||
43
- typeof req.method !== "string"
42
+ req === null ||
43
+ req.jsonrpc !== "2.0" ||
44
+ typeof req.method !== "string"
44
45
  ) {
45
- return this.error(null, INVALID_REQUEST, "Invalid request")
46
+ return this.error(null, JsonRpcErrorCodes.INVALID_REQUEST, "Invalid request")
46
47
  }
47
-
48
- const id =
48
+
49
+ const id =
49
50
  typeof (req as any)?.id === "string" ||
50
- typeof (req as any)?.id === "number" ||
51
- (req as any)?.id === null ? (req as any).id : null
51
+ typeof (req as any)?.id === "number" ||
52
+ (req as any)?.id === null ? (req as any).id : null
52
53
 
53
54
  const handler = this.methods.get(req.method)
54
55
  if (!handler) {
55
- return id === null ? null : this.error(req.id, METHOD_NOT_FOUND, "Method not found")
56
+ return id === null ? null : this.error(req.id, JsonRpcErrorCodes.METHOD_NOT_FOUND, "Method not found")
56
57
  }
57
58
 
58
59
  try {
@@ -66,19 +67,19 @@ export class JsonRpcServer {
66
67
  } catch (err) {
67
68
  return this.error(
68
69
  req.id ?? null,
69
- INTERNAL_ERROR,
70
+ JsonRpcErrorCodes.INTERNAL_ERROR,
70
71
  "Internal error",
71
72
  err instanceof Error ? err.message : err
72
73
  )
73
74
  }
74
75
  }
75
76
 
76
- private error(
77
- id: JsonRpcRequest["id"],
78
- code: number,
77
+ private error<Result, Method = string>(
78
+ id: JsonRpcRequest<Method>["id"],
79
+ code: JsonRpcErrorCodes | number,
79
80
  message: string,
80
81
  data?: unknown
81
- ): JsonRpcResponse {
82
+ ): JsonRpcResponse<Result, JsonRpcErrorCodes | number> {
82
83
  return {
83
84
  jsonrpc: "2.0",
84
85
  error: { code, message, data },
package/src/types.ts CHANGED
@@ -1,28 +1,28 @@
1
1
  export type JsonRpcId = string | number | null
2
2
 
3
- export interface JsonRpcRequest {
3
+ export interface JsonRpcRequest<Method> {
4
4
  jsonrpc: "2.0"
5
- method: string
6
- params?: unknown
5
+ method: Method
6
+ params?: unknown[]
7
7
  id?: JsonRpcId
8
8
  }
9
9
 
10
- export interface JsonRpcSuccess {
10
+ export interface JsonRpcSuccess<Result> {
11
11
  jsonrpc: "2.0"
12
- result: unknown
12
+ result: Result
13
13
  id: JsonRpcId
14
14
  }
15
15
 
16
- export interface JsonRpcErrorObject {
17
- code: number
16
+ export interface JsonRpcErrorObject<ErrorCode> {
17
+ code: ErrorCode
18
18
  message: string
19
19
  data?: unknown
20
20
  }
21
21
 
22
- export interface JsonRpcError {
22
+ export interface JsonRpcError<ErrorCode> {
23
23
  jsonrpc: "2.0"
24
- error: JsonRpcErrorObject
24
+ error: JsonRpcErrorObject<ErrorCode>
25
25
  id: JsonRpcId
26
26
  }
27
27
 
28
- export type JsonRpcResponse = JsonRpcSuccess | JsonRpcError
28
+ export type JsonRpcResponse<Result, ErrorCode> = JsonRpcSuccess<Result> | JsonRpcError<ErrorCode>