Noder.io provides a lightweight and flexible core to create a scalable API of a lib, a module, an application or a framework. Noder.io is inspired (among others) by Angular and Pimple.
It is useful for starting a project quickly with a modular API ready to use.
Noder.io (and any object built on top of Noder.io) integrates dependency injection, lazy loading and is extensible via a plugins system easy to use.
No dependencies, works on Node.js and in the browser (only 7kb).
Installation
For Node.js
You can install Noder.io with NPM (Node Package Manager).
npm install noder.io
For the browser
Although originally designed for use with Node.js, it can also be used directly in the browser (only 7kb).
Usage
var noder = require('noder.io');
Best practice, create an instance of Noder
class:
// ./api/index.js
var Noder = require('noder.io').Noder;
var api = new Noder();
// code body that constructs your API
module.exports = api;
or shortcut:
// ./api/index.js
module.exports = require('noder.io').createNoder();
Use your API in another file:
var api = require('./api');
// load a plugin
api.use('pluginName');
// create an item in the container
api.$di.set('someItem', 'value of the item');
// ...
Collection
// create a collection
var items = noder.createCollection();
items.set('myKey', 'my key value');
// my key value
console.log(items.get('myKey'));
// get all items
var all = items.getAll();
// true
console.log(items instanceof noder.Collection);
See collection.
Dependency Injection
See dependency injection.
Lazy loading
noder.$require
method provides a lazy require()
:
// define the property without loading the mongoose module
noder.$require('mongoose');
// false
console.log(noder.$require.isLoaded('mongoose'));
// lazy loading
var mongoose = noder.mongoose;
// true
console.log(noder.$require.isLoaded('mongoose'));
// true
console.log(noder.mongoose === require('mongoose'));
Aliases:
noder.$require('promise', 'bluebird');
// true
console.log(noder.promise === require('bluebird'));
Custom loader:
// factory: promisify the "fs" module
noder.$require('fs', function() {
return noder.promise.promisifyAll(require('fs'));
});
fs.readFileAsync('./any-file.js')
.then(function(contents) {
console.log(contents);
})
.catch(function(err) {
console.error(err);
})
;
See lazy loading.
Plugins
Noder.io provides a plugin system to make a package works as a plugin for Noder.io and also as a standalone module or library.
Example of a Noder plugin:
/**
* Initialization for use as a standalone module.
* @return {Noder} New `Noder` instance
*/
module.exports = function blog() {
var Noder = require('noder.io').Noder;
var noder = new Noder();
// or use the shortcut:
// var noder = require('noder.io').createNoder();
return module.exports.__noder(noder);
};
/**
* Init `blog` plugin.
* @param {Noder} noder `Noder` instance
* @return {Noder} Current `Noder` instance
*/
module.exports.__noder = function blogPlugin(noder) {
// create config object only if not exists
noder.$di.addOnce('config', {}, true);
// sub-modules of blogPlugin
// that add features to the instance of Noder
noder.use(require('./api/article'));
noder.use(require('./api/comment'));
noder.use(require('./api/admin'));
// Always return the instance of Noder to allow chaining
return noder;
};
See plugins.
Example
Here is an example that could be a real case.
File: ./api/config
module.exports.__noder = function config(noder) {
noder.$di.set('config' {
connection: 'mongodb://localhost/blog',
post: {
limit: 20
}
});
return noder;
}
File: ./api/db.js
var Post = require('../models/post.js');
module.exports.__noder = function db(noder) {
// define custom loader
noder.$require('mongoose', function() {
var mongoose = require('mongoose');
// note: `this` === `noder.$di._container`
this.connectMongoose(mongoose);
return mongoose;
});
// define a singleton
noder.$di.singleton('connectMongoose', function connectMongoose(mongoose) {
return mongoose.connect(noder.$di.get('config').connection);
};
// define a helper
noder.$di.set('getPosts', function getPosts(callback) {
var config = noder.$di.get('config');
return Post
.find({published: true})
.sort({'date': -1})
.limit(config.post.limit)
.exec(callback);
};
return noder;
};
File: ./api/index.js
// module.exports is a singleton
module.exports = require('noder.io').createNoder();
File: ./app.js
var api = require('./api');
// define lazy loader with alias
api.$require('markdown', 'marked');
// init config
api.use('./api/config');
// init DB dependencies
api.use('./api/db');
// init blog dependencies
api.use('./api/blog');
// invoke the dependencies injected as arguments
api.$invoke(['view', 'getPosts'], function(view, getPosts) {
getPosts(function(err, posts) {
// `posts` will be of length 20 (see `config` object)
for(var i in posts) {
// parse markdown of each posts
posts[i].contents = api.markdown(posts[i].contents);
}
// render posts
view.render(posts);
});
});
// another way, use the dependencies in the scope (`this`)
api.$apply(function() {
this.getPosts(function(err, posts) {
// `posts` will be of length 20 (see `config` object)
for(var i in posts) {
// parse markdown of each posts
posts[i].contents = api.markdown(posts[i].contents);
}
// render posts
this.view.render(posts);
});
})
The workflow may be easier but it's to show an example using several things at once.
With a small modification, we could also obtain this way, file: ./app.js
var db = api.db;
db.connectMongoose();
// invoke this function with the dependency injected as argument
db('getPosts', function(getPosts) {
getPosts(function(err, posts) {
// `posts` will be of length 20 (see `config` object)
api.view('blog/posts', err, posts);
});
});
Free rein to your imagination and your favorites good practices :)
Learn
The learning curve to be productive with Noder.io is very short. The guide presents you a quick tour of some features of Noder.io, the API is fully documented.
I suggest you read the few pages of this guide in order to know and to effectively exploit the capabilities provided by Noder.io.
Try to handle the noder.$di
container, creates a service, try the dependency injection, creates a plugin ("hello world"). And go start your next project with Noder.io :)
The concrete practice is the best for learning quickly!
Related
Unit Tests
Noder.io is tested with Unit.js and Mocha.
Unit.js is a powerful and intuitive unit testing framework for Node.js and also for javascript in the browser. The core of Unit.js is built on top of Noder.io.
It's a unit testing framework that provides a awesome implementation of Noder.io with dependency injection in the scope (this
) of some BDD methods (given(), when(), then(), ... ), the plugin system and all features of Noder.io!
License
MIT (c) 2013, Nicolas Tallefourtane.
Author
Noder.io is designed and built with love by Nicolas Tallefourtane.