From b488c7707b65056c27c38674587bc86172f7d898 Mon Sep 17 00:00:00 2001 From: Rob Eisenberg Date: Fri, 27 Feb 2015 23:36:02 -0500 Subject: [PATCH] chore(all): prepare release 0.4.4 --- bower.json | 2 +- dist/amd/container.js | 132 +++++++++++++++++++++- dist/amd/index.js | 10 +- dist/amd/metadata.js | 221 ++++++++++++++++++++++++++++++++++++- dist/amd/util.js | 10 +- dist/commonjs/container.js | 134 +++++++++++++++++++++- dist/commonjs/index.js | 12 +- dist/commonjs/metadata.js | 221 ++++++++++++++++++++++++++++++++++++- dist/commonjs/util.js | 10 +- dist/system/container.js | 131 +++++++++++++++++++++- dist/system/index.js | 12 +- dist/system/metadata.js | 213 ++++++++++++++++++++++++++++++++++- dist/system/util.js | 11 +- doc/CHANGELOG.md | 8 ++ package.json | 2 +- 15 files changed, 1096 insertions(+), 33 deletions(-) diff --git a/bower.json b/bower.json index 62bab9b..da436ea 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "aurelia-dependency-injection", - "version": "0.4.3", + "version": "0.4.4", "description": "A lightweight, extensible dependency injection container for JavaScript.", "keywords": [ "aurelia", diff --git a/dist/amd/container.js b/dist/amd/container.js index 179b658..02bb54f 100644 --- a/dist/amd/container.js +++ b/dist/amd/container.js @@ -3,16 +3,26 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var Metadata = _aureliaMetadata.Metadata; var Resolver = _metadata.Resolver; var Registration = _metadata.Registration; var isClass = _util.isClass; - var emptyParameters = Object.freeze([]); + /** + * A lightweight, extensible dependency injection container. + * + * @class Container + * @constructor + */ + var Container = exports.Container = (function () { function Container(constructionInfo) { + _classCallCheck(this, Container); + this.constructionInfo = constructionInfo || new Map(); this.entries = new Map(); this.root = this; @@ -20,6 +30,13 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export _prototypeProperties(Container, null, { supportAtScript: { + + /** + * Add support for AtScript RTTI according to spec at http://www.atscript.org + * + * @method useAtScript + */ + value: function supportAtScript() { this.addParameterInfoLocator(function (fn) { var parameters = fn.parameters, @@ -42,6 +59,14 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, addParameterInfoLocator: { + + /** + * Adds an additional location to search for constructor parameter type info. + * + * @method addParameterInfoLocator + * @param {Function} locator Configures a locator function to use when searching for parameter info. It should return undefined if no parameter info is found. + */ + value: function addParameterInfoLocator(locator) { if (this.locateParameterInfoElsewhere === undefined) { this.locateParameterInfoElsewhere = locator; @@ -57,6 +82,15 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, registerInstance: { + + /** + * Registers an existing object instance with the container. + * + * @method registerInstance + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Object} instance The instance that will be resolved when the key is matched. + */ + value: function registerInstance(key, instance) { this.registerHandler(key, function (x) { return instance; @@ -66,6 +100,15 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, registerTransient: { + + /** + * Registers a type (constructor function) such that the container returns a new instance for each request. + * + * @method registerTransient + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Function} [fn] The constructor function to use when the dependency needs to be instantiated. + */ + value: function registerTransient(key, fn) { fn = fn || key; this.registerHandler(key, function (x) { @@ -76,6 +119,15 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, registerSingleton: { + + /** + * Registers a type (constructor function) such that the container always returns the same instance for each request. + * + * @method registerSingleton + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Function} [fn] The constructor function to use when the dependency needs to be instantiated. + */ + value: function registerSingleton(key, fn) { var singleton = null; fn = fn || key; @@ -87,6 +139,15 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, autoRegister: { + + /** + * Registers a type (constructor function) by inspecting its registration annotations. If none are found, then the default singleton registration is used. + * + * @method autoRegister + * @param {Function} fn The constructor function to use when the dependency needs to be instantiated. + * @param {Object} [key] The key that identifies the dependency at resolution time; usually a constructor function. + */ + value: function autoRegister(fn, key) { var registration; @@ -106,6 +167,14 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, autoRegisterAll: { + + /** + * Registers an array of types (constructor functions) by inspecting their registration annotations. If none are found, then the default singleton registration is used. + * + * @method autoRegisterAll + * @param {Function[]} fns The constructor function to use when the dependency needs to be instantiated. + */ + value: function autoRegisterAll(fns) { var i = fns.length; while (i--) { @@ -116,6 +185,15 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, registerHandler: { + + /** + * Registers a custom resolution function such that the container calls this function for each request to obtain the instance. + * + * @method registerHandler + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Function} handler The resolution function to use when the dependency is needed. It will be passed one arguement, the container instance that is invoking it. + */ + value: function registerHandler(key, handler) { this.getOrCreateEntry(key).push(handler); }, @@ -123,6 +201,15 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, get: { + + /** + * Resolves a single instance based on the provided key. + * + * @method get + * @param {Object} key The key that identifies the object to resolve. + * @return {Object} Returns the resolved instance. + */ + value: function get(key) { var entry; @@ -157,8 +244,18 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, getAll: { + + /** + * Resolves all instance registered under the provided key. + * + * @method getAll + * @param {Object} key The key that identifies the objects to resolve. + * @return {Object[]} Returns an array of the resolved instances. + */ + value: function getAll(key) { var _this = this; + var entry; if (key === null || key === undefined) { @@ -183,8 +280,19 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, hasHandler: { + + /** + * Inspects the container to determine if a particular key has been registred. + * + * @method hasHandler + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Boolean} [checkParent=false] Indicates whether or not to check the parent container hierarchy. + * @return {Boolean} Returns true if the key has been registred; false otherwise. + */ + value: function hasHandler(key) { var checkParent = arguments[1] === undefined ? false : arguments[1]; + if (key === null || key === undefined) { throw new Error("key cannot be null or undefined."); } @@ -195,6 +303,14 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, createChild: { + + /** + * Creates a new dependency injection container whose parent is the current container. + * + * @method createChild + * @return {Container} Returns a new container instance parented to this. + */ + value: function createChild() { var childContainer = new Container(this.constructionInfo); childContainer.parent = this; @@ -206,6 +322,15 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export configurable: true }, invoke: { + + /** + * Invokes a function, recursively resolving its dependencies. + * + * @method invoke + * @param {Function} fn The function to invoke with the auto-resolved dependencies. + * @return {Object} Returns the instance resulting from calling the function. + */ + value: function invoke(fn) { var info = this.getOrCreateConstructionInfo(fn), keys = info.keys, @@ -296,5 +421,8 @@ define(["exports", "aurelia-metadata", "./metadata", "./util"], function (export return Container; })(); - exports.__esModule = true; + + Object.defineProperty(exports, "__esModule", { + value: true + }); }); \ No newline at end of file diff --git a/dist/amd/index.js b/dist/amd/index.js index c1c30ee..c9b0994 100644 --- a/dist/amd/index.js +++ b/dist/amd/index.js @@ -1,6 +1,11 @@ define(["exports", "aurelia-metadata", "./metadata", "./container"], function (exports, _aureliaMetadata, _metadata, _container) { "use strict"; + /** + * A lightweight, extensible dependency injection container for JavaScript. + * + * @module dependency-injection + */ var Metadata = _aureliaMetadata.Metadata; var Transient = _metadata.Transient; var Singleton = _metadata.Singleton; @@ -14,8 +19,9 @@ define(["exports", "aurelia-metadata", "./metadata", "./container"], function (e exports.Parent = _metadata.Parent; exports.Container = _container.Container; - Metadata.configure.classHelper("transient", Transient); Metadata.configure.classHelper("singleton", Singleton); - exports.__esModule = true; + Object.defineProperty(exports, "__esModule", { + value: true + }); }); \ No newline at end of file diff --git a/dist/amd/metadata.js b/dist/amd/metadata.js index 8f517be..493b875 100644 --- a/dist/amd/metadata.js +++ b/dist/amd/metadata.js @@ -5,11 +5,31 @@ define(["exports"], function (exports) { var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + /** + * An abstract annotation used to allow functions/classes to indicate how they should be registered with the container. + * + * @class Registration + * @constructor + */ + var Registration = exports.Registration = (function () { - function Registration() {} + function Registration() { + _classCallCheck(this, Registration); + } _prototypeProperties(Registration, null, { register: { + /** + * Called by the container to allow custom registration logic for the annotated function/class. + * + * @method register + * @param {Container} container The container to register with. + * @param {Object} key The key to register as. + * @param {Object} fn The function to register (target of the annotation). + */ + value: function register(container, key, fn) { throw new Error("A custom Registration must implement register(container, key, fn)."); }, @@ -20,8 +40,20 @@ define(["exports"], function (exports) { return Registration; })(); + + /** + * An annotation used to allow functions/classes to indicate that they should be registered as transients with the container. + * + * @class Transient + * @constructor + * @extends Registration + * @param {Object} [key] The key to register as. + */ + var Transient = exports.Transient = (function (Registration) { function Transient(key) { + _classCallCheck(this, Transient); + this.key = key; } @@ -29,6 +61,16 @@ define(["exports"], function (exports) { _prototypeProperties(Transient, null, { register: { + + /** + * Called by the container to register the annotated function/class as transient. + * + * @method register + * @param {Container} container The container to register with. + * @param {Object} key The key to register as. + * @param {Object} fn The function to register (target of the annotation). + */ + value: function register(container, key, fn) { container.registerTransient(this.key || key, fn); }, @@ -39,9 +81,22 @@ define(["exports"], function (exports) { return Transient; })(Registration); + + /** + * An annotation used to allow functions/classes to indicate that they should be registered as singletons with the container. + * + * @class Singleton + * @constructor + * @extends Registration + * @param {Object} [key] The key to register as. + */ + var Singleton = exports.Singleton = (function (Registration) { function Singleton(keyOrRegisterInRoot) { var registerInRoot = arguments[1] === undefined ? false : arguments[1]; + + _classCallCheck(this, Singleton); + if (typeof keyOrRegisterInRoot === "boolean") { this.registerInRoot = keyOrRegisterInRoot; } else { @@ -54,6 +109,16 @@ define(["exports"], function (exports) { _prototypeProperties(Singleton, null, { register: { + + /** + * Called by the container to register the annotated function/class as a singleton. + * + * @method register + * @param {Container} container The container to register with. + * @param {Object} key The key to register as. + * @param {Object} fn The function to register (target of the annotation). + */ + value: function register(container, key, fn) { var destination = this.registerInRoot ? container.root : container; destination.registerSingleton(this.key || key, fn); @@ -65,11 +130,29 @@ define(["exports"], function (exports) { return Singleton; })(Registration); + + /** + * An abstract annotation used to allow functions/classes to specify custom dependency resolution logic. + * + * @class Resolver + * @constructor + */ + var Resolver = exports.Resolver = (function () { - function Resolver() {} + function Resolver() { + _classCallCheck(this, Resolver); + } _prototypeProperties(Resolver, null, { get: { + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Object} Returns the resolved object. + */ + value: function get(container) { throw new Error("A custom Resolver must implement get(container) and return the resolved instance(s)."); }, @@ -80,8 +163,20 @@ define(["exports"], function (exports) { return Resolver; })(); + + /** + * An annotation used to allow functions/classes to specify lazy resolution logic. + * + * @class Lazy + * @constructor + * @extends Resolver + * @param {Object} key The key to lazily resolve. + */ + var Lazy = exports.Lazy = (function (Resolver) { function Lazy(key) { + _classCallCheck(this, Lazy); + this.key = key; } @@ -89,6 +184,16 @@ define(["exports"], function (exports) { _prototypeProperties(Lazy, { of: { + + /** + * Creates a Lazy Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to lazily resolve. + * @return {Lazy} Returns an insance of Lazy for the key. + */ + value: function of(key) { return new Lazy(key); }, @@ -97,8 +202,18 @@ define(["exports"], function (exports) { } }, { get: { + + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Function} Returns a function which can be invoked at a later time to obtain the actual dependency. + */ + value: function get(container) { var _this = this; + return function () { return container.get(_this.key); }; @@ -110,8 +225,20 @@ define(["exports"], function (exports) { return Lazy; })(Resolver); + + /** + * An annotation used to allow functions/classes to specify resolution of all matches to a key. + * + * @class All + * @constructor + * @extends Resolver + * @param {Object} key The key to lazily resolve all matches for. + */ + var All = exports.All = (function (Resolver) { function All(key) { + _classCallCheck(this, All); + this.key = key; } @@ -119,6 +246,16 @@ define(["exports"], function (exports) { _prototypeProperties(All, { of: { + + /** + * Creates an All Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to resolve all instances for. + * @return {All} Returns an insance of All for the key. + */ + value: function of(key) { return new All(key); }, @@ -127,6 +264,15 @@ define(["exports"], function (exports) { } }, { get: { + + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Object[]} Returns an array of all matching instances. + */ + value: function get(container) { return container.getAll(this.key); }, @@ -137,9 +283,23 @@ define(["exports"], function (exports) { return All; })(Resolver); + + /** + * An annotation used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. + * + * @class Optional + * @constructor + * @extends Resolver + * @param {Object} key The key to optionally resolve for. + * @param {Boolean} [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + */ + var Optional = exports.Optional = (function (Resolver) { function Optional(key) { var checkParent = arguments[1] === undefined ? false : arguments[1]; + + _classCallCheck(this, Optional); + this.key = key; this.checkParent = checkParent; } @@ -148,8 +308,20 @@ define(["exports"], function (exports) { _prototypeProperties(Optional, { of: { + + /** + * Creates an Optional Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to optionally resolve for. + * @param {Boolean} [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return {Optional} Returns an insance of Optional for the key. + */ + value: function of(key) { var checkParent = arguments[1] === undefined ? false : arguments[1]; + return new Optional(key, checkParent); }, writable: true, @@ -157,6 +329,15 @@ define(["exports"], function (exports) { } }, { get: { + + /** + * Called by the container to provide optional resolution of the key. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Object} Returns the instance if found; otherwise null. + */ + value: function get(container) { if (container.hasHandler(this.key, this.checkParent)) { return container.get(this.key); @@ -171,8 +352,20 @@ define(["exports"], function (exports) { return Optional; })(Resolver); + + /** + * An annotation used to inject the dependency from the parent container instead of the current one. + * + * @class Parent + * @constructor + * @extends Resolver + * @param {Object} key The key to resolve from the parent container. + */ + var Parent = exports.Parent = (function (Resolver) { function Parent(key) { + _classCallCheck(this, Parent); + this.key = key; } @@ -180,6 +373,16 @@ define(["exports"], function (exports) { _prototypeProperties(Parent, { of: { + + /** + * Creates a Parent Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to resolve. + * @return {Parent} Returns an insance of Parent for the key. + */ + value: function of(key) { return new Parent(key); }, @@ -188,6 +391,15 @@ define(["exports"], function (exports) { } }, { get: { + + /** + * Called by the container to load the dependency from the parent container + * + * @method get + * @param {Container} container The container to resolve the parent from. + * @return {Function} Returns the matching instance from the parent container + */ + value: function get(container) { return container.parent ? container.parent.get(this.key) : null; }, @@ -198,5 +410,8 @@ define(["exports"], function (exports) { return Parent; })(Resolver); - exports.__esModule = true; + + Object.defineProperty(exports, "__esModule", { + value: true + }); }); \ No newline at end of file diff --git a/dist/amd/util.js b/dist/amd/util.js index 84b655f..3274f88 100644 --- a/dist/amd/util.js +++ b/dist/amd/util.js @@ -2,11 +2,14 @@ define(["exports"], function (exports) { "use strict"; exports.isClass = isClass; + // Fix Function#name on browsers that do not support it (IE): function test() {} if (!test.name) { Object.defineProperty(Function.prototype, "name", { - get: function () { + get: function get() { var name = this.toString().match(/^\s*function\s*(\S*)\s*\(/)[1]; + // For better performance only parse once, and then cache the + // result through a new accessor for repeated access. Object.defineProperty(this, "name", { value: name }); return name; } @@ -24,5 +27,8 @@ define(["exports"], function (exports) { return Object.keys(clsOrFunction.prototype).length > 0; } - exports.__esModule = true; + + Object.defineProperty(exports, "__esModule", { + value: true + }); }); \ No newline at end of file diff --git a/dist/commonjs/container.js b/dist/commonjs/container.js index 98db1fd..3eabf6d 100644 --- a/dist/commonjs/container.js +++ b/dist/commonjs/container.js @@ -2,18 +2,30 @@ var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var Metadata = require("aurelia-metadata").Metadata; + var _metadata = require("./metadata"); var Resolver = _metadata.Resolver; var Registration = _metadata.Registration; -var isClass = require("./util").isClass; +var isClass = require("./util").isClass; var emptyParameters = Object.freeze([]); +/** +* A lightweight, extensible dependency injection container. +* +* @class Container +* @constructor +*/ + var Container = exports.Container = (function () { function Container(constructionInfo) { + _classCallCheck(this, Container); + this.constructionInfo = constructionInfo || new Map(); this.entries = new Map(); this.root = this; @@ -21,6 +33,13 @@ var Container = exports.Container = (function () { _prototypeProperties(Container, null, { supportAtScript: { + + /** + * Add support for AtScript RTTI according to spec at http://www.atscript.org + * + * @method useAtScript + */ + value: function supportAtScript() { this.addParameterInfoLocator(function (fn) { var parameters = fn.parameters, @@ -43,6 +62,14 @@ var Container = exports.Container = (function () { configurable: true }, addParameterInfoLocator: { + + /** + * Adds an additional location to search for constructor parameter type info. + * + * @method addParameterInfoLocator + * @param {Function} locator Configures a locator function to use when searching for parameter info. It should return undefined if no parameter info is found. + */ + value: function addParameterInfoLocator(locator) { if (this.locateParameterInfoElsewhere === undefined) { this.locateParameterInfoElsewhere = locator; @@ -58,6 +85,15 @@ var Container = exports.Container = (function () { configurable: true }, registerInstance: { + + /** + * Registers an existing object instance with the container. + * + * @method registerInstance + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Object} instance The instance that will be resolved when the key is matched. + */ + value: function registerInstance(key, instance) { this.registerHandler(key, function (x) { return instance; @@ -67,6 +103,15 @@ var Container = exports.Container = (function () { configurable: true }, registerTransient: { + + /** + * Registers a type (constructor function) such that the container returns a new instance for each request. + * + * @method registerTransient + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Function} [fn] The constructor function to use when the dependency needs to be instantiated. + */ + value: function registerTransient(key, fn) { fn = fn || key; this.registerHandler(key, function (x) { @@ -77,6 +122,15 @@ var Container = exports.Container = (function () { configurable: true }, registerSingleton: { + + /** + * Registers a type (constructor function) such that the container always returns the same instance for each request. + * + * @method registerSingleton + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Function} [fn] The constructor function to use when the dependency needs to be instantiated. + */ + value: function registerSingleton(key, fn) { var singleton = null; fn = fn || key; @@ -88,6 +142,15 @@ var Container = exports.Container = (function () { configurable: true }, autoRegister: { + + /** + * Registers a type (constructor function) by inspecting its registration annotations. If none are found, then the default singleton registration is used. + * + * @method autoRegister + * @param {Function} fn The constructor function to use when the dependency needs to be instantiated. + * @param {Object} [key] The key that identifies the dependency at resolution time; usually a constructor function. + */ + value: function autoRegister(fn, key) { var registration; @@ -107,6 +170,14 @@ var Container = exports.Container = (function () { configurable: true }, autoRegisterAll: { + + /** + * Registers an array of types (constructor functions) by inspecting their registration annotations. If none are found, then the default singleton registration is used. + * + * @method autoRegisterAll + * @param {Function[]} fns The constructor function to use when the dependency needs to be instantiated. + */ + value: function autoRegisterAll(fns) { var i = fns.length; while (i--) { @@ -117,6 +188,15 @@ var Container = exports.Container = (function () { configurable: true }, registerHandler: { + + /** + * Registers a custom resolution function such that the container calls this function for each request to obtain the instance. + * + * @method registerHandler + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Function} handler The resolution function to use when the dependency is needed. It will be passed one arguement, the container instance that is invoking it. + */ + value: function registerHandler(key, handler) { this.getOrCreateEntry(key).push(handler); }, @@ -124,6 +204,15 @@ var Container = exports.Container = (function () { configurable: true }, get: { + + /** + * Resolves a single instance based on the provided key. + * + * @method get + * @param {Object} key The key that identifies the object to resolve. + * @return {Object} Returns the resolved instance. + */ + value: function get(key) { var entry; @@ -158,8 +247,18 @@ var Container = exports.Container = (function () { configurable: true }, getAll: { + + /** + * Resolves all instance registered under the provided key. + * + * @method getAll + * @param {Object} key The key that identifies the objects to resolve. + * @return {Object[]} Returns an array of the resolved instances. + */ + value: function getAll(key) { var _this = this; + var entry; if (key === null || key === undefined) { @@ -184,8 +283,19 @@ var Container = exports.Container = (function () { configurable: true }, hasHandler: { + + /** + * Inspects the container to determine if a particular key has been registred. + * + * @method hasHandler + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Boolean} [checkParent=false] Indicates whether or not to check the parent container hierarchy. + * @return {Boolean} Returns true if the key has been registred; false otherwise. + */ + value: function hasHandler(key) { var checkParent = arguments[1] === undefined ? false : arguments[1]; + if (key === null || key === undefined) { throw new Error("key cannot be null or undefined."); } @@ -196,6 +306,14 @@ var Container = exports.Container = (function () { configurable: true }, createChild: { + + /** + * Creates a new dependency injection container whose parent is the current container. + * + * @method createChild + * @return {Container} Returns a new container instance parented to this. + */ + value: function createChild() { var childContainer = new Container(this.constructionInfo); childContainer.parent = this; @@ -207,6 +325,15 @@ var Container = exports.Container = (function () { configurable: true }, invoke: { + + /** + * Invokes a function, recursively resolving its dependencies. + * + * @method invoke + * @param {Function} fn The function to invoke with the auto-resolved dependencies. + * @return {Object} Returns the instance resulting from calling the function. + */ + value: function invoke(fn) { var info = this.getOrCreateConstructionInfo(fn), keys = info.keys, @@ -297,4 +424,7 @@ var Container = exports.Container = (function () { return Container; })(); -exports.__esModule = true; \ No newline at end of file + +Object.defineProperty(exports, "__esModule", { + value: true +}); \ No newline at end of file diff --git a/dist/commonjs/index.js b/dist/commonjs/index.js index b94e942..e3bc9b2 100644 --- a/dist/commonjs/index.js +++ b/dist/commonjs/index.js @@ -1,6 +1,13 @@ "use strict"; +/** + * A lightweight, extensible dependency injection container for JavaScript. + * + * @module dependency-injection + */ + var Metadata = require("aurelia-metadata").Metadata; + var _metadata = require("./metadata"); var Transient = _metadata.Transient; @@ -15,7 +22,8 @@ exports.Optional = _metadata.Optional; exports.Parent = _metadata.Parent; exports.Container = require("./container").Container; - Metadata.configure.classHelper("transient", Transient); Metadata.configure.classHelper("singleton", Singleton); -exports.__esModule = true; \ No newline at end of file +Object.defineProperty(exports, "__esModule", { + value: true +}); \ No newline at end of file diff --git a/dist/commonjs/metadata.js b/dist/commonjs/metadata.js index e48a5f5..f357bff 100644 --- a/dist/commonjs/metadata.js +++ b/dist/commonjs/metadata.js @@ -4,11 +4,31 @@ var _inherits = function (subClass, superClass) { if (typeof superClass !== "fun var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + +/** +* An abstract annotation used to allow functions/classes to indicate how they should be registered with the container. +* +* @class Registration +* @constructor +*/ + var Registration = exports.Registration = (function () { - function Registration() {} + function Registration() { + _classCallCheck(this, Registration); + } _prototypeProperties(Registration, null, { register: { + /** + * Called by the container to allow custom registration logic for the annotated function/class. + * + * @method register + * @param {Container} container The container to register with. + * @param {Object} key The key to register as. + * @param {Object} fn The function to register (target of the annotation). + */ + value: function register(container, key, fn) { throw new Error("A custom Registration must implement register(container, key, fn)."); }, @@ -19,8 +39,20 @@ var Registration = exports.Registration = (function () { return Registration; })(); + +/** +* An annotation used to allow functions/classes to indicate that they should be registered as transients with the container. +* +* @class Transient +* @constructor +* @extends Registration +* @param {Object} [key] The key to register as. +*/ + var Transient = exports.Transient = (function (Registration) { function Transient(key) { + _classCallCheck(this, Transient); + this.key = key; } @@ -28,6 +60,16 @@ var Transient = exports.Transient = (function (Registration) { _prototypeProperties(Transient, null, { register: { + + /** + * Called by the container to register the annotated function/class as transient. + * + * @method register + * @param {Container} container The container to register with. + * @param {Object} key The key to register as. + * @param {Object} fn The function to register (target of the annotation). + */ + value: function register(container, key, fn) { container.registerTransient(this.key || key, fn); }, @@ -38,9 +80,22 @@ var Transient = exports.Transient = (function (Registration) { return Transient; })(Registration); + +/** +* An annotation used to allow functions/classes to indicate that they should be registered as singletons with the container. +* +* @class Singleton +* @constructor +* @extends Registration +* @param {Object} [key] The key to register as. +*/ + var Singleton = exports.Singleton = (function (Registration) { function Singleton(keyOrRegisterInRoot) { var registerInRoot = arguments[1] === undefined ? false : arguments[1]; + + _classCallCheck(this, Singleton); + if (typeof keyOrRegisterInRoot === "boolean") { this.registerInRoot = keyOrRegisterInRoot; } else { @@ -53,6 +108,16 @@ var Singleton = exports.Singleton = (function (Registration) { _prototypeProperties(Singleton, null, { register: { + + /** + * Called by the container to register the annotated function/class as a singleton. + * + * @method register + * @param {Container} container The container to register with. + * @param {Object} key The key to register as. + * @param {Object} fn The function to register (target of the annotation). + */ + value: function register(container, key, fn) { var destination = this.registerInRoot ? container.root : container; destination.registerSingleton(this.key || key, fn); @@ -64,11 +129,29 @@ var Singleton = exports.Singleton = (function (Registration) { return Singleton; })(Registration); + +/** +* An abstract annotation used to allow functions/classes to specify custom dependency resolution logic. +* +* @class Resolver +* @constructor +*/ + var Resolver = exports.Resolver = (function () { - function Resolver() {} + function Resolver() { + _classCallCheck(this, Resolver); + } _prototypeProperties(Resolver, null, { get: { + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Object} Returns the resolved object. + */ + value: function get(container) { throw new Error("A custom Resolver must implement get(container) and return the resolved instance(s)."); }, @@ -79,8 +162,20 @@ var Resolver = exports.Resolver = (function () { return Resolver; })(); + +/** +* An annotation used to allow functions/classes to specify lazy resolution logic. +* +* @class Lazy +* @constructor +* @extends Resolver +* @param {Object} key The key to lazily resolve. +*/ + var Lazy = exports.Lazy = (function (Resolver) { function Lazy(key) { + _classCallCheck(this, Lazy); + this.key = key; } @@ -88,6 +183,16 @@ var Lazy = exports.Lazy = (function (Resolver) { _prototypeProperties(Lazy, { of: { + + /** + * Creates a Lazy Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to lazily resolve. + * @return {Lazy} Returns an insance of Lazy for the key. + */ + value: function of(key) { return new Lazy(key); }, @@ -96,8 +201,18 @@ var Lazy = exports.Lazy = (function (Resolver) { } }, { get: { + + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Function} Returns a function which can be invoked at a later time to obtain the actual dependency. + */ + value: function get(container) { var _this = this; + return function () { return container.get(_this.key); }; @@ -109,8 +224,20 @@ var Lazy = exports.Lazy = (function (Resolver) { return Lazy; })(Resolver); + +/** +* An annotation used to allow functions/classes to specify resolution of all matches to a key. +* +* @class All +* @constructor +* @extends Resolver +* @param {Object} key The key to lazily resolve all matches for. +*/ + var All = exports.All = (function (Resolver) { function All(key) { + _classCallCheck(this, All); + this.key = key; } @@ -118,6 +245,16 @@ var All = exports.All = (function (Resolver) { _prototypeProperties(All, { of: { + + /** + * Creates an All Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to resolve all instances for. + * @return {All} Returns an insance of All for the key. + */ + value: function of(key) { return new All(key); }, @@ -126,6 +263,15 @@ var All = exports.All = (function (Resolver) { } }, { get: { + + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Object[]} Returns an array of all matching instances. + */ + value: function get(container) { return container.getAll(this.key); }, @@ -136,9 +282,23 @@ var All = exports.All = (function (Resolver) { return All; })(Resolver); + +/** +* An annotation used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. +* +* @class Optional +* @constructor +* @extends Resolver +* @param {Object} key The key to optionally resolve for. +* @param {Boolean} [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. +*/ + var Optional = exports.Optional = (function (Resolver) { function Optional(key) { var checkParent = arguments[1] === undefined ? false : arguments[1]; + + _classCallCheck(this, Optional); + this.key = key; this.checkParent = checkParent; } @@ -147,8 +307,20 @@ var Optional = exports.Optional = (function (Resolver) { _prototypeProperties(Optional, { of: { + + /** + * Creates an Optional Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to optionally resolve for. + * @param {Boolean} [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return {Optional} Returns an insance of Optional for the key. + */ + value: function of(key) { var checkParent = arguments[1] === undefined ? false : arguments[1]; + return new Optional(key, checkParent); }, writable: true, @@ -156,6 +328,15 @@ var Optional = exports.Optional = (function (Resolver) { } }, { get: { + + /** + * Called by the container to provide optional resolution of the key. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Object} Returns the instance if found; otherwise null. + */ + value: function get(container) { if (container.hasHandler(this.key, this.checkParent)) { return container.get(this.key); @@ -170,8 +351,20 @@ var Optional = exports.Optional = (function (Resolver) { return Optional; })(Resolver); + +/** +* An annotation used to inject the dependency from the parent container instead of the current one. +* +* @class Parent +* @constructor +* @extends Resolver +* @param {Object} key The key to resolve from the parent container. +*/ + var Parent = exports.Parent = (function (Resolver) { function Parent(key) { + _classCallCheck(this, Parent); + this.key = key; } @@ -179,6 +372,16 @@ var Parent = exports.Parent = (function (Resolver) { _prototypeProperties(Parent, { of: { + + /** + * Creates a Parent Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to resolve. + * @return {Parent} Returns an insance of Parent for the key. + */ + value: function of(key) { return new Parent(key); }, @@ -187,6 +390,15 @@ var Parent = exports.Parent = (function (Resolver) { } }, { get: { + + /** + * Called by the container to load the dependency from the parent container + * + * @method get + * @param {Container} container The container to resolve the parent from. + * @return {Function} Returns the matching instance from the parent container + */ + value: function get(container) { return container.parent ? container.parent.get(this.key) : null; }, @@ -197,4 +409,7 @@ var Parent = exports.Parent = (function (Resolver) { return Parent; })(Resolver); -exports.__esModule = true; \ No newline at end of file + +Object.defineProperty(exports, "__esModule", { + value: true +}); \ No newline at end of file diff --git a/dist/commonjs/util.js b/dist/commonjs/util.js index 3a926a9..cb6018a 100644 --- a/dist/commonjs/util.js +++ b/dist/commonjs/util.js @@ -1,11 +1,14 @@ "use strict"; exports.isClass = isClass; +// Fix Function#name on browsers that do not support it (IE): function test() {} if (!test.name) { Object.defineProperty(Function.prototype, "name", { - get: function () { + get: function get() { var name = this.toString().match(/^\s*function\s*(\S*)\s*\(/)[1]; + // For better performance only parse once, and then cache the + // result through a new accessor for repeated access. Object.defineProperty(this, "name", { value: name }); return name; } @@ -23,4 +26,7 @@ function isClass(clsOrFunction) { return Object.keys(clsOrFunction.prototype).length > 0; } -exports.__esModule = true; \ No newline at end of file + +Object.defineProperty(exports, "__esModule", { + value: true +}); \ No newline at end of file diff --git a/dist/system/container.js b/dist/system/container.js index 0984c10..ff72117 100644 --- a/dist/system/container.js +++ b/dist/system/container.js @@ -1,7 +1,6 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) { - "use strict"; + var Metadata, Resolver, Registration, isClass, _prototypeProperties, _classCallCheck, emptyParameters, Container; - var Metadata, Resolver, Registration, isClass, _prototypeProperties, emptyParameters, Container; return { setters: [function (_aureliaMetadata) { Metadata = _aureliaMetadata.Metadata; @@ -12,11 +11,24 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) isClass = _util.isClass; }], execute: function () { + "use strict"; + _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + emptyParameters = Object.freeze([]); + + /** + * A lightweight, extensible dependency injection container. + * + * @class Container + * @constructor + */ Container = _export("Container", (function () { function Container(constructionInfo) { + _classCallCheck(this, Container); + this.constructionInfo = constructionInfo || new Map(); this.entries = new Map(); this.root = this; @@ -24,6 +36,13 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) _prototypeProperties(Container, null, { supportAtScript: { + + /** + * Add support for AtScript RTTI according to spec at http://www.atscript.org + * + * @method useAtScript + */ + value: function supportAtScript() { this.addParameterInfoLocator(function (fn) { var parameters = fn.parameters, @@ -46,6 +65,14 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, addParameterInfoLocator: { + + /** + * Adds an additional location to search for constructor parameter type info. + * + * @method addParameterInfoLocator + * @param {Function} locator Configures a locator function to use when searching for parameter info. It should return undefined if no parameter info is found. + */ + value: function addParameterInfoLocator(locator) { if (this.locateParameterInfoElsewhere === undefined) { this.locateParameterInfoElsewhere = locator; @@ -61,6 +88,15 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, registerInstance: { + + /** + * Registers an existing object instance with the container. + * + * @method registerInstance + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Object} instance The instance that will be resolved when the key is matched. + */ + value: function registerInstance(key, instance) { this.registerHandler(key, function (x) { return instance; @@ -70,6 +106,15 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, registerTransient: { + + /** + * Registers a type (constructor function) such that the container returns a new instance for each request. + * + * @method registerTransient + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Function} [fn] The constructor function to use when the dependency needs to be instantiated. + */ + value: function registerTransient(key, fn) { fn = fn || key; this.registerHandler(key, function (x) { @@ -80,6 +125,15 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, registerSingleton: { + + /** + * Registers a type (constructor function) such that the container always returns the same instance for each request. + * + * @method registerSingleton + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Function} [fn] The constructor function to use when the dependency needs to be instantiated. + */ + value: function registerSingleton(key, fn) { var singleton = null; fn = fn || key; @@ -91,6 +145,15 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, autoRegister: { + + /** + * Registers a type (constructor function) by inspecting its registration annotations. If none are found, then the default singleton registration is used. + * + * @method autoRegister + * @param {Function} fn The constructor function to use when the dependency needs to be instantiated. + * @param {Object} [key] The key that identifies the dependency at resolution time; usually a constructor function. + */ + value: function autoRegister(fn, key) { var registration; @@ -110,6 +173,14 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, autoRegisterAll: { + + /** + * Registers an array of types (constructor functions) by inspecting their registration annotations. If none are found, then the default singleton registration is used. + * + * @method autoRegisterAll + * @param {Function[]} fns The constructor function to use when the dependency needs to be instantiated. + */ + value: function autoRegisterAll(fns) { var i = fns.length; while (i--) { @@ -120,6 +191,15 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, registerHandler: { + + /** + * Registers a custom resolution function such that the container calls this function for each request to obtain the instance. + * + * @method registerHandler + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Function} handler The resolution function to use when the dependency is needed. It will be passed one arguement, the container instance that is invoking it. + */ + value: function registerHandler(key, handler) { this.getOrCreateEntry(key).push(handler); }, @@ -127,6 +207,15 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, get: { + + /** + * Resolves a single instance based on the provided key. + * + * @method get + * @param {Object} key The key that identifies the object to resolve. + * @return {Object} Returns the resolved instance. + */ + value: function get(key) { var entry; @@ -161,8 +250,18 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, getAll: { + + /** + * Resolves all instance registered under the provided key. + * + * @method getAll + * @param {Object} key The key that identifies the objects to resolve. + * @return {Object[]} Returns an array of the resolved instances. + */ + value: function getAll(key) { var _this = this; + var entry; if (key === null || key === undefined) { @@ -187,8 +286,19 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, hasHandler: { + + /** + * Inspects the container to determine if a particular key has been registred. + * + * @method hasHandler + * @param {Object} key The key that identifies the dependency at resolution time; usually a constructor function. + * @param {Boolean} [checkParent=false] Indicates whether or not to check the parent container hierarchy. + * @return {Boolean} Returns true if the key has been registred; false otherwise. + */ + value: function hasHandler(key) { var checkParent = arguments[1] === undefined ? false : arguments[1]; + if (key === null || key === undefined) { throw new Error("key cannot be null or undefined."); } @@ -199,6 +309,14 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, createChild: { + + /** + * Creates a new dependency injection container whose parent is the current container. + * + * @method createChild + * @return {Container} Returns a new container instance parented to this. + */ + value: function createChild() { var childContainer = new Container(this.constructionInfo); childContainer.parent = this; @@ -210,6 +328,15 @@ System.register(["aurelia-metadata", "./metadata", "./util"], function (_export) configurable: true }, invoke: { + + /** + * Invokes a function, recursively resolving its dependencies. + * + * @method invoke + * @param {Function} fn The function to invoke with the auto-resolved dependencies. + * @return {Object} Returns the instance resulting from calling the function. + */ + value: function invoke(fn) { var info = this.getOrCreateConstructionInfo(fn), keys = info.keys, diff --git a/dist/system/index.js b/dist/system/index.js index cd3e3bd..c75db63 100644 --- a/dist/system/index.js +++ b/dist/system/index.js @@ -1,6 +1,4 @@ System.register(["aurelia-metadata", "./metadata", "./container"], function (_export) { - "use strict"; - var Metadata, Transient, Singleton; return { setters: [function (_aureliaMetadata) { @@ -8,6 +6,7 @@ System.register(["aurelia-metadata", "./metadata", "./container"], function (_ex }, function (_metadata) { Transient = _metadata.Transient; Singleton = _metadata.Singleton; + _export("Registration", _metadata.Registration); _export("Transient", _metadata.Transient); @@ -27,8 +26,15 @@ System.register(["aurelia-metadata", "./metadata", "./container"], function (_ex _export("Container", _container.Container); }], execute: function () { + "use strict"; + Metadata.configure.classHelper("transient", Transient); Metadata.configure.classHelper("singleton", Singleton); } }; -}); \ No newline at end of file +}); +/** + * A lightweight, extensible dependency injection container for JavaScript. + * + * @module dependency-injection + */ \ No newline at end of file diff --git a/dist/system/metadata.js b/dist/system/metadata.js index 7dbd434..2549474 100644 --- a/dist/system/metadata.js +++ b/dist/system/metadata.js @@ -1,19 +1,39 @@ System.register([], function (_export) { - "use strict"; + var _inherits, _prototypeProperties, _classCallCheck, Registration, Transient, Singleton, Resolver, Lazy, All, Optional, Parent; - var _inherits, _prototypeProperties, Registration, Transient, Singleton, Resolver, Lazy, All, Optional, Parent; return { setters: [], execute: function () { + "use strict"; + _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + /** + * An abstract annotation used to allow functions/classes to indicate how they should be registered with the container. + * + * @class Registration + * @constructor + */ Registration = _export("Registration", (function () { - function Registration() {} + function Registration() { + _classCallCheck(this, Registration); + } _prototypeProperties(Registration, null, { register: { + /** + * Called by the container to allow custom registration logic for the annotated function/class. + * + * @method register + * @param {Container} container The container to register with. + * @param {Object} key The key to register as. + * @param {Object} fn The function to register (target of the annotation). + */ + value: function register(container, key, fn) { throw new Error("A custom Registration must implement register(container, key, fn)."); }, @@ -24,8 +44,19 @@ System.register([], function (_export) { return Registration; })()); + + /** + * An annotation used to allow functions/classes to indicate that they should be registered as transients with the container. + * + * @class Transient + * @constructor + * @extends Registration + * @param {Object} [key] The key to register as. + */ Transient = _export("Transient", (function (Registration) { function Transient(key) { + _classCallCheck(this, Transient); + this.key = key; } @@ -33,6 +64,16 @@ System.register([], function (_export) { _prototypeProperties(Transient, null, { register: { + + /** + * Called by the container to register the annotated function/class as transient. + * + * @method register + * @param {Container} container The container to register with. + * @param {Object} key The key to register as. + * @param {Object} fn The function to register (target of the annotation). + */ + value: function register(container, key, fn) { container.registerTransient(this.key || key, fn); }, @@ -43,9 +84,21 @@ System.register([], function (_export) { return Transient; })(Registration)); + + /** + * An annotation used to allow functions/classes to indicate that they should be registered as singletons with the container. + * + * @class Singleton + * @constructor + * @extends Registration + * @param {Object} [key] The key to register as. + */ Singleton = _export("Singleton", (function (Registration) { function Singleton(keyOrRegisterInRoot) { var registerInRoot = arguments[1] === undefined ? false : arguments[1]; + + _classCallCheck(this, Singleton); + if (typeof keyOrRegisterInRoot === "boolean") { this.registerInRoot = keyOrRegisterInRoot; } else { @@ -58,6 +111,16 @@ System.register([], function (_export) { _prototypeProperties(Singleton, null, { register: { + + /** + * Called by the container to register the annotated function/class as a singleton. + * + * @method register + * @param {Container} container The container to register with. + * @param {Object} key The key to register as. + * @param {Object} fn The function to register (target of the annotation). + */ + value: function register(container, key, fn) { var destination = this.registerInRoot ? container.root : container; destination.registerSingleton(this.key || key, fn); @@ -69,11 +132,28 @@ System.register([], function (_export) { return Singleton; })(Registration)); + + /** + * An abstract annotation used to allow functions/classes to specify custom dependency resolution logic. + * + * @class Resolver + * @constructor + */ Resolver = _export("Resolver", (function () { - function Resolver() {} + function Resolver() { + _classCallCheck(this, Resolver); + } _prototypeProperties(Resolver, null, { get: { + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Object} Returns the resolved object. + */ + value: function get(container) { throw new Error("A custom Resolver must implement get(container) and return the resolved instance(s)."); }, @@ -84,8 +164,19 @@ System.register([], function (_export) { return Resolver; })()); + + /** + * An annotation used to allow functions/classes to specify lazy resolution logic. + * + * @class Lazy + * @constructor + * @extends Resolver + * @param {Object} key The key to lazily resolve. + */ Lazy = _export("Lazy", (function (Resolver) { function Lazy(key) { + _classCallCheck(this, Lazy); + this.key = key; } @@ -93,6 +184,16 @@ System.register([], function (_export) { _prototypeProperties(Lazy, { of: { + + /** + * Creates a Lazy Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to lazily resolve. + * @return {Lazy} Returns an insance of Lazy for the key. + */ + value: function of(key) { return new Lazy(key); }, @@ -101,8 +202,18 @@ System.register([], function (_export) { } }, { get: { + + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Function} Returns a function which can be invoked at a later time to obtain the actual dependency. + */ + value: function get(container) { var _this = this; + return function () { return container.get(_this.key); }; @@ -114,8 +225,19 @@ System.register([], function (_export) { return Lazy; })(Resolver)); + + /** + * An annotation used to allow functions/classes to specify resolution of all matches to a key. + * + * @class All + * @constructor + * @extends Resolver + * @param {Object} key The key to lazily resolve all matches for. + */ All = _export("All", (function (Resolver) { function All(key) { + _classCallCheck(this, All); + this.key = key; } @@ -123,6 +245,16 @@ System.register([], function (_export) { _prototypeProperties(All, { of: { + + /** + * Creates an All Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to resolve all instances for. + * @return {All} Returns an insance of All for the key. + */ + value: function of(key) { return new All(key); }, @@ -131,6 +263,15 @@ System.register([], function (_export) { } }, { get: { + + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Object[]} Returns an array of all matching instances. + */ + value: function get(container) { return container.getAll(this.key); }, @@ -141,9 +282,22 @@ System.register([], function (_export) { return All; })(Resolver)); + + /** + * An annotation used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. + * + * @class Optional + * @constructor + * @extends Resolver + * @param {Object} key The key to optionally resolve for. + * @param {Boolean} [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + */ Optional = _export("Optional", (function (Resolver) { function Optional(key) { var checkParent = arguments[1] === undefined ? false : arguments[1]; + + _classCallCheck(this, Optional); + this.key = key; this.checkParent = checkParent; } @@ -152,8 +306,20 @@ System.register([], function (_export) { _prototypeProperties(Optional, { of: { + + /** + * Creates an Optional Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to optionally resolve for. + * @param {Boolean} [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return {Optional} Returns an insance of Optional for the key. + */ + value: function of(key) { var checkParent = arguments[1] === undefined ? false : arguments[1]; + return new Optional(key, checkParent); }, writable: true, @@ -161,6 +327,15 @@ System.register([], function (_export) { } }, { get: { + + /** + * Called by the container to provide optional resolution of the key. + * + * @method get + * @param {Container} container The container to resolve from. + * @return {Object} Returns the instance if found; otherwise null. + */ + value: function get(container) { if (container.hasHandler(this.key, this.checkParent)) { return container.get(this.key); @@ -175,8 +350,19 @@ System.register([], function (_export) { return Optional; })(Resolver)); + + /** + * An annotation used to inject the dependency from the parent container instead of the current one. + * + * @class Parent + * @constructor + * @extends Resolver + * @param {Object} key The key to resolve from the parent container. + */ Parent = _export("Parent", (function (Resolver) { function Parent(key) { + _classCallCheck(this, Parent); + this.key = key; } @@ -184,6 +370,16 @@ System.register([], function (_export) { _prototypeProperties(Parent, { of: { + + /** + * Creates a Parent Resolver for the supplied key. + * + * @method of + * @static + * @param {Object} key The key to resolve. + * @return {Parent} Returns an insance of Parent for the key. + */ + value: function of(key) { return new Parent(key); }, @@ -192,6 +388,15 @@ System.register([], function (_export) { } }, { get: { + + /** + * Called by the container to load the dependency from the parent container + * + * @method get + * @param {Container} container The container to resolve the parent from. + * @return {Function} Returns the matching instance from the parent container + */ + value: function get(container) { return container.parent ? container.parent.get(this.key) : null; }, diff --git a/dist/system/util.js b/dist/system/util.js index 8e88862..d0bbf1a 100644 --- a/dist/system/util.js +++ b/dist/system/util.js @@ -1,11 +1,9 @@ System.register([], function (_export) { - "use strict"; - _export("isClass", isClass); + // Fix Function#name on browsers that do not support it (IE): function test() {} - function isUpperCase(char) { return char.toUpperCase() === char; } @@ -17,13 +15,18 @@ System.register([], function (_export) { return Object.keys(clsOrFunction.prototype).length > 0; } + return { setters: [], execute: function () { + "use strict"; + if (!test.name) { Object.defineProperty(Function.prototype, "name", { - get: function () { + get: function get() { var name = this.toString().match(/^\s*function\s*(\S*)\s*\(/)[1]; + // For better performance only parse once, and then cache the + // result through a new accessor for repeated access. Object.defineProperty(this, "name", { value: name }); return name; } diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index d31e5d5..e308810 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -1,3 +1,11 @@ +### 0.4.4 (2015-02-27) + + +#### Bug Fixes + +* **package:** update dependencies ([25e924ca](http://github.com/aurelia/dependency-injection/commit/25e924caccdfd033657047a22b93428b90363700)) + + ### 0.4.3 (2015-02-18) diff --git a/package.json b/package.json index 7ae7677..d8ca43c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aurelia-dependency-injection", - "version": "0.4.3", + "version": "0.4.4", "description": "A lightweight, extensible dependency injection container for JavaScript.", "keywords": [ "aurelia",