npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ch1/rpc

v1.3.1

Published

JavaScript Remote Procedure Call (RPC)

Downloads

11

Readme

CH1 RPC

CircleCI

This is not well maintained

This is not traditional RPC, but it is like it

Installation

yarn add @ch1/rpc

Usage

Convenient usage would be to use another library that consumes this library. Two examples are:

However this library can work over pretty much any stringifiable interface. Maybe binary one day.

Simplest Pure JS Example

Ideally process A/B would be literal separate processes like workers or sockets. However the usage can be "faked" in a single process as is done in [the tests]:(./spec/js-rpc.spec.ts "Testing Source Code")

Process A

const b = rpc.create({ /* config */}, {
  sayOnA: (arg) => console.log(`Process B says ${arg}`);
});

b.ready.then(() => b.remote.sayOnB('hello world');
// will call sayOnB on process B

Process B

const a = rpc.create({ /* config */}, {
  sayOnB: (arg) => console.log(`Process A says ${arg}`);
});

a.ready.then(() => a.remote.sayOnA('hello world');
// will call sayOnA on process A

How It Works

@ch1/rpc can work across any transport provided that the transport can be simplified into on and emit functions.

What do we mean by on and emit functions? Let's imagine for a moment the Web Worker API

note: @ch1/rpc-worker contains convenience functions that provide WebWorker support out of the box. The examples here are educational and do not need to be implemented

In our first process we might have a Web Worker:

// make a new worker
const myWorker = new Worker('worker.js');

// js-rpc only wants/needs to use the first parameter of emit consequently the
// WebWorker post message can be used out of the box
const emit = myWorker.postMessage.bind(myWorker);

// js-rpc's on message wants/needs data to be its first parameter.  Since
// WebWorker.onmessage boxes passed data into an even we need to extract it
const on = myWorker.onmessage(event => event.data);

// make a RPC Object:
const worker = create({ on, emit } /* object to expose on worker process */);

In our second WebWorker process we have a slightly different API:

// WebWorkers use a variable called "self" to register their messages:
// self.postMessage has the same api as in our previous example
const emit = self.postMessage.bind(self);

// self.onmessage also boxes data into events
const on = self.onmessage(event => event.data);

// make a RPC Object:
const parentWindow = create(
  { on, emit } /* object to expose on window process */,
);

API

The create call kicks everything off:

// RemoteType is a user defined type meant to inform TypeScript
// what the function signatures will be of `RPC.remote`
export function create<RemoteType>(
  // The config object is more like the internal state of the system
  // There are many config options
  // This object will be changing in the future to better separate concerns
  // Relevant config options will be documented below
  config: RPCConfig,
  // The optional "remote" object _in this context_ are the functions "local"
  // to the `create` call that you wish to expose on the other side
  // of the transport (worker, server, whatever)
  remote?: Remote<any>,
  // ignore this optional argument for now
  remoteDesc?: RemoteDesc,
): RPC<RemoteType>;

The RPC<RemoteType> interface is the full object you get back from the create call:

export interface RPC<RemoteType> {
  // The config object is more like the internal state of the system
  // There are many config options
  // This object will be changing in the future to better separate concerns
  // Relevant config options will be documented below
  config: RPCConfig;

  // promises to free up the resources, takes an optional reason that
  // propagates through to error messages received by any pending async
  // results
  destroy: (reason?: string) => Promise<void>;

  // registers a callback and calls it in the event the object's `destroy`
  // method is called.  `onDestroy` returns a de-registration function
  onDestroy: (callback: (reason?: string) => any) => () => void;

  // this is a promise that resolves if/when the rpc system is ready
  // it will time out and fail at a configurable threshold
  ready: Promise<void>;

  // this is the object that will expose all of the remote functions
  // this object can have nested objects with functions
  remote: RemoteType;
}

The RPCConfig Object is vast and it will be shrinking soon. The parts that will stay consistent are the mandatory configurations:

export interface RPCConfig {
  /*************** Required ***************/
  // the `emit` method must be defined by the user of `rpc`
  // it is what sends stuff to the worker/socket/whatever
  emit: (payload: any): any;

  // the `on` method must be defined by the user of `rpc`
  // it is what receives stuff from the worker/socket/whatever
  on: (callback: (payload: any) => any): () => any;
}

License

LGPL