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();
app.boot(function(err) {
if (err) return console.log(err);
app.conf.add({
http: {
host: 'localhost',
port: 8080
},
static: {
path: './public'
},
myplugin: {
time: 5000
}
});
app.on('error', function(err) {
});
app.require('cantina-web');
app.load('plugins');
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) {
app.conf.add({
square: {
color: 'red',
height: 200
},
circle: {
color: 'blue',
radius: 4
}
});
app.shapes = {
squares: [],
circles: []
};
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);
});
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();
});
});
app.hook('destroy').add(function (next) {
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):
- argv - Command-line arguments parsed by optimist.
- env - Environment variables that match the prefix: 'app_'
- ./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. - 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.
Terra Eclipse, Inc. is a nationally recognized political technology and
strategy firm located in Santa Cruz, CA and Washington, D.C.