Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Easily harness the power of DNode/Upnode
tree: 29ff865e1e

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.


eNode is a simple wrapper around DNode and upnode functionality, simplifying creation and operation of DNode Servers and Clients. I found that DNode used some confusing patterns and made certain operations complicated, so I wrapped them up in an 'easier' interface.

Features and Differences from DNode

  • eNode makes a sharp distinction between Clients and Servers
  • Automatic buffering of requests and reconnections on lost servers as provided by upnode is configured by default between Servers and Clients
  • All 'connection' handling code is done in the 'connect' event, and unlike Dnode, the Servers/Clients don't return fire any callbacks/events until they have recieved the remote's API
  • Remote API calls get passed remote API & connection properties in a meta property as the last argument passed to every API call. This means you don't necessarily need to define your API inside the scope of connection handler to get access to connection/remote objects.
  • eNode servers automatically keep track of connections and disconnections, accessible via the server's connections Array.
  • The shutdown function will shut down both Servers and Clients, in DNode this was a multistep process which fired multiple events. eNode will fire 'shutdown'/return callback from shutdown when the connection is properly shut down.
  • All operations take a callback which fires when ready, but also emits corresponding events. e.g. shutdown() will emit the 'shutdown' event, but can also take a callback.
  • Using straight DNode on Node 0.6.x, if any of your remote calls callback with an Error the error arrive at the Client as an empty object. eNode finds Error objects in the data you're returning in your remote callback, and uses err.toString() to convert the Error into a String format like: 'Error: Some error occurred'. If you want to transmit more information about Errors, you can provide a different serialisation method by simply overriding serializeError on eNode Clients & Servers.


Create a Server with an API

var api = {
  sendInfo: function(info, callback) {
    // do something with info
    callback(null, {data: 'got some info: ' + info}) // stupid api

// create Server with  the supplied API
// and listen for connections on port 3000
var server = new enode.Server(api).listen(3000) 

Creating a Client and connecting to a Server

// connect to server running on port 3000
var client = enode.Client().connect(3000)

Executing Server API methods from a Client

// execute remote method 'getSomeData' from Server
client.once('ready', function(server, connection) {
  var info = 'bovine'
  server.sendInfo(info, function(err, returnedData) {
    console.log( // 'got some info: bovine'

Creating a Client with an API and connecting to a Server

var client
var api = {
  shutdown: client.shutdown(callback)

// Clients can have API's too
client = enode.Client(api).connect(3000)

Calling a Client API from a Server

server.on('connect', function(client, connection) {
  // call remote Client's `shutdown` method
  client.shutdown(function(err) {
    if (err) return console.log('error shutting down client: ' +
    console.log('client shut down: ' +

Shutting down a Server/Client

server.shutdown(function() {
  console.log('Callback: the server shutdown')

// or alternatively

server.on('shutdown', function() {
  console.log('Event: the server shutdown')

client.shutdown(function() {
  console.log('Callback: the client shutdown')

// shutdown event should execute around same time as shutdown callback is run
client.on('shutdown', function() {
  console.log('Event: the client shutdown')

Returning Errors

// alternative definition format
var server = new enode.Server({
  makeError: function(callback) {
    callback(new Error('oops'))

var client = new enode.Client().connect(3000, function(remote) { 
  // this connect() callback fires when client is connected 
  remote.makeError(function(err) {
    console.log(typeof err) // 'string'
    console.log(err) // Error: oops
    console.log('Error: oops' === err) // true



// server.js
var enode = require('enode')

var api = {
  whoami: function(callback, meta) {
    callback(null, "server " +

var server = new enode.Server(api).listen(5000)

server.on('connect', function(remote, connection) {
  console.log('new connection',
  remote.whoami(function(err, value) {
    console.log('server connected to', value)
  console.log('connected clients', server.connections.length)
server.on('disconnect', function(connection) {
  console.log('connected clients', server.connections.length)


// client.js
var enode = require('enode')

var api = {
  whoami: function(callback, meta) {
    callback(null, "client " +

var client = new enode.Client(api).connect(5000)

client.on('ready', function(remote) {
  remote.whoami(function(err, value) {
    console.log('client connected to', value)


  • Implement middleware
  • More usage examples


Tim Oxley



Something went wrong with that request. Please try again.