A zero-dependencies protocol agnostic implementation of the JSON-RPC-2.0 spec.
This package includes a client and a server, but you can import either separately without increasing the size of your final build, if you don't need both.
npm install json-rpc-dual-engine
Create the server with an object that implements the methods to be exposed to the client:
import { JsonRpcServer } from 'json-rpc-dual-engine/server';
const api = {
multiply(a, b) {
return a * b;
},
ping() {
return 'pong';
},
};
const server = new JsonRpcServer({ api });
Register a onresponse
callback to receive the json-rpc responses generated by the server:
// `onresponse` will be called whenever the server generates a response.
// It's your job is to send it to the client somehow.
server.onresponse = response => console.log(response);
Then use the accept
method to deliver incoming remote method calls to the server.
The server validates the json-rpc message call, calls the appropriate registered method,
and generate the appropriate json-rpc response based on the return of the registered handler.
// It's your job to receive the request from the client somehow.
const request = '{"jsonrpc":"2.0","method":"multiply","params":[7,11],"id":"1"}';
server.accept(request);
// Output: '{"jsonrpc":"2.0","result":77,"id":"1"}'
Create the client:
import { JsonRpcClient } from 'json-rpc-dual-engine/client';
const client = new JsonRpcClient();
Register a onrequest
callack to send requests made by the client to the server.
// It's your job to send the requests to the server somehow.
client.onrequest = request => console.log(request);
client.sendRequest('multiply', [7, 11]);
// Output: '{"jsonrpc":"2.0","method":"multiply","params":[7,11],"id":"1"}'
client.sendNotification('ping'); // no return
// Output: '{"jsonrpc":"2.0","method":"ping"}'
// Or use the proxy object:
client.remote.multiply(7, 11);
client.remote.ping();
Use the accept
method to deliver incoming server responses to the client to resolve request promises.
// Using setTimeout to simulate a future incoming message from the server
setTimeout(100, () => {
const response = '{"jsonrpc":"2.0","result":77,"id":"2"}'; // Gets a response from the server somehow
client.accept(response);
});
const result = await client.request('multiply', [7, 11]);
console.log(result); // Output: 77
Or using the proxy object:
const remote = client.remote;
const result = await remote.multiply(7, 11);
console.log(result); // Output: 77
The JsonRpcDualEngine
class includes both a client and a server in it.
It's useful in cases where you need bidirectional communication.
The accept()
method of the dual engine accepts both requests and responses.
import { JsonRpcDualEngine } from 'json-rpc-dual-engine';
const engine1 = new JsonRpcDualEngine({
api: {
getId() { return '1'; }
}
});
const engine2 = new JsonRpcDualEngine({
api: {
getId() { return '2'; }
}
});
engine1.onmessage = message => engine2.accept(message);
engine2.onmessage = message => engine1.accept(message);
console.log(await engine1.sendRequest('getId')); // Output: '2'
console.log(await engine2.sendRequest('getId')); // Output: '1'
On the server side:
import { JsonRpcServer } from 'json-rpc-dual-engine/server';
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
const engine = JsonRpcServer({
api: {
multiply(a, b) {
return a * b;
}
}
});
wss.on('connection', ws => {
ws.on('message', request => engine.accept(request)); // Messages from the client are handled by the engine
engine.onresponse = response => ws.send(response); // Responses are sent to the client via websocket
});
On the client side:
import { JsonRpcClient } from 'json-rpc-dual-engine/client';
import WebSocket from 'ws';
const websocket = new WebSocket('ws://remote.example');
const engine = new JsonRpcClient();
engine.onrequest = request => websocket.send(request); // Requests are sent to the server via websocket
websocket.on('message', response => engine.accept(response)); // Responses from the server are handled by the engine
// Waits for connection before sending a message
await new Promise((resolve, reject) => {
websocket.onopen = resolve;
websocket.onerror = reject;
});
// Sends a json-rpc request through webscoket to the remote server and waits for the response
const result = await engine.remote.multiply(7, 11);
console.log(result); // Output: 77
npm install
npm test
npm run coverage