Magnum DI
A super simple Scoped Dependency Injection framework for NodeJS
npm install --save magnum-di
//Load it up./
var injector = require('magnum-di')()
//Register some dependencies.
injector.service('MyService', {name: 'Bob', sayName: function(){console.log(this.name)}})
//inject them into your function
injector.inject(function(MyService){
MyService.sayName() // -> Bob
})
Why Dependency Injection?
- Managing complex applications with many files. Maintaining module dependencies in one location reduces errors and makes an application easier to reason about.
- Procedurally loading files with dependencies becomes much easier.
- Ease of testing in isolation, mocking module dependencies becomes trivial. No need to use a module to fiddle with the internals of require to get a mocked object into your module. With DI just register a different module with the correct methods and you are done mocking.
Examples
Express route definitions.
Here we register a dependency in our main application file, and use the injector to call the function returned by the require('./UserModel) call.
Run this with npm run example-server
//userRoutes.js
module.exports = function(Router, User) {
//Here Router and User will be injected.
Router.get('/', function(req, res, next){
User.userDetails('Bob', function(err, data){
res.json({user: data})
})
});
return {path: '/user', router: Router}
};
//app.js
var injector = require('magnum-di')();
var express = require('express');
var Database = require('./Database');
var app = express()
var http = require('http');
//Register some dependencies.
injector.factory('Router', express.Router);
injector.service('Database', Database);
//Here we are letting the injector provide the database to our UserModel
//This will make it simple to mock in our unit tests.
var User = injector.inject(require('./UserModel'));
injector.service('User', User);
var userRoute = injector.inject(require('./UserRoutes'));
app.use(userRoute.path, userRoute.router);
http.createServer(app).listen(8080);
Mocking database for testing
Following our above example, we use magnum-di to mock out our Database object for testing.
Run this with npm run example-test
var injector = require('magnum-di');
var should = require('should');
//Our mock database object
injector.service('Database', {
User: {
users: {George: {name: 'George', age: 30}, Mike: {name: 'Mike', age: 20}},
find: function(username, cb) {
var user = (this.users[username]) ? this.users[username] : null
cb(null, user);
}
}
});
//We now have a user model that is using our mock database.
var User = injector.inject(require('./UserModel'));
describe('Model being tested with a mock Database object', function() {
it('should not have real data', function(done) {
User.userDetails('Bob', function(err, data){
should(data).be.null
done()
})
});
it('should have mock data', function(done) {
User.userDetails('George', function(err, data){
data.age.should.equal(30)
done()
})
});
});
API
MagnumDI
Kind: global class
-
MagnumDI
- new MagnumDI()
-
.createChild() ⇒
MagnumDI
-
.service(name, item) ⇒
*
-
.instance(name, fn) ⇒
function
-
.factory(name, fn) ⇒
function
-
.merge(name, merge) ⇒
*
-
.get(name) ⇒
*
|null
-
.replace(name, replacement) ⇒
Object
-
.unregister(name) ⇒
boolean
-
.inject(fnOrstr, thisArg) ⇒
*
new MagnumDI()
Provides an instance of the Magnum DI injector.
MagnumDI
magnumDI.createChild() ⇒ Creates a Child instance of the current injector. Calls to .get or .inject will first search this injector, if a parameter is found it will return it if not it will continue up the tree until a value is found or the topmost instance is reached.
Kind: instance method of MagnumDI
*
magnumDI.service(name, item) ⇒ Registers an object, string, number or function.
Kind: instance method of MagnumDI
Returns: *
- Returns provided dependency
Param | Type | Description |
---|---|---|
name | string |
Name to be used in the injected function |
item |
object | array | number | string | function
|
Item to be injected. |
function
magnumDI.instance(name, fn) ⇒ When injected, calls as a constructor with new.
Kind: instance method of MagnumDI
Returns: function
- Returns provided function
Param | Type | Description |
---|---|---|
name | string |
Name to be used in the injected function. |
fn | function |
Function to be called with new. |
function
magnumDI.factory(name, fn) ⇒ When injected, calls the passed function. Returns the result of that call.
Kind: instance method of MagnumDI
Returns: function
- Retuens provided function.
Param | Type | Description |
---|---|---|
name | string |
Name to be used in the injected function |
fn | function |
Function to be called by injector. |
*
magnumDI.merge(name, merge) ⇒ Merges supplied object into the object registered for , if doesn't exist it will be created.
Kind: instance method of MagnumDI
Returns: *
- Returns provided dependency
Param | Type | Description |
---|---|---|
name | String |
Dependency object to modify |
merge | Object |
Object to merge with existing dependency |
*
| null
magnumDI.get(name) ⇒ Returns the specified dependency.
Kind: instance method of MagnumDI
Returns: *
| null
- The named dependency item, or null.
Param | Type | Description |
---|---|---|
name | string |
Dependency to retrieve. |
Object
magnumDI.replace(name, replacement) ⇒ Modifies a registered service object.
Kind: instance method of MagnumDI
Returns: Object
- Replaced dependency
Param | Type | Description |
---|---|---|
name | String |
Dependency object to modify. |
replacement | Object |
Object to replace current registered object. |
boolean
magnumDI.unregister(name) ⇒ Removes the specified dependency.
Kind: instance method of MagnumDI
Returns: boolean
- The result of the operation.
Param | Type | Description |
---|---|---|
name | string |
Registered dependency to remove. |
*
magnumDI.inject(fnOrstr, thisArg) ⇒ Runs the given function with args injected and with an optional context object.
Kind: instance method of MagnumDI
Returns: *
- Returns the result of the called function.
Param | Type | Description |
---|---|---|
fnOrstr |
function | string
|
function - inject args and run, string - Return the named dependency. |
thisArg | object |
Calling context. |
Contributing
Check out, add, document, test.
Run tests with npm test
.
Regenerate this Readme with npm run readme