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 🙏

© 2026 – Pkg Stats / Ryan Hefner

diva

v0.0.35

Published

Actor based javascript objects, with chaining, promises, and messaging

Readme

diva

still in development mode

Overview

This module is a base to write node modules with clear, concise, and expressive code. It provides a base class, methods, and patterns for creating concurrent, actor-based javascript.

Basically, the goal is to allow expressive, simple scripting like this:


var jimmy = new Person();
var dana  = new Person();

diva(jimmy);
diva(dana);

jimmy
  .jog('10mph')
  .stopJogging()
  .pause(10000)
  .walk('2 miles')
  .send(dana)
  .after('stopJogging', function(result) {
    return new Promise(function(resolve, reject) {
      jimmy
        .say('Resting...');
    }
  })
  .jog('10mph')
  .run()
 ...

dana
  .study()
  .pause(2000)
  .onReceipt(function(msg) {

    dana
      .say('How many miles did jimmy jog?')
      .say(msg);

  })
  .pause(4000)
  .run()

More generally, expanding this module with other popular modules like request can create simple and expressive client side modules for interacting with apis.


client
  request('www.somesite.com/api/get/5')
  parse()
  save(__dirname + '/people')

The module depends on RSVP, but any promise library including native ES6 Promises should work.

$ npm install diva

Initialization

Use diva() to add the Diva skeleton to the class:

var diva = require('diva');

var Person = function() {
  this.name = 'Name';
}

diva(Person);

that.queue( fn )

Description

Creates a function to create a promise in the internal queue. Use with prototypes to create chainable waterfall promises.

that.queue(function <name>(result) {
  return new Promise(function (resolve, reject)) {

  //logic goes here
});

Promise

Description

Expose the rsvp Promise object

var Promise = require('diva').Promise

run

Description

Run the current queue, passing in a value to the first method in the chain.

.run([value])

stop

Description

Stop running the queue.

.stop()

empty

Description

Empty the current queue.

.empty()

before, after

Description

Add a promise before or after every time a particular method is called in the chain

.after(<name>, function(result) {
  return new Promise(function (resolve, reject) {
    //logic here
    resolve(<waterfall value>);
  });
})

set

Description

Set the waterfall value as a property of the diva object (for later reference.) If a value is spacified, then that value will be set and passed down the waterfall.

.set(<name>, [value])
Description

Get a property of the diva object and send it down the waterfall

.get(<name>)
Description

Get and remove a property of the diva object and send it down the waterfall

.remove(<name>)
Description

Display the current waterfall value or a string. The current waterfall value passes through in either case.

.display(<string>)
Description

Pause the chain for a certain amount of time

.pause(<time>)
Description

Change the waterfall value

.change(<value>)

send

Description

Send the current value (or a specified message) to another diva chain that will receive the message with onReceipt (it does not have to be a diva object)

.change(<receiver>, [message])

mail

Description

Mail a current value to another diva chain that will receive the message and put it in its mailbox

.change(<receiver>, [message])

onReceive( fn(msg) { })

Description

Receive the value from a sender. Execute immediately, or call diva methods from the callback and run to run synchronously after the current queue.

isRunning()

Description

Returns true if the diva object is running a queue

retrieve()

Description

Pull the bottom (oldest) x values out of the mailbox

draw()

Description

Pull the top (recent) x values out of the mailbox

Example Usage

var request = require('request')
  , diva    = require('../index')
  , Promise = require('rsvp').Promise
  , fs      = require('fs')

Create any type of "object"

var Person = function() { }

Add the diva prototypes to the object type.

Person = diva(Person);

Create methods with a specific signature:

  var that = this;
  return that.queue(function <name>(result) {
    return new Promise(function (resolve, reject)) {

    resolve(<value-to-pass>)
    });
  });

Chain methods together and send messages to other diva objects (or any message handler)


john.name = 'john'
mary.name = 'mary'

var end = {
  onReceive: function(msg) {
    console.log("***End Scene***")
  }
}

john
  .display()
  .send(mary, "Mary I am going to the store for 10 seconds.")
  .goToStore()
  .set('location')
  .pause(10000)
  .mail(mary, "(Mail) John->Mary: I'm not coming home for another 10 seconds")
  .pause(10000)
  .recieve(function onReceive(msg) {
    if(msg === 'Where are you John?') {
      console.log('John: I am at the ' + this.location)
    }

    this
      .empty()
      .display('John: What a nag...')
      .send(end)
      .run()
   })
  .display("John: I'm back!!!")
  .run('Actor: John')
  .display('Will not show up')

mary
  .display()
  .pause(2000)
  .display('**Mary is twiddling her thumbs**')
  .pause(15000)
  .display('Mary: John is not back yet')
  .display('Mary: Let me ask where he is.')
  .send(john, 'Where are you John?')
  .display("Mary: Why don't I check the mail...")
  .retrieve()
  .display()
  .after('display', function onAfter(result) {
    return new Promise(function (resolve, reject) {
      console.log('(Mary talks a lot)');
      resolve(result);
    });
   })
  .google('google')
  .save(__dirname + '/test.txt')
  .recieve(function(msg) {
    console.log('John->Mary: ' + msg);
  })
  .display('((Sleep))')
  .run('Actor: Mary')
  .display('Will show up')
  .run()
  .error( function(msg) {
      console.log(msg)
  })

console.log('***Begin Scene***')