Tiny transport agnostic JSON-RPC 2.0 client and server which can work both in NodeJs, Browser, Electron etc
IMPORTANT: Library is in active development till version 1.0. API changes are possible.
- Transport agnostic (works with HTTP, MQTT, Websocket, Browser post message etc). Here is the list of supported transports - https://www.npmjs.com/search?q=keywords:mole-transport
- Zero dependencies. Mole-RPC itself has zero dependencies.
- Works both in NodeJs and in a browser (both client anf server). For example, you can use it to send request to webworker in your browser.
- Bidirectional websocket connections support via WS tranport. For example, you want a JSON RPC server which handles remote calls but the same time you want to send commands in opposite direction using the same connection.So, you can use connection initiated by any of the sides for the server and the client the same time.
- Server can use several transports the same time. For example, you want an RPC server that accepts connections from your local workers by TCP and from Web browser by websocket. You can pass as many transports as you wish.
- Lightweight
- Modern API. Totally based on Promises and supports Proxified interface
- Supports all features of JSON-RPC 2.0 (batches, notifications etc)
- Easy to create own transport. Transports have simple API as possible, so it is very easy to add a new transport.
You a lot of working examples you can find here too https://github.com/koorchik/node-mole-rpc-examples
If you use modern JavaScript you can use proxified client. It allows you to do remote calls very similar to local calls
import MoleClientProxified from 'mole-rpc/MoleClientProxified';
// choose any transports here
// https://www.npmjs.com/search?q=keywords:mole-transport
const transport = new TransportClient();
const calculator = new MoleClientProxified({ transport });
const result1 = await calculator.sum(1, 3);
const result2 = await calculator.asyncSum(2, 3);
// Send JSON RPC notification (fire and forget)
// server will send no response
await calculator.notify.sum(3, 2);
import MoleClient from 'mole-rpc/MoleClient';
// choose any transports here
// https://www.npmjs.com/search?q=keywords:mole-transport
const transport = new TransportClient();
const client = new MoleClient({ transport });
const result1 = await client.callMethod('sum', [1, 3]);
const result2 = await client.callMethod('sum', [2, 3]);
// Send JSON RPC notification (fire and forget)
// server will send no response
await client.notify('sum', [2, 3]);
You can expose instance directly. Methods which start with underscore will not be exposed. Built-in methods of Object base class will not be exposed.
import MoleServer from 'mole-rpc/MoleServer';
class Calculator {
sum(a, b) {
return a + b;
}
asyncSum(a, b) {
return new Promise((resolve, reject) => {
resolve(this.sum(a, b));
});
}
_privateMethod() {
// will not be exposed
}
}
const calculator = new Calculator();
// choose any transports here
// https://www.npmjs.com/search?q=keywords:mole-transport
const transports = [new TransportServer()];
const server = new MoleServer({ transports: [] });
server.expose(calculator);
await server.run();
You can expose functions directly
import MoleServer from "mole-rpc/MoleServer";
function sum(a, b) {
return a+b;
}
function asyncSum(a, b) {
return new Promise((resolve, reject) {
resolve( sum(a, b) );
});
}
// choose any transports here
// https://www.npmjs.com/search?q=keywords:mole-transport
const transports = [ new TransportServer() ];
const server = new MoleServer({ transports });
server.expose({
sum,
asyncSum
});
await server.run();
// Proxified client: explicit call
await calculator.callMethod.sum(1, 2); // the same as "calculator.sum(1, 2)"
// Can be usefull if your server method is a reserverd name.
// For example to make a call to remote "notify" method.
await proxifiedClient.callMethod.notify("Hello");
// Proxified client: run request in parallel
const promises = [
calculator.sum(1, 2);
calculator.notify.sum(1, 2);
];
const results = await Promise.all(promises);
// Simple client: run in parallel
const promises = [
client.callMethod('sum', [1, 2]);
client.notify('sum', [1, 2]);
];
const results = await Promise.all(promises);
// Simple client: run batch
const results = await client.runBatch([
['sum', [1, 3]],
['sum', [2, 5], 'notify'],
['sum', [7, 9], 'callMethod'], // "callMethod" is optional
[methodName, params, mode]
]);
// Result structure
[
{success: true, result: 123},
null, // no response for notification
{success: false, error: errorObject}
];
Usually,