gentle_rpc
JSON-RPC 2.0 TypeScript library for deno and the browser.
This library is accessible through the https://deno.land/x/ service or through https://nest.land/package/gentle_rpc.
Features
- Complies with the JSON-RPC 2.0 specification
- Sends data with the fetch API
- Uses JavaScript/TypeScript native proxies for a simple API on the client side
Example
Always use versioned imports for your dependencies. For example
https://deno.land/x/gentle_rpc@v1.2/rpcServer.ts
.
Server/deno side
import {
serve,
ServerRequest,
} from "https://deno.land/std@0.71.0/http/server.ts";
import { respondRpc } from "https://deno.land/x/gentle_rpc/rpcServer.ts";
console.log("listening on 0.0.0.0:8000");
const s = serve("0.0.0.0:8000");
const rpcMethods = {
sayHello: (w: string) => `Hello ${w}`,
animalsMakeNoise: (noise: string) => noise.toUpperCase(),
};
for await (const req of s) {
await respondRpc(req, rpcMethods);
}
Client/remote side
import { createRemote } from "https://deno.land/x/gentle_rpc/rpcClient.ts";
const remote = createRemote("http://0.0.0.0:8000");
const greeting = await remote.sayHello("World");
console.log(greeting); // Hello World
API
Server
respondRpc(request, methods, { includeServerErrorStack, callMethodsWithRequestObj })
- request:
ServerRequest
- methods:
{ [method: string]: (...args: any[]) => unknown }
- includeServerErrorStack:
boolean
detemines if the client's error objects may contain the server's error stack. Default isfalse
. - callMethodsWithRequestObj:
boolean
if true the request object will be added as the first argument to the method call. Default isfalse
. - returns the RPC response object.
Client
createRemote(url, options)
url: string | URL | Request
the URL to fetch data from.options: Options
this object sets the fetch API options (RequestInit). Additionally, it contains the three optional propertiesnotification: boolean
,id: string | number
andhandleUnsuccessfulResponse: (response: Response => any)
.notification
causes the server to make an empty response.id
defines a custom id.handleUnsuccessfulResponse
contains an optional callback which is called if fetch was not successful (status code outside the range 200-299). It takes the returned response object as argument.
- returns a remote proxy object (see below).
remote.method(values)
Each method call of the remote object will look for the identically named method on the server side, where the methods are defined. This API is based on the native JS/TS Proxy object.
Any amount of arguments to the method calls is possible.
The remote methods return the result property of the RPC response object as promise.
await remote.sayHello("World"); // Hello World
Batch Requests
Additionally, to send several request objects at the same time, the client may send an array filled with request objects (an RPC batch request). You can do this in two different ways:
remote.batch([["method", ["arg1", "arg2"]], ["method", ["arg1", "arg2"]], ...])
const noise1 = await remote.batch([
["animalsMakeNoise", ["miaaow"]],
["animalsMakeNoise", ["wuuuufu"]],
["animalsMakeNoise", ["iaaaiaia"]],
["animalsMakeNoise", ["fiiiiire"]],
]);
// [ "MIAAOW", "WUUUUFU", "IAAAIAIA", "FIIIIIRE" ]
remote.batch({key1: ["method", ["arg1", "arg2"]], key2: ["method", ["arg1", "arg2"]], ...})
This way of making batch requests uses the object keys (cat, dog, donkey, dragon) as RPC request object ids under the hood. The returned RPC result values will be assigned to these keys. Let's take a look at the following example:
const noise2 = await remote.batch({
cat: ["animalsMakeNoise", ["miaaow"]],
dog: ["animalsMakeNoise", ["wuuuufu"]],
donkey: ["animalsMakeNoise", ["iaaaiaia"]],
dragon: ["animalsMakeNoise", ["fiiiiire"]],
});
// { cat: "MIAAOW", dog: "WUUUUFU", donkey: "IAAAIAIA", dragon: "FIIIIIRE" }
Examples and Tests
Checkout the examples and tests folders for more detailed examples.
Contribution
Every kind of contribution to this project is highly appreciated.
Please run deno fmt
on the changed files before making a pull request.