Comparing version 0.6.0 to 0.7.0
;(function(undefined) { | ||
'use strict'; | ||
/** | ||
* BottleJS v0.6.0 - 2014-10-19 | ||
* BottleJS v0.7.0 - 2014-12-06 | ||
* A powerful, extensible dependency injection micro container | ||
@@ -26,2 +26,20 @@ * | ||
/** | ||
* Map of fullnames by index => name | ||
* | ||
* @type Array | ||
*/ | ||
var fullnameMap = []; | ||
/** | ||
* Iterator used to flatten arrays with reduce. | ||
* | ||
* @param Array a | ||
* @param Array b | ||
* @return Array | ||
*/ | ||
var concatIterator = function concatIterator(a, b) { | ||
return a.concat(b); | ||
}; | ||
/** | ||
* Get a group (middleware, decorator, etc.) for this bottle instance and service name. | ||
@@ -39,9 +57,46 @@ * | ||
} | ||
if (!group[name]) { | ||
if (name && !group[name]) { | ||
group[name] = []; | ||
} | ||
return group[name]; | ||
return name ? group[name] : group; | ||
}; | ||
/** | ||
* Will try to get all things from a collection by name, by __global__, and by mapped names. | ||
* | ||
* @param Array collection | ||
* @param Number id | ||
* @param String name | ||
* @return Array | ||
*/ | ||
var getAllWithMapped = function(collection, id, name) { | ||
return get(fullnameMap, id, name) | ||
.map(getMapped.bind(null, collection)) | ||
.reduce(concatIterator, get(collection, id, name)) | ||
.concat(get(collection, id, '__global__')); | ||
}; | ||
/** | ||
* Iterator used to get decorators from a map | ||
* | ||
* @param Array collection | ||
* @param Object data | ||
* @return Function | ||
*/ | ||
var getMapped = function getMapped(collection, data) { | ||
return get(collection, data.id, data.fullname); | ||
}; | ||
/** | ||
* Iterator used to walk down a nested object. | ||
* | ||
* @param Object obj | ||
* @param String prop | ||
* @return mixed | ||
*/ | ||
var getNested = function getNested(obj, prop) { | ||
return obj[prop]; | ||
}; | ||
/** | ||
* A helper function for pushing middleware and decorators onto their stacks. | ||
@@ -69,3 +124,10 @@ * | ||
var constant = function constant(name, value) { | ||
Object.defineProperty(this.container, name, { | ||
var parts = name.split('.'); | ||
name = parts.pop(); | ||
defineConstant.call(parts.reduce(setValueObject, this.container), name, value); | ||
return this; | ||
}; | ||
var defineConstant = function defineConstant(name, value) { | ||
Object.defineProperty(this, name, { | ||
configurable : false, | ||
@@ -76,4 +138,2 @@ enumerable : true, | ||
}); | ||
return this; | ||
}; | ||
@@ -118,4 +178,10 @@ | ||
var getService = function(service) { | ||
return this.container[service]; | ||
/** | ||
* Get a service stored under a nested key | ||
* | ||
* @param String fullname | ||
* @return Service | ||
*/ | ||
var getNestedService = function getNestedService(fullname) { | ||
return fullname.split('.').reduce(getNested, this); | ||
}; | ||
@@ -126,7 +192,7 @@ | ||
* | ||
* @param array services | ||
* @return array Array of instances (in the order they were provided) | ||
* @param Array services | ||
* @return Array Array of instances (in the order they were provided) | ||
*/ | ||
var digest = function digest(services) { | ||
return (services || []).map(getService, this); | ||
return (services || []).map(getNestedService, this.container); | ||
}; | ||
@@ -163,4 +229,4 @@ | ||
*/ | ||
var applyMiddleware = function(id, name, instance, container) { | ||
var middleware = get(middles, id, '__global__').concat(get(middles, id, name)); | ||
var applyMiddleware = function applyMiddleware(id, name, instance, container) { | ||
var middleware = getAllWithMapped(middles, id, name); | ||
var descriptor = { | ||
@@ -173,3 +239,3 @@ configurable : true, | ||
var index = 0; | ||
var next = function() { | ||
var next = function nextMiddleware() { | ||
if (middleware[index]) { | ||
@@ -233,15 +299,15 @@ middleware[index++](instance, next); | ||
/** | ||
* Map of nested bottles by index => name | ||
* | ||
* @type Array | ||
*/ | ||
var nestedBottles = []; | ||
/** | ||
* Map of provider constructors by index => name | ||
* | ||
* @type Object | ||
* @type Array | ||
*/ | ||
var providers = []; | ||
var providerMap = []; | ||
var getProviders = function(id) { | ||
if (!providers[id]) { | ||
providers[id] = {}; | ||
} | ||
return providers[id]; | ||
}; | ||
/** | ||
@@ -261,17 +327,36 @@ * Used to process decorators in the provider | ||
* | ||
* @param String name | ||
* @param String fullname | ||
* @param Function Provider | ||
* @return Bottle | ||
*/ | ||
var provider = function provider(name, Provider) { | ||
var providerName, providers, properties, container, id; | ||
var provider = function provider(fullname, Provider) { | ||
var parts, providers, name, id, factory; | ||
id = this.id; | ||
providers = getProviders(id); | ||
if (providers[name]) { | ||
return console.error(name + ' provider already registered.'); | ||
providers = get(providerMap, id); | ||
if (providers[fullname]) { | ||
return console.error(fullname + ' provider already registered.'); | ||
} | ||
providers[fullname] = true; | ||
parts = fullname.split('.'); | ||
name = parts.shift(); | ||
factory = parts.length ? createSubProvider : createProvider; | ||
return factory.call(this, name, Provider, fullname, parts); | ||
}; | ||
/** | ||
* Create the provider properties on the container | ||
* | ||
* @param String fullname | ||
* @param String name | ||
* @param Function Provider | ||
* @return Bottle | ||
*/ | ||
var createProvider = function createProvider(name, Provider) { | ||
var providerName, properties, container, id; | ||
id = this.id; | ||
container = this.container; | ||
providers[name] = Provider; | ||
providerName = name + 'Provider'; | ||
@@ -284,8 +369,5 @@ | ||
get : function getProvider() { | ||
var Constructor = providers[name], instance; | ||
if (Constructor) { | ||
instance = new Constructor(); | ||
delete container[providerName]; | ||
container[providerName] = instance; | ||
} | ||
var instance = new Provider(); | ||
delete container[providerName]; | ||
container[providerName] = instance; | ||
return instance; | ||
@@ -301,3 +383,2 @@ } | ||
var instance; | ||
if (provider) { | ||
@@ -308,4 +389,3 @@ delete container[providerName]; | ||
// filter through decorators | ||
instance = get(decorators, id, '__global__') | ||
.concat(get(decorators, id, name)) | ||
instance = getAllWithMapped(decorators, id, name) | ||
.reduce(reducer, provider.$get(container)); | ||
@@ -322,2 +402,29 @@ } | ||
/** | ||
* Creates a bottle container on the current bottle container, and registers | ||
* the provider under the sub container. | ||
* | ||
* @param String name | ||
* @param Function Provider | ||
* @param String fullname | ||
* @param Array parts | ||
* @return Bottle | ||
*/ | ||
var createSubProvider = function createSubProvider(name, Provider, fullname, parts) { | ||
var bottle, bottles, subname, id; | ||
id = this.id; | ||
bottles = get(nestedBottles, id); | ||
bottle = bottles[name]; | ||
if (!bottle) { | ||
this.container[name] = (bottle = bottles[name] = Bottle.pop()).container; | ||
} | ||
subname = parts.join('.'); | ||
bottle.provider(subname, Provider); | ||
set(fullnameMap, bottle.id, subname, { fullname : fullname, id : id }); | ||
return this; | ||
}; | ||
/** | ||
* Register a service, factory, provider, or value based on properties on the object. | ||
@@ -353,12 +460,2 @@ * | ||
/** | ||
* Map used to inject dependencies in the generic factory; | ||
* | ||
* @param String key | ||
* @return mixed | ||
*/ | ||
var mapContainer = function mapContainer(key) { | ||
return this.container[key]; | ||
}; | ||
/** | ||
* Register a service inside a generic factory. | ||
@@ -373,5 +470,5 @@ * | ||
var bottle = this; | ||
return factory.call(bottle, name, function GenericFactory() { | ||
return factory.call(this, name, function GenericFactory() { | ||
if (deps) { | ||
Service = Service.bind.apply(Service, deps.map(mapContainer, bottle)); | ||
Service = Service.bind.apply(Service, deps.map(getNested.bind(bottle, bottle.container))); | ||
} | ||
@@ -390,3 +487,31 @@ return new Service(); | ||
var value = function value(name, val) { | ||
Object.defineProperty(this.container, name, { | ||
var parts; | ||
parts = name.split('.'); | ||
name = parts.pop(); | ||
defineValue.call(parts.reduce(setValueObject, this.container), name, val); | ||
return this; | ||
}; | ||
/** | ||
* Iterator for setting a plain object literal via defineValue | ||
* | ||
* @param Object container | ||
* @param string name | ||
*/ | ||
var setValueObject = function setValueObject(container, name) { | ||
var newContainer = {}; | ||
defineValue.call(container, name, newContainer); | ||
return newContainer; | ||
}; | ||
/** | ||
* Define a mutable property on the container. | ||
* | ||
* @param String name | ||
* @param mixed val | ||
* @return void | ||
* @scope container | ||
*/ | ||
var defineValue = function defineValue(name, val) { | ||
Object.defineProperty(this, name, { | ||
configurable : true, | ||
@@ -397,4 +522,2 @@ enumerable : true, | ||
}); | ||
return this; | ||
}; | ||
@@ -401,0 +524,0 @@ |
{ | ||
"name": "bottlejs", | ||
"version": "0.6.0", | ||
"version": "0.7.0", | ||
"description": "A powerful, extensible dependency injection micro container", | ||
@@ -5,0 +5,0 @@ "main": "dist/bottle.js", |
@@ -168,3 +168,3 @@ | ||
bottle.decorator('Beer', function(beer, next) { | ||
bottle.middleware('Beer', function(beer, next) { | ||
// this middleware will only affect the Beer service. | ||
@@ -171,0 +171,0 @@ console.log('Beer? Nice. Tip your bartender...'); |
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
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
30768
545