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

cantina

v4.2.0

Published

An application bootstrapper and plugin framework.

Downloads

40

Readme

Cantina

A node.js application framework that leverages the power of a shared event emitter, a simple plugin pattern, and a flexible configuration engine.

Current Version: 4.x

Example

var app = require('cantina').createApp();

// Boot the application
// --------------------
// 1. Locates your application root directory (so plugins can reference it).
// 2. Creates an `etc` configuration object and loads configuration from a
//    variety of default sources.
// 3. Loads default core plugin(s): utils
app.boot(function(err) {
  // Handle load errors.
  if (err) return console.log(err);

  // Optionally, add default configuration.
  // (a better practice is to put your configuration in `./etc/conf.json`)
  app.conf.add({
    http: {
      host: 'localhost',
      port: 8080
    },
    static: {
      path: './public'
    },
    myplugin: {
      time: 5000
    }
  });

  // Handle errors.
  app.on('error', function(err) {
    // Save the error to your logs or something.
  });

  // Load plugins
  // ------------
  // To load a 'plugin', use app.require().
  //
  // For example, load the cantina-web plugins like so:
  app.require('cantina-web');

  // Loaders
  // -------
  // Cantina provides an api for registering and calling 'loader' methods.
  // 'Loaders' generally require modules from a folder and make them available
  // in some way.  For example, cantina provides a 'plugins' loader that loads
  // all the modules in the 'plugins/' directory.
  app.load('plugins');

  // Start the application
  // ---------------------
  // 1. Runs all 'start' hooks asynchronously, in series.
  // 2. Runs all 'started' hooks asynchronously, in parallel.
  // 3. Optionally, you can respond to initialization errors with a callback.
  app.start();
});

Plugins

Cantina plugins get access to the app object and can extend or use apis attached to it. Plugins can really do whatever they want, however, there are a few conventions that can be followed in order to cooperate with the application initialization process.

Example Plugin

module.exports = function (app) {

  // Add some default configuration options.
  app.conf.add({
    square: {
      color: 'red',
      height: 200
    },
    circle: {
      color: 'blue',
      radius: 4
    }
  });

  // Expose data or an API on the app.
  app.shapes = {
    squares: [],
    circles: []
  };

  // Bind to application events, such as 'error', or custom ones that your
  // application uses.
  app.on('create:circle', function(options) {
    var defaults = app.conf.get('circle');
    var circle = {
      color: options.color || defaults.color,
      radius: options.radius || defaults.radius
    };
    app.shapes.circles.push(circle);
  });

  // Add a 'start' hook.
  // Hooks run asynchronously, so if you setup requires hitting a database or doing
  // other asynchronous work, you should do that here.
  app.hook('start').add(function (next) {
    app.db.loadCircles(function(err, circles) {
      if (err) return next(err);
      circles.forEach(function(circle) {
        app.emit('create:circle', circle);
      });
      next();
    });
  });

  // Add a 'destroy' hook.
  app.hook('destroy').add(function (next) {
    // Clean-up if the app is destroyed.
    next();
  });
};

Configuration

An important function of Cantina is to centralize your app's configuration.

Cantina delegates to node-etc to handle many different configuration sources. When you call app.boot() the following sources will be automatically checked and loaded (by order of precedence):

  1. argv - Command-line arguments parsed by optimist.
  2. env - Environment variables that match the prefix: 'app_'
  3. ./etc/ - JSON, JS, and YAML files in [app root]/etc will be parsed and added to the config. If the filename is config.* then the contents will be merged in at the root level of the config. Any other files are assumed to be plugin specific and will be merged into conf keyed by filename.
  4. package.json - If your package.json contains an etc key it will be merged into the conf.

After app.boot() has finished, you can add more configuration either in your application or in plugins via app.conf.add, app.conf.set, or any other means of adding configuration that etc exposes.

Most applications should just store their configuration in ./etc and rely on plugin defaults and argv for the rest.

Events and Hooks

Events and hooks should be your go-to solutions for organizing and implementing application logic. Use app.on() and app.emit() when you want to deal with synchronous tasks. app.hook() exposes an api for registering asynchronous tasks. It is powered by stact-hooks.


Developed by Terra Eclipse

Terra Eclipse, Inc. is a nationally recognized political technology and strategy firm located in Santa Cruz, CA and Washington, D.C.