beat

Simple dependency injection for node

beat

Simple dependency injection for node

Enjoy also beat-conf, lean configuration utility for Beat

var Beat = require('beat');
var app = new Beat('app');
 
app.value('port', process.env.PORT || 3000);
app.value('express', require('express'));
  
app.factory('app', function(express){
  return express();
});
  
app.run(function(appport){
  app.get('/hello.txt', function(reqres){
    res.send('Hello World');
  });
  app.listen(port);
  console.log('Express running at :'+port);
});

Install it with NPM:

npm install --save beat

Then require it:

var Beat = require('beat');

constructor(alias): starts a new Beat with an alias (defaults to "unnamed")

To produce the instance, Beat should be called with new operator.

var myServer = new Beat('server');

value(token, value): defines a value for injection

Register the final value.

myServer.value('port', 80);

factory(token, factoryFn): defines a factory for injection

To produce the instance, factoryFn will be called once (with instance context) and its result will be used.

The factoryFn function can use injection annotation.

myServer.factory('port', function(){
  var port = 80;
  // some logic here 
  return port;
});

run(fn): runs a code block, with injection

fn will be called (with instance context).

The fn function can use injection annotation.

myServer.run(function(serverport){
  server.listen(port);
});

get(token): obtains a property

myServer.value('port', 80);
var port = myServer.get('port');

load(beatInstance): import properties and factories from an Beat instance

Useful to bind different beats

var config = new Beat('config');
config.value('port', 80);
 
myServer.load(config);
myServer.run(function(appport){
  app.listen(port);
});

or at different files

var config = module.exports = new Beat('config');
config.value('port', 80);
myServer.load(require('./config'));
myServer.run(function(appport){
  app.listen(port);
});

Methods run and factory can recieve annotated functions as arguments, that will be used for injection.

The injector looks up tokens based on argument names:

myServer.run(function(serverport) {
  // will inject objects bound to 'server' and 'port' tokens 
});

You can also use a array:

myServer.run(['http', 'serverPort', function(serverport) {
  // will inject objects bound to 'http' and 'serverPort' tokens 
}]);

Beat instantiation can declare modules as dependencies.

Therefore, declare them as array at constructor second parameter:

var Beat = require('beat');
var db = module.exports = new Beat('db', ['mongoose']);
 
db.factory('db', function(mongooseconf) {
  if(conf.env == 'test')
    mongoose.set('debug', true);
  return mongoose.createConnection(conf.mongo).once('open', function() {
    console.log('Mongoose connected');
  });
});

You can also use objects for aliasing:

var Beat = require('beat');
var db = module.exports = new Beat('db', ['mongoose', {conf:'../config.json'}]);
 
db.factory('db', function(mongooseconf) {
  if(conf.env == 'test')
    mongoose.set('debug', true);
  return mongoose.createConnection(conf.mongo).once('open', function() {
    console.log('Mongoose connected');
  });
});

file paths starting with / will be relative to process cwd.

If the required module provides a Beat object, their properties will be mixed with local ones:

var Beat = require('beat');
var routes = module.exports = new Beat('routes', [
  '/lib/middlewares',
  '/lib/models',
  '/lib/app'
]);
 
routes.factory('routes', function routes(appauthMiddlewareProductsModel){
  app.all('/api/*', authMiddleware);
  app.get('/api/products/:id', function show(reqres) {
    ProductsModel.findById(req.params.id, function(errdoc) {
      res.send(err?400:(doc||404));
    });
  });
});

Is also possible to load dependencies after construction, with the same sintax:

var Beat = require('beat');
var routes = module.exports = new Beat('routes');
 
routes.loadModules([
  '/lib/middlewares',
  '/lib/models',
  '/lib/app'
]);

Angular.js DI