2.0.2 • Published 11 months ago

rpc-async v2.0.2

Weekly downloads
-
License
ISC
Repository
github
Last release
11 months ago

RPC Async

Isomorphic async RPCs on top of message based communication protocols.

Out of the box support for:

  • Browser WebSockets
  • Browser WebWorker
  • NodeJS IPC (inter-process-communication)
  • NodeJS UDP sockets (bidirectional)
  • NodeJS duplex streams

Features

  • request-response mapping
  • concurrent requests
  • timout control
  • remote stack traces on / off
  • customisable message encoding
  • NodeJS and Browser support
  • TypeScript support

The package contains well formated JS files and TypeScript declarations. Once bundled and minified (e.g. using esbuild) it boils down to tiny ~4kb.

Usage

RPC over IPC in a cluster

Both peers can expose and invoke RPC APIs. For brevity, only the server side is implemented in this example.

import cluster from "node:cluster";
import { rpcFromIpc } from "rpc-async";

/* optional interface */
interface Server {
  add: (a: number, b: number) => number;
  disconnect: () => void;
}

if (cluster.isPrimary) {
  /* --- MAIN PROCESS ---- */
  const worker = cluster.fork();
  const rpc = rpcFromIpc(worker);
  /* Implement and expose local methods.  
  ✅ Use generics for type safety */
  rpc.expose<Server>({
    add: (a: number, b: number) => a + b,
    disconnect: () => cluster.disconnect(),
  });
} else {
  /* --- CHILD PROCESS ---- */
  /* ✅ Use generics for code completion */
  const rpc = rpcFromIpc<Server>(process);
  /* rpc.request[method]() invokes promisified non void remote methods */
  const sum = await rpc.request.add(3, 4);
  console.log("sum =", sum); // => 7
  /* rpc.notify[method]() invokes void remote methods */
  rpc.notify.disconnect();
}

API

Templates

NamePlatformSourceTest
rpcFromStreamNodeJSsourcetest
rpcFromIpcNodeJSsourcetest
rpcFromUdpNodeJSsourcetest
rpcFromWebSocketBrowsersourceTODO
rpcFromWebWorkerBrowsersourceTODO

User defined RPC template

If you have a communication channel that allows you to

  • send messages
  • listen to incoming messages
  • remove your listener (optional, but recommended)

You can build your own RPC wrapper.

/* -- pseudocode for an imaginary "com"unication channel -- */
import { createRpc, type Handler } from 'rpc-async'

export function myCustomRpc<T extends Handler>(com: any) {
  return createRpc<T>({
    /* required: send messages */
    send: (msg) => com.send(msg),
    /* required: listen to and route incoming messages. Should return a detach function */
    attach: (route) => {
      com.on("message", route)
      return () => com.removeListener("message", route)
    },
    /* optional message codec, depending on the needs of your communication channel */
    encode: (obj: any) => JSON.stringify(obj),
    decode: (text: string) => JSON.parse(text)
  });
}

This pseudocode is quite similar to the templates listed above. Usually the communication channels have quite similar APIs and only slight adjustments are required.

Developer Notes

Read about rpc-async protocol specs.

Publish via

npm run deploy [major|minor|patch]
# build > test > tag > publish #

Further reading

Credits

Other similar solutions

trpc provides a feature rich "End-to-end typesafe API".

2.0.2

11 months ago

1.0.1

11 months ago

1.0.0

12 months ago

2.0.1

11 months ago

2.0.0

11 months ago

0.3.0

1 year ago

0.2.3

2 years ago

0.2.2

2 years ago

0.2.1

2 years ago