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

@pylonide/smith

v0.2.0

Published

Smith is an RPC agent system for Node.JS used in architect and vfs.

Downloads

40

Readme

Smith

Build Status

Smith is an RPC agent system for Node.JS used in architect and vfs.

Usage

Smith can be used in any situation where you have a duplex node stream. This can be over tcp, stdio, a pipe, or anything that sends bytes back and forth.

TCP client-server example

In this example, I have a TCP server that serves an add function to any agent clients who want to consume the service.

For the server, we create a small agent and serve it on a listening tcp port.

var net = require('net');
var Agent = require('smith').Agent;

var api = {
  add: function (a, b, callback) {
    callback(null, a + b);
  }
};

// Start a TCP server
net.createServer(function (socket) {
  // Create the agent that serves the shared api.
  var agent = new Agent(api);
  // Connect to the remote agent
  agent.connect(socket, function (err, api) {
    if (err) return console.error(err.stack);
    console.log("A new client connected");
  });
  // Log when the agent disconnects
  agent.on("disconnect", function (err) {
    console.error("The client disconnected")
    if (err) console.error(err.stack);
  });

}).listen(1337, function () {
  console.log("Agent server listening on port 1337");
});

Then to consume this TCP service, we can create an agent and connect it to the tcp server.

var net = require('net');
var Agent = require('smith').Agent;

var socket = net.connect(1337, function () {
  // Create our client
  var agent = new Agent()
  agent.connect(socket, function (err, api) {
    api.add(4, 5, function (err, result) {
      if (err) throw err;
      console.log("4 + 5 = %s", result);
      agent.disconnect();
    });
  });
});

For an example of how to reconnect if the connection goes down, see https://github.com/c9/smith/blob/master/samples/tcp-client-autoreconnect.js

STDIO Parent-Child Example

Here we create a node process that spawns a child process, and the two talk to eachother calling functions both directions.

Both share a simple API library.

exports.ping = function (callback) {
    callback(null, process.pid + " pong");
}

The parent creates an Agent,spawns the child, and connects.

var spawn = require('child_process').spawn;
var Agent = require('smith').Agent;
var Transport = require('smith').Transport;

// Create an agent instance using the shared API
var agent = new Agent(require('./process-shared-api'));

// Spawn the child process that runs the other half.
var child = spawn(process.execPath, [__dirname + "/process-child.js"]);
// Forward the child's console output
child.stderr.pipe(process.stderr);

var transport = new Transport(child.stdout, child.stdin);
agent.connect(transport, function (err, api) {
  if (err) throw err;
  // Call the child's API in a loop
  function loop() {
    api.ping(function (err, message) {
      if (err) throw err;
      console.log("Child says %s", message);
    })
    setTimeout(loop, Math.random() * 1000);
  }
  loop();
});

The child resumes stdin, creates an Agent, and connects.

var Agent = require('smith').Agent;
var Transport = require('smith').Transport;

// Redirect logs to stderr since stdout is used for data
console.log = console.error;

// Start listening on stdin for smith rpc data.
process.stdin.resume();

var agent = new Agent(require('./process-shared-api'));
var transport = new Transport(process.stdin, process.stdout);
agent.connect(transport, function (err, api) {
  if (err) throw err;
  // Call the parent's API in a loop
  function loop() {
    api.ping(function (err, message) {
      if (err) throw err;
      console.log("Got %s from parent", message);
    })
    setTimeout(loop, Math.random() * 1000);
  }
  loop();
});

Class: Agent

Agent is the main class used in smith. It represents an agent in your mesh network. It provides a set of service functions exposed as async functions.

new Agent(api)

Create a new Agent instance that serves the functions listed in api.

agent.api

The functions this agent serves locally to remote agents.

agent.remoteApi

A object containing proxy functions for the api functions in the remote agent. Calling these functions when the remote is offline will result in the last argument being called with a ENOTCONNECTED error (assuming it's a function).

agent.connectionTimeout

If the connection hasn't happened by 10,000 ms, an ETIMEDOUT error will happen. To change the timeoutvalue, change connectionTimeout on either the instance or the prototype. Set to zero to disable.

Event: 'connect'

function (remoteApi) { }

When the rpc handshake is complete, the agent will emit a connect event containing the remoteApi.

Event: 'disconnect'

function () { }

Emitted when the transport dies and the remote becomes offline

Event: 'drain'

When the writable stream in the transport emits drain, it's forwarded here

agent.connect(transport, [callback]))

Start the connection to a new remote agent using transport. Emits connect when ready or error on failure. Optionally use the callback to get (err, api, agent) results.

The transport argument is either a Transport instance or a duplex Stream. The callback will be called with (err, remoteApi).

agent.disconnect(err)

Tell the agent to disconnect from the transport with optional error reason err.

agent.send(message)

Encode a message and send it on the transport. Used internally to send function calls. Returns false if the kernel buffer is full.

Class: Transport

Transport is a wrapper around a duplex socket to allow two Agent instances to talk to eachother. A transport will shut down itself if either end of the socket ends and emit an error event.

new Transport(input, [output])

Pass in either a duplex Stream instance or two streams (one readable, one writable). This transport object can then be used to connect to another Agent.

Event: 'message'

function (message) { }

Emitted when a message arrives from the remote end of the transport.ts

Event: 'drain'

function () { }

Emitted when the writable stream emits drain. (The write buffer is empty.)

Event: 'disconnect'

function (err) { }

Emitted when the transport dies. If this was caused by an error, it will be emitted here.

transport.send(message)

Send a message to the other end of the transport. Message is JSON serializable object with the addition of being able to serialize node Buffer instances and undefined values. Returns true if the kernel buffer is full and you should pause your incoming stream.