Comparing version 1.0.0 to 1.0.1
/** | ||
* inversify v.0.0.7 - A lightweight IoC container written in TypeScript. | ||
* inversify v.1.0.0 - A lightweight IoC container written in TypeScript. | ||
* Copyright (c) 2015 Remo H. Jansen | ||
@@ -7,2 +7,2 @@ * MIT inversify.io/LICENSE | ||
*/ | ||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;n="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,n.inversify=e()}}(function(){return function e(n,t,i){function r(f,p){if(!t[f]){if(!n[f]){var u="function"==typeof require&&require;if(!p&&u)return u(f,!0);if(o)return o(f,!0);var s=new Error("Cannot find module '"+f+"'");throw s.code="MODULE_NOT_FOUND",s}var c=t[f]={exports:{}};n[f][0].call(c.exports,function(e){var t=n[f][1][e];return r(t?t:e)},c,c.exports,e,n,t,i)}return t[f].exports}for(var o="function"==typeof require&&require,f=0;f<i.length;f++)r(i[f]);return r}({1:[function(e,n,t){var i=e("./kernel"),r=e("./type_binding"),o=e("./type_binding_scope"),f={Kernel:i,TypeBindingScopeEnum:o,TypeBinding:r};n.exports=f},{"./kernel":2,"./type_binding":3,"./type_binding_scope":4}],2:[function(e,n,t){var i=(e("./type_binding_scope"),function(){function e(){this._bindings=new Object}return e.prototype.bind=function(e){this._validateBinding(e)===!0&&(this._bindings[e.runtimeIdentifier]=e)},e.prototype.unbind=function(e){var n=this._bindings[e];if("undefined"==typeof n)throw new Error("Could not resolve service "+e);delete this._bindings[e]},e.prototype.unbindAll=function(){this._bindings=new Object},e.prototype.resolve=function(e){var n=this._bindings[e];if("undefined"==typeof n)throw new Error("Could not resolve service "+e);if(1===n.scope&&null!==n.cache)return n.cache;var t=this._injectDependencies(n.implementationType);return n.cache=t,t},e.prototype._validateBinding=function(e){var n=!0;if("string"!=typeof e.runtimeIdentifier){var t="Expected type of "+e.runtimeIdentifier+" to be string";console.log(t),n=!1}if("undefined"!=typeof this._bindings[e.runtimeIdentifier]){var t="Dublicated binding runtime identifier "+e.runtimeIdentifier;console.log(t),n=!1}if("function"!=typeof e.implementationType){var t="Expected "+e.implementationType+" to be a constructor";console.log(t),n=!1}return n},e.prototype._getConstructorArguments=function(e){var n,t,i,r,o,f;return o=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,f=/([^\s,]+)/g,n=e.toString().replace(o,""),t=n.indexOf("(")+1,i=n.indexOf(")"),r=n.slice(t,i).match(f),null===r&&(r=[]),r},e.prototype._injectDependencies=function(e){var n=this._getConstructorArguments(e);if(0===n.length)return new e;for(var t=[],i=null,r=0;r<n.length;r++){var o=n[r];i=this.resolve(o),t.push(i)}return this._construct(e,t)},e.prototype._construct=function(e,n){function t(){e.apply(this,n)}return t.prototype=e.prototype,new t},e}());n.exports=i},{"./type_binding_scope":4}],3:[function(e,n,t){var i=e("./type_binding_scope"),r=function(){function e(e,n,t){if(this.runtimeIdentifier=e,this.implementationType=n,this.cache=null,"undefined"==typeof t)this.scope=0;else{if(!i[t]){var r="Invalid scope type "+t;throw new Error(r)}this.scope=t}}return e}();n.exports=r},{"./type_binding_scope":4}],4:[function(e,n,t){var i;!function(e){e[e.Transient=0]="Transient",e[e.Singleton=1]="Singleton"}(i||(i={})),n.exports=i},{}]},{},[1])(1)}); | ||
!function(n){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.inversify=n()}}(function(){return function n(e,t,i){function r(u,p){if(!t[u]){if(!e[u]){var s="function"==typeof require&&require;if(!p&&s)return s(u,!0);if(o)return o(u,!0);var c=new Error("Cannot find module '"+u+"'");throw c.code="MODULE_NOT_FOUND",c}var f=t[u]={exports:{}};e[u][0].call(f.exports,function(n){var t=e[u][1][n];return r(t?t:n)},f,f.exports,n,e,t,i)}return t[u].exports}for(var o="function"==typeof require&&require,u=0;u<i.length;u++)r(i[u]);return r}({1:[function(n,e,t){var i=n("./kernel"),r=n("./type_binding"),o=n("./type_binding_scope"),u={Kernel:i.Kernel,TypeBinding:r.TypeBinding,TypeBindingScopeEnum:o.TypeBindingScopeEnum};t.inversify=u},{"./kernel":2,"./type_binding":4,"./type_binding_scope":5}],2:[function(n,e,t){var i=n("./type_binding_scope"),r=n("./lookup"),o=function(){function n(){this._bindingDictionary=new r.Lookup}return n.prototype.bind=function(n){this._bindingDictionary.add(n.runtimeIdentifier,n)},n.prototype.unbind=function(n){try{this._bindingDictionary.remove(n)}catch(e){throw new Error("Could not resolve service "+n)}},n.prototype.unbindAll=function(){this._bindingDictionary=new r.Lookup},n.prototype.resolve=function(n){var e;if(!this._bindingDictionary.hasKey(n))return null;e=this._bindingDictionary.get(n);var t=e[0];if(t.scope===i.TypeBindingScopeEnum.Singleton&&null!==t.cache)return t.cache;var r=this._injectDependencies(t.implementationType);return t.cache=r,r},n.prototype._getConstructorArguments=function(n){var e,t,i,r,o,u;return o=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,u=/([^\s,]+)/g,e=n.toString().replace(o,""),t=e.indexOf("(")+1,i=e.indexOf(")"),r="function"==typeof Map&&-1!==e.indexOf("class")&&-1===e.indexOf("constructor")?null:e.slice(t,i).match(u),null===r&&(r=[]),r},n.prototype._injectDependencies=function(n){var e=this._getConstructorArguments(n);if(0===e.length)return new n;for(var t=[],i=null,r=0;r<e.length;r++){var o=e[r];i=this.resolve(o),t.push(i)}return this._construct(n,t)},n.prototype._construct=function(n,e){function t(){n.apply(this,e)}return t.prototype=n.prototype,new t},n}();t.Kernel=o},{"./lookup":3,"./type_binding_scope":5}],3:[function(n,e,t){var i=function(){function n(n,e){this.key=n,this.value=new Array,this.value.push(e)}return n}(),r=function(){function n(){this._hashMap=new Array}return n.prototype.getIndexByKey=function(n){for(var e=-1,t=0;t<this._hashMap.length;t++){var i=this._hashMap[t];i.key===n&&(e=t)}return e},n.prototype.add=function(n,e){if(null===n||void 0===n)throw new Error("Argument Null");if(null===e||void 0===e)throw new Error("Argument Null");var t=this.getIndexByKey(n);if(-1!==t){var r=this._hashMap[t];r.key===n&&r.value.push(e)}else this._hashMap.push(new i(n,e))},n.prototype.get=function(n){if(null===n||void 0===n)throw new Error("Argument Null");var e=this.getIndexByKey(n);if(-1===e)throw new Error("Key Not Found");var t=this._hashMap[e];return t.key===n?t.value:void 0},n.prototype.remove=function(n){if(null===n||void 0===n)throw new Error("Argument Null");var e=this.getIndexByKey(n);if(-1===e)throw new Error("Key Not Found");this._hashMap.splice(e,1)},n.prototype.hasKey=function(n){if(null===n||void 0===n)throw new Error("Argument Null");var e=this.getIndexByKey(n);return-1!==e?!0:!1},n}();t.Lookup=r},{}],4:[function(n,e,t){var i=n("./type_binding_scope"),r=function(){function n(n,e,t){if(this.runtimeIdentifier=n,this.implementationType=e,this.cache=null,"undefined"==typeof t)this.scope=i.TypeBindingScopeEnum.Transient;else{if(!i.TypeBindingScopeEnum[t]){var r="Invalid scope type "+t;throw new Error(r)}this.scope=t}}return n}();t.TypeBinding=r},{"./type_binding_scope":5}],5:[function(n,e,t){var i;!function(n){n[n.Transient=0]="Transient",n[n.Singleton=1]="Singleton"}(i||(i={})),t.TypeBindingScopeEnum=i},{}]},{},[1])(1)}); |
@@ -39,3 +39,3 @@ "use strict"; | ||
noImplicitAny : false, | ||
target : "ES3", | ||
target : "ES5", | ||
module : "commonjs", | ||
@@ -51,5 +51,13 @@ declarationFiles : false | ||
var tsTestProject = tsc.createProject({ | ||
removeComments : false, | ||
noImplicitAny : false, | ||
target : "ES5", | ||
module : "commonjs", | ||
declarationFiles : false | ||
}); | ||
gulp.task("build-test", function() { | ||
return gulp.src(__dirname + "/test/*.test.ts") | ||
.pipe(tsc(tsProject)) | ||
.pipe(tsc(tsTestProject)) | ||
.js.pipe(gulp.dest(__dirname + "/build/test/")); | ||
@@ -114,2 +122,3 @@ }); | ||
gulp.task("cover", function() { | ||
if (!process.env.CI) return; | ||
return gulp.src(__dirname + '/coverage/**/lcov.info') | ||
@@ -116,0 +125,0 @@ .pipe(coveralls()); |
{ | ||
"name": "inversify", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "A lightweight IoC container written in TypeScript.", | ||
@@ -10,3 +10,3 @@ "main": "dist/inversify.js", | ||
"scripts": { | ||
"test": "gulp" | ||
"test": "gulp test" | ||
}, | ||
@@ -36,22 +36,23 @@ "repository": { | ||
"devDependencies": { | ||
"browserify": "^9.0.8", | ||
"chai": "^2.2.0", | ||
"gulp": "^3.8.11", | ||
"gulp-coveralls": "^0.1.3", | ||
"browserify": "^11.0.1", | ||
"chai": "^3.2.0", | ||
"gulp": "^3.9.0", | ||
"gulp-coveralls": "^0.1.4", | ||
"gulp-docco": "0.0.4", | ||
"gulp-header": "^1.2.2", | ||
"gulp-run": "^1.6.7", | ||
"gulp-tslint": "^2.0.0", | ||
"gulp-typescript": "^2.6.0", | ||
"gulp-uglify": "^1.2.0", | ||
"karma": "^0.12.31", | ||
"gulp-header": "^1.7.1", | ||
"gulp-run": "^1.6.10", | ||
"gulp-tslint": "^3.2.0", | ||
"gulp-typescript": "^2.8.2", | ||
"gulp-uglify": "^1.4.0", | ||
"karma": "^0.13.9", | ||
"karma-chai": "^0.1.0", | ||
"karma-coverage": "^0.3.0", | ||
"karma-mocha": "^0.1.10", | ||
"karma-phantomjs-launcher": "^0.1.4", | ||
"karma-coverage": "^0.5.1", | ||
"karma-mocha": "^0.2.0", | ||
"karma-phantomjs-launcher": "^0.2.1", | ||
"karma-sinon": "^1.0.4", | ||
"mocha": "^2.2.4", | ||
"run-sequence": "^1.0.2", | ||
"sinon": "^1.14.1", | ||
"typescript": "^1.5.0-alpha", | ||
"mocha": "^2.3.0", | ||
"phantomjs": "^1.9.18", | ||
"run-sequence": "^1.1.2", | ||
"sinon": "^1.16.1", | ||
"typescript": "^1.6.0-beta", | ||
"vinyl-buffer": "^1.0.0", | ||
@@ -58,0 +59,0 @@ "vinyl-source-stream": "^1.1.0" |
@@ -19,3 +19,3 @@ # InversifyJS | ||
### Motivation | ||
JavaScript applications are becoming larger and larger day after day. As a result we are using a lot of our architecture exprience from languages like Java or C# in JavaScript. We are embracing OOP with JavaScript but we are not writting SOLID JavaScript. InversifyJS has been designed to allow JavaScript developers to write code that adheres to the SOLID principles. | ||
JavaScript applications are becoming larger and larger day after day. As a result we are using a lot of our architecture experience from languages like Java or C# in JavaScript. We are embracing OOP with JavaScript but we are not writing SOLID JavaScript. InversifyJS has been designed to allow JavaScript developers to write code that adheres to the SOLID principles. | ||
@@ -27,9 +27,9 @@ ### Philosophy | ||
2. Facilitate and encourage the adherance to the best OOP and IoC practices. | ||
2. Facilitate and encourage the adherence to the best OOP and IoC practices. | ||
3. Add as litle runtime overhead as possible. | ||
3. Add as little runtime overhead as possible. | ||
# Installation | ||
You can get the latest release using NPM or Bower. | ||
You can get the latest release using npm or bower. The type definitions file can be installed using tsd. | ||
``` | ||
@@ -43,4 +43,7 @@ npm install inversify --save | ||
``` | ||
tsd install inversify --save | ||
``` | ||
# The Basics (with TypeScript) | ||
The main goal of InversifyJS is top allow JavaScript developers to write code that adheres to the SOLID principles. Many of these principles refer to the usage of interfaces. The main reason why it is not possible to write native SOLID JavaScript is becase the language lacks interfaces. In the other hand, TypeScript features interfaces, so, if you are going to use InversifyJS it is recommended to work with TypeScript to get the most out of it. | ||
The main goal of InversifyJS is top allow JavaScript developers to write code that adheres to the SOLID principles. Many of these principles refer to the usage of interfaces. The main reason why it is not possible to write native SOLID JavaScript is because the language lacks interfaces. In the other hand, TypeScript features interfaces, so, if you are going to use InversifyJS it is recommended to work with TypeScript to get the most out of it. | ||
@@ -106,3 +109,3 @@ #### 1. Declare interfaces & implementations | ||
In order to resolve a depencency, the kernel needs to be told which implementation type (classes) to associate with each service type (interfaces). We will use type bindigns for this purpose. A type binding (or just a binding) is a mapping between a service type (an interface), and an implementation type (class). | ||
In order to resolve a dependency, the kernel needs to be told which implementation type (classes) to associate with each service type (interfaces). We will use type bindings for this purpose. A type binding (or just a binding) is a mapping between a service type (an interface), and an implementation type (class). | ||
@@ -127,3 +130,3 @@ ``` | ||
After declaring the type bindigns, we can invoke the kernel resolve method to resolve a dependency. We will use a string as the interface identifier (instead of the interface itself) because the TypeScript interfaces are not available at runtime. | ||
After declaring the type bindings, we can invoke the kernel resolve method to resolve a dependency. We will use a string as the interface identifier (instead of the interface itself) because the TypeScript interfaces are not available at runtime. | ||
@@ -134,3 +137,3 @@ ``` | ||
If the interface that we are tyring to resolve is bind to a class that has some dependencies, InversifyJS will resolve and inject them into a new instance via the class constructor. | ||
If the interface that we are trying to resolve is bind to a class that has some dependencies, InversifyJS will resolve and inject them into a new instance via the class constructor. | ||
@@ -146,7 +149,7 @@ ``` | ||
Invoking resolve everytime we need to inject something, as if it was a Service Locator is an anti-pattern. If we are working with an MVC framweork the composition root should be located in the application class, somewhere along the routing logic or in a controller factory class. Please refer to the integration examples if you need additional help. | ||
Invoking resolve every time we need to inject something, as if it was a Service Locator is an anti-pattern. If we are working with an MVC framework the composition root should be located in the application class, somewhere along the routing logic or in a controller factory class. Please refer to the integration examples if you need additional help. | ||
# Integration with popular frameworks | ||
InversifyJS was designed with many popular JavaScript frameworks in mind. As a result, it is really easy to integrate with existing JavaScript frameworks and examples of integration withmany popular frameworks are available in the [official repository](https://github.com/inversify/Inversify-code-samples). | ||
InversifyJS was designed with many popular JavaScript frameworks in mind. As a result, it is really easy to integrate with existing JavaScript frameworks and examples of integration with many popular frameworks are available in the [official examples repository](https://github.com/inversify/Inversify-code-samples). | ||
@@ -162,3 +165,3 @@ # Good Practices | ||
Invoking resolve everytime we need to inject something, as if it was a Service Locator is an anti-pattern. If we are working with an MVC framweork the composition root should be located in the application class, somewhere along the routing logic or in a controller factory class. | ||
Invoking resolve every time we need to inject something, as if it was a Service Locator is an anti-pattern. If we are working with an MVC framework the composition root should be located in the application class, somewhere along the routing logic or in a controller factory class. | ||
@@ -165,0 +168,0 @@ #### Avoid Constructor over-injection |
@@ -1,2 +0,2 @@ | ||
interface TypeBindingInterface<TServiceType> { | ||
interface ITypeBinding<TServiceType> { | ||
runtimeIdentifier : string; | ||
@@ -8,4 +8,4 @@ implementationType : { new(): TServiceType ;}; | ||
interface KernelInterface { | ||
bind(typeBinding : TypeBindingInterface<any>) : void; | ||
interface IKernel { | ||
bind(typeBinding : ITypeBinding<any>) : void; | ||
unbind(runtimeIdentifier : string) : void; | ||
@@ -15,1 +15,13 @@ unbindAll() : void; | ||
} | ||
interface IKeyValuePair<T> { | ||
key : string; | ||
value : Array<T>; | ||
} | ||
interface ILookup<T> { | ||
add(key : string, value : T) : void; | ||
get(key : string) : Array<T>; | ||
remove(key : string) : void; | ||
hasKey(key : string) : boolean; | ||
} |
@@ -8,12 +8,12 @@ ///<reference path="./interfaces.d.ts" /> | ||
import Kernel = require("./kernel"); | ||
import TypeBinding = require("./type_binding"); | ||
import TypeBindingScopeEnum = require("./type_binding_scope"); | ||
import { Kernel } from "./kernel"; | ||
import { TypeBinding } from "./type_binding"; | ||
import { TypeBindingScopeEnum } from "./type_binding_scope"; | ||
var inversify = { | ||
Kernel : Kernel, | ||
TypeBindingScopeEnum : TypeBindingScopeEnum, | ||
TypeBinding : TypeBinding | ||
TypeBinding : TypeBinding, | ||
TypeBindingScopeEnum : TypeBindingScopeEnum | ||
}; | ||
export = inversify; | ||
export { inversify }; |
@@ -18,15 +18,21 @@ ///<reference path="./interfaces.d.ts" /> | ||
import TypeBindingScopeEnum = require("./type_binding_scope"); | ||
import { TypeBindingScopeEnum } from "./type_binding_scope"; | ||
import { Lookup } from "./lookup"; | ||
class Kernel implements KernelInterface { | ||
declare var Map; | ||
class Kernel implements IKernel { | ||
// The objet properties are used as unique keys type | ||
// bindings are used as values | ||
private _bindings : Object; | ||
private _bindingDictionary : ILookup<ITypeBinding<any>>; | ||
// The class default constructor | ||
constructor() { | ||
this._bindingDictionary = new Lookup<ITypeBinding<any>>(); | ||
} | ||
// Regiters a type binding | ||
public bind(typeBinding : TypeBindingInterface<any>) : void { | ||
if(this._validateBinding(typeBinding) === true){ | ||
this._bindings[typeBinding.runtimeIdentifier] = typeBinding; | ||
} | ||
public bind(typeBinding : ITypeBinding<any>) : void { | ||
this._bindingDictionary.add(typeBinding.runtimeIdentifier, typeBinding); | ||
} | ||
@@ -36,8 +42,8 @@ | ||
public unbind(runtimeIdentifier : string) : void { | ||
var binding = this._bindings[runtimeIdentifier]; | ||
if(typeof binding === "undefined") { | ||
try { | ||
this._bindingDictionary.remove(runtimeIdentifier); | ||
} | ||
catch(e) { | ||
throw new Error(`Could not resolve service ${runtimeIdentifier}`); | ||
} | ||
delete this._bindings[runtimeIdentifier]; | ||
} | ||
@@ -47,3 +53,3 @@ | ||
public unbindAll() : void { | ||
this._bindings = new Object(); | ||
this._bindingDictionary = new Lookup<ITypeBinding<any>>(); | ||
} | ||
@@ -54,8 +60,13 @@ | ||
var binding : TypeBindingInterface<TImplementationType> = this._bindings[runtimeIdentifier]; | ||
if(typeof binding === "undefined") { | ||
throw new Error(`Could not resolve service ${runtimeIdentifier}`); | ||
var bindings : ITypeBinding<TImplementationType>[] | ||
if(this._bindingDictionary.hasKey(runtimeIdentifier)) { | ||
bindings = this._bindingDictionary.get(runtimeIdentifier); | ||
} | ||
else { | ||
return null; | ||
} | ||
// NOTE: this will be remove when contextual binding support is added | ||
var binding = bindings[0]; | ||
// The type binding cache is used t store singleton instance | ||
@@ -72,31 +83,2 @@ if((binding.scope === TypeBindingScopeEnum.Singleton) && (binding.cache !== null)) { | ||
// Validates a type binding | ||
private _validateBinding(typeBinding : TypeBindingInterface<any>) : boolean { | ||
var isValid = true; | ||
// Runtime identifier is a string | ||
if(typeof typeBinding.runtimeIdentifier !== "string") { | ||
var msg = `Expected type of ${typeBinding.runtimeIdentifier} to be string`; | ||
console.log(msg); | ||
isValid = false; | ||
} | ||
// Runtime identifier must be unique | ||
if(typeof this._bindings[typeBinding.runtimeIdentifier] !== "undefined") { | ||
var msg = `Dublicated binding runtime identifier ${typeBinding.runtimeIdentifier}`; | ||
console.log(msg); | ||
isValid = false; | ||
} | ||
// Implementation type must be a constructor | ||
if(typeof typeBinding.implementationType !== "function") { | ||
var msg = `Expected ${typeBinding.implementationType} to be a constructor`; | ||
console.log(msg); | ||
isValid = false; | ||
} | ||
return isValid; | ||
} | ||
// Take a function as argument and discovers | ||
@@ -108,3 +90,3 @@ // the names of its arguments at run-time | ||
// Regular expresions used to get a list containing | ||
// Regular expressions used to get a list containing | ||
// the names of the arguments of a function | ||
@@ -117,4 +99,15 @@ STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; | ||
argsEnd = fnStr.indexOf(')'); | ||
result = fnStr.slice(argsInit, argsEnd).match(ARGUMENT_NAMES); | ||
// If using ES6 classes and there is no constructor | ||
// there is no need to parser constructor args | ||
if('function' === typeof Map && | ||
fnStr.indexOf("class") !== -1 && | ||
fnStr.indexOf("constructor") === -1) { | ||
result = null; | ||
} | ||
else { | ||
result = fnStr.slice(argsInit, argsEnd).match(ARGUMENT_NAMES); | ||
} | ||
if(result === null) { | ||
@@ -147,5 +140,5 @@ result = [] | ||
// Use of .apply() with 'new' operator. Can call any constructor | ||
// except native constructors that behave differently when called | ||
// as functions, like String, Number, Date, etc.) with an array of arguments | ||
// Use of .apply() with 'new' operator. Can call any constructor (except native | ||
// constructors that behave differently when called as functions, like String, | ||
// Number, Date, etc.) with an array of arguments | ||
private _construct<TImplementationType>( | ||
@@ -161,9 +154,4 @@ constr : { new(): TImplementationType ;}, args : Object[]) : TImplementationType { | ||
} | ||
// The class default constructor | ||
constructor() { | ||
this._bindings = new Object(); | ||
} | ||
} | ||
export = Kernel; | ||
export { Kernel }; |
@@ -6,2 +6,2 @@ enum TypeBindingScopeEnum { | ||
export = TypeBindingScopeEnum; | ||
export { TypeBindingScopeEnum }; |
@@ -10,5 +10,5 @@ ///<reference path="./interfaces.d.ts" /> | ||
import TypeBindingScopeEnum = require("./type_binding_scope"); | ||
import { TypeBindingScopeEnum } from "./type_binding_scope"; | ||
class TypeBinding<TServiceType> implements TypeBindingInterface<TServiceType> { | ||
class TypeBinding<TServiceType> implements ITypeBinding<TServiceType> { | ||
@@ -51,2 +51,2 @@ // The runtime identifier used because at runtime we don't have interfaces | ||
export = TypeBinding; | ||
export { TypeBinding }; |
///<reference path="../typings/tsd.d.ts" /> | ||
import inversify = require("../source/inversify"); | ||
import { inversify } from "../source/inversify"; | ||
import { Lookup } from "../source/lookup"; | ||
var expect = chai.expect; | ||
declare var Map; | ||
//****************************************************************************** | ||
@@ -91,2 +94,12 @@ //* MOCKS AND STUBS | ||
it("Throws when invalid scope \n", (done) => { | ||
var runtimeIdentifier = "FooInterface"; | ||
var scopeType = 3; | ||
var fn = function() { | ||
new inversify.TypeBinding<FooInterface>(runtimeIdentifier, Foo, scopeType); | ||
} | ||
expect(fn).to.throw(`Invalid scope type ${scopeType}`); | ||
done(); | ||
}); | ||
}); | ||
@@ -120,15 +133,18 @@ | ||
//var fooBarBinding = new inversify.TypeBinding<FooBarInterface>( | ||
// fooBarRuntimeIdentifier, FooBar, inversify.TypeBindingScopeEnum.Singleton); | ||
var fooBarBinding = new inversify.TypeBinding<FooBarInterface>( | ||
fooBarRuntimeIdentifier, FooBar, inversify.TypeBindingScopeEnum.Singleton); | ||
kernel.bind(fooBinding); | ||
kernel.bind(barBinding); | ||
//kernel.bind(fooBarBinding); | ||
kernel.bind(fooBarBinding); | ||
var fooResult = kernel.resolve<FooInterface>(fooRuntimeIdentifier); | ||
var barResult = kernel.resolve<BarInterface>(barRuntimeIdentifier); | ||
// var fooBarresult = kernel.resolve<FooBarInterface>(fooBarRuntimeIdentifier); | ||
var fooBarresult = kernel.resolve<FooBarInterface>(fooBarRuntimeIdentifier); | ||
// todo assert fooBarresult pedendencies injected correctly | ||
expect(fooBarresult.foo).to.not.be.null; | ||
expect(fooBarresult.bar).to.not.be.null; | ||
expect(fooBarresult.greet()).to.eql("foobar"); | ||
done(); | ||
@@ -138,12 +154,17 @@ }); | ||
it('It should NOT be able to resolve unbound dependencies \n', (done) => { | ||
// todo | ||
done(); | ||
}); | ||
var kernel = new inversify.Kernel(); | ||
var fooRuntimeIdentifier = "FooInterface"; | ||
var barRuntimeIdentifier = "BarInterface"; | ||
it('It should NOT be able to dublicate a type binding \n', (done) => { | ||
// todo | ||
var barBinding = new inversify.TypeBinding<BarInterface>(barRuntimeIdentifier, Bar); | ||
kernel.bind(barBinding); | ||
var foo = kernel.resolve(fooRuntimeIdentifier); | ||
var bar = kernel.resolve(barRuntimeIdentifier); | ||
expect(foo).to.be.null; | ||
expect(bar).to.not.be.null; | ||
done(); | ||
}); | ||
it('It should store ingleton type bindings in cache \n', (done) => { | ||
it('It should store singleton type bindings in cache \n', (done) => { | ||
var kernel = new inversify.Kernel(); | ||
@@ -179,6 +200,13 @@ var runtimeIdentifier = "FooInterface"; | ||
var foo = kernel.resolve(fooRuntimeIdentifier); | ||
var bar = kernel.resolve(barRuntimeIdentifier); | ||
expect(foo).to.not.be.null; | ||
expect(bar).to.not.be.null; | ||
kernel.unbind(fooRuntimeIdentifier); | ||
var foo = kernel.resolve(fooRuntimeIdentifier); | ||
var bar = kernel.resolve(barRuntimeIdentifier); | ||
expect(foo).to.be.null; | ||
expect(bar).to.not.be.null; | ||
// todo assert only foo is unbound | ||
done(); | ||
@@ -199,3 +227,6 @@ }); | ||
// todo assert foo and bar are unbound | ||
var foo = kernel.resolve(fooRuntimeIdentifier); | ||
var bar = kernel.resolve(barRuntimeIdentifier); | ||
expect(foo).to.be.null; | ||
expect(bar).to.be.null; | ||
@@ -205,2 +236,100 @@ done(); | ||
it('Throw when cannot unbind \n', (done) => { | ||
var kernel = new inversify.Kernel(); | ||
var fooRuntimeIdentifier = "FooInterface"; | ||
var fn = function() { | ||
kernel.unbind(fooRuntimeIdentifier); | ||
} | ||
expect(fn).to.throw(`Could not resolve service ${fooRuntimeIdentifier}`); | ||
done(); | ||
}); | ||
it('Not try to find constructor arguments when ES6 and no constructor \n', () => { | ||
// MORE INFO at https://github.com/inversify/InversifyJS/issues/23 | ||
// using any to access private members | ||
var kernel : any = new inversify.Kernel(); | ||
var binding : any = inversify.TypeBinding; | ||
var A = function(){}; | ||
A.toString = function() { return "class A {\n}"; } | ||
var B = function(){}; | ||
B.toString = function() { return "class B {\n constructor(a) {\n }\n}"; } | ||
kernel.bind(new binding('a', A)); | ||
kernel.bind(new binding('b', B)); | ||
// trigger ES6 detection (TODO run tests on real --harmony enviroment) | ||
Map = function() { }; | ||
// using any to access private members | ||
var args1 = kernel._getConstructorArguments(A); | ||
expect(args1).to.be.instanceof(Array); | ||
expect(args1.length).to.equal(0); | ||
var args2 = kernel._getConstructorArguments(B); | ||
expect(args2).to.be.instanceof(Array); | ||
expect(args2.length).to.equal(1); | ||
expect(args2[0]).to.be.a('string'); | ||
expect(args2[0]).to.equal("a"); | ||
// roll back ES6 detection | ||
Map = undefined; | ||
}); | ||
}); | ||
//****************************************************************************** | ||
//* LOOKUP CLASS | ||
//****************************************************************************** | ||
describe('Lookup Test Suite \n', () => { | ||
it('Key cannot be null when invoking get() remove() or hasKey() \n', (done) => { | ||
var lookup = new Lookup<any>(); | ||
var getFn = function() { lookup.get(null); } | ||
var removeFn = function() { lookup.remove(null); } | ||
var hasKeyFn = function() { lookup.hasKey(null); } | ||
expect(getFn).to.throw("Argument Null"); | ||
expect(removeFn).to.throw("Argument Null"); | ||
expect(hasKeyFn).to.throw("Argument Null"); | ||
done(); | ||
}); | ||
it('Key cannot be null when invoking add() \n', (done) => { | ||
var lookup = new Lookup<any>(); | ||
var addFn = function() { lookup.add(null, 1); } | ||
expect(addFn).to.throw("Argument Null"); | ||
done(); | ||
}); | ||
it('Value cannot be null when invoking add() \n', (done) => { | ||
var lookup = new Lookup<any>(); | ||
var addFn = function() { lookup.add("TEST_KEY", null); } | ||
expect(addFn).to.throw("Argument Null"); | ||
done(); | ||
}); | ||
it('Value cannot be null when invoking add() \n', (done) => { | ||
var lookup = new Lookup<any>(); | ||
var key = "TEST_KEY"; | ||
lookup.add(key, 1); | ||
lookup.add(key, 2); | ||
var result = lookup.get(key); | ||
expect(result.length).to.eql(2); | ||
done(); | ||
}); | ||
it('Throws when key not found \n', (done) => { | ||
var lookup = new Lookup<any>(); | ||
var fn = function() { | ||
lookup.get("THIS_KEY_IS_NOT_AVAILABLE"); | ||
} | ||
expect(fn).to.throw("Key Not Found"); | ||
done(); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
75524
27
1605
191
0
23
5