Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
emonkak committed Jul 23, 2015
0 parents commit b4aa8d1
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules
npm-debug.log
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: node_js
node_js:
- "0.12"
- "0.11"
after_script: "npm run-script coveralls"
sudo: false
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# di.js

[![Build Status](https://travis-ci.org/emonkak/di.js.svg?branch=master)](https://travis-ci.org/emonkak/di.js)
[![Coverage Status](https://coveralls.io/repos/emonkak/di.js/badge.svg?branch=master&service=github)](https://coveralls.io/github/emonkak/di.js?branch=master)
3 changes: 3 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var Injector = require('./injector')

module.exports = Injector
6 changes: 6 additions & 0 deletions lib/inject.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function inject(injector, definition) {
var args = definition.deps.map(injector.resolve, injector)
return definition.factory.apply(null, args)
}

module.exports = inject
77 changes: 77 additions & 0 deletions lib/injector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
var prototypeScope = require('./prototype-scope')

/**
* @class
*/
function Injector() {
this.definitions = new Map()
}

/**
* Defines a dependency definition with a factory.
*
* @param {Object} target
* @param {Array.<Object>} deps
* @param {?Function} factory
* @param {?Function} scope
*/
Injector.prototype.define = function(target, deps, factory, scope) {
this.definitions.set(target, {
target: target,
deps: deps,
factory: factory,
scope: (scope || prototypeScope)()
})
return this
}

/**
* Defines a dependency definition with a class.
*
* @param {Object} target
* @param {Array.<Object>} deps
* @param {?Function} scope
*/
Injector.prototype.defineClass = function(target, deps, scope) {
function classFactory() {
var instance = Object.create(target.prototype)
target.apply(instance, arguments)
return instance
}

return this.define(target, deps, classFactory, scope)
}

/**
* Defines a dependency definition with a function.
*
* @param {Object} target
* @param {Array.<Object>} deps
* @param {?Function} scope
*/
Injector.prototype.defineFunction = function(target, deps, scope) {
function functionFactory() {
var klass = Function.prototype.bind.apply(target, arguments)
return target.apply(null, arguments)
}

return this.define(target, deps, functionFactory, scope)
}

/**
* Resolves the dependencies for given object.
*
* @param {Object} target
* @return {Object}
*/
Injector.prototype.resolve = function(target) {
if (!this.definitions.has(target)) {
throw "Can't resolve dependencies for given object: " + target
}

var definition = this.definitions.get(target)

return definition.scope(this, definition)
}

module.exports = Injector
7 changes: 7 additions & 0 deletions lib/prototype-scope.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var inject = require('./inject')

function prototypeScope() {
return inject
}

module.exports = prototypeScope
11 changes: 11 additions & 0 deletions lib/singleton-scope.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var inject = require('./inject')

function singletonScope() {
var instance = null

return function getInstance(injector, definition) {
return instance = instance || inject(injector, definition)
}
}

module.exports = singletonScope
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "@emonkak/di",
"version": "1.0.0",
"description": "A lightweight dependency injector",
"main": "lib/index.js",
"repository": {
"type": "git",
"url": "git://github.com/emonkak/di.js.git"
},
"scripts": {
"test": "mocha",
"coveralls": "YOURPACKAGE_COVERAGE=1 mocha --require blanket --reporter mocha-lcov-reporter | coveralls"
},
"author": "Shota Nozaki",
"license": "MIT",
"devDependencies": {
"blanket": "^1.1.7",
"coveralls": "^2.11.3",
"expect.js": "^0.3.1",
"mocha": "^2.2.5",
"mocha-lcov-reporter": "0.0.2"
},
"config": {
"blanket": {
"pattern": "lib"
}
}
}
49 changes: 49 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
var expect = require('expect.js')
var Injector = require('../lib/')
var singletonScope = require('../lib/singleton-scope')

describe('Injector', function() {
function Foo(bar, baz) {
this.bar = bar
this.baz = baz
}

function Bar(qux, quux) {
this.qux = qux
this.quux = quux
}

function Baz(qux, quux) {
this.qux = qux
this.quux = quux
}

function Qux() {}

function Quux() {}

var injector = new Injector()
.defineClass(Foo, [Bar, Baz])
.defineClass(Bar, [Qux, Quux])
.defineClass(Baz, [Qux, Quux])
.defineClass(Qux, [], singletonScope)
.defineClass(Quux, [])

it('should be resolved dependencies', function() {
var foo = injector.resolve(Foo)

expect(foo).to.be.a(Foo)
expect(foo.bar).to.be.a(Bar)
expect(foo.bar.qux).to.be.a(Qux)
expect(foo.bar.quux).to.be.a(Quux)
expect(foo.baz).to.be.a(Baz)
expect(foo.baz.qux).to.be.a(Qux)
expect(foo.baz.quux).to.be.a(Quux)

expect(foo.bar.qux).to.be(foo.baz.qux)
expect(foo.bar.quux).not.to.be(foo.baz.quux)

expect(foo.bar.qux).to.be(injector.resolve(Qux))
expect(foo.bar.quux).not.to.be(injector.resolve(Quux))
})
})

0 comments on commit b4aa8d1

Please sign in to comment.