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

dualapi

v1.3.1

Published

Framework for distributed javascript applications

Downloads

7

Readme

DualAPI Build Status

A lightweight and extensible framework for distributed isomorphic javascript applications. DualAPI extends dual-protocol, adding convenience functions and default behaviors for common messaging patterns.

For a simple example distributed example, see the dual-engine.io example.

Constructing domains

The dualapi module is the constructor for dualapi domains.

  var d = require('dualapi')();

The most common use case for dualapi domains is to provide a listener function for processing dual-protocol messages. Hosts are attached to the domain by using the dual-protocol mount method:

  d.mount(['unresponsive'], function (body, ctxt) {
    // do some processing
  });

Request and Return

Often, a dualapi host will emit a response after processing input. dualapi provides a convienent extension to dual-protocol by providing the ctxt.return method.

  d.mount(['simpledb', 'get'], function (body, ctxt) {
    ctxt.return('the processed response');
  });

By default, return sets the returned options.statusCode to 200. Then, any method having access to a connected domain may request data from this address. The request method returns a spreadable promise which will be resolved when the source host replies:

  d.request(['simpledb', 'get'])
    .spread(function (body, options) {
       console.log(options.statusCode + ' ' + body);
    });

   // prints:
   // "200 the processed response"

A smarter database can override the response statusCode by providing explicit options.

  var db = {};
  d.mount(['smarterdb', 'set', ':key'], function (body, ctxt) {
    if (db.hasOwnProperty(ctxt.params.key)) {
       ctxt.return('Conflict', { statusCode: 409 });
    } else {
       db[ctxt.params.key] = body;
       ctxt.return('OK', { statusCode: 201 });
    }
  });

  d.mount(['smarterdb', 'get', ':key'], function (body, ctxt) {
    if (db.hasOwnProperty(ctxt.params.key)) {
       ctxt.return(db[ctxt.params.key]);
    } else {
       ctxt.return('Not Found', { statusCode: 404 });
    }
  });

A client can use the enhanced status codes to modify its own response:


  d.request(['smarterdb', 'get', 'bucket'])
      .spread(function (body, options) {
         if (options.statusCode == 200) {
            console.log('' + options.statusCode + ' Request returned: ' + body);
         } else {
            console.log('' + options.statusCode + ' Failed to retrieve from bucket.');
         }
      });
      
  d.request(['smarterdb', 'set', 'bucket'], 'an egg')
      .spread(function (body, options) {
         if (options.statusCode == 201) {
            console.log('' + options.statusCode + ' Wrote to bucket');
         } else {
            console.log('' + options.statusCode + ' Failed to write to bucket.');
         }
      });

  d.request(['smarterdb', 'get', 'bucket'])
      .spread(function (body, options) {
         if (options.statusCode == 200) {
            console.log('' + options.statusCode + ' Second request got: ' + body);
         } else {
            console.log('' + options.statusCode + ' Second request failed to retrieve bucket.');
         }
      });

  // Running this the first time would print:
  // 404 Failed to retrieve from bucket
  // 201 Wrote to bucket
  // 200 Second request got: an egg

  // Running a second time would print:
  // 200 Request returned: an egg
  // 409 Failed to write to bucket.
  // 200 Second request got: an egg

On the other hand, if no host is listening at the requested address, request will return with a status code of 503. The request may also provide a timeout option, in which case the status code will be 504.

d.request(['nowhere'])
    .spread(function (body, options) {
        console.log('"nowhere" request returned status code ' + options.statusCode);
    });

// would print
// "nowhere" request returned status code 503

d.request(['unresponsive'], null, { timeout: 1 })
    .spread(function (body, options) {
        console.log('"unresponsive" request returned status code ' + options.statusCode);
    });

// would print (after 1 second delay)
// "unresponsive" request returned status code 504

Forward

To be written.

Proxy

To be written.

Error

To be written.