injector-js
Advanced tools
Comparing version 0.1.1 to 0.2.0
{ | ||
"name": "InjectorJS", | ||
"version": "0.1.1", | ||
"version": "0.2", | ||
"ignore": [ | ||
@@ -11,4 +11,4 @@ "node_modules", | ||
"dependencies": { | ||
"ClazzJS": "~0.3.1" | ||
"ClazzJS": "~0.5.1" | ||
} | ||
} |
@@ -40,4 +40,5 @@ ; | ||
var namespace = ClazzJS.namespace; | ||
var clazz = ClazzJS.clazz; | ||
var meta = ClazzJS.meta; | ||
var clazz = namespace('InjectorJS').get('clazz'); | ||
var meta = namespace('InjectorJS').get('meta'); | ||
var _ = ClazzJS._; | ||
@@ -49,78 +50,140 @@ namespace('InjectorJS', function(clazz, namespace) { | ||
properties: { | ||
factory: { | ||
type: ['hash'], | ||
default: {} | ||
}, | ||
defaultFactory: { | ||
type: ['object', { | ||
instanceOf: 'Factories/Abstract' | ||
}], | ||
converters: { | ||
fromString: function(factory) { | ||
if (_.isUndefined(factory)) { | ||
factory = this.getFactory(factory); | ||
} | ||
return factory; | ||
} | ||
}, | ||
constraints: { | ||
exists: function(factory) { | ||
return this.hasFactory(factory.getName()); | ||
return this.hasFactory(factory); | ||
} | ||
}, | ||
default: function() { | ||
var factory = clazz('Factories/Object').create(); | ||
if (!this.hasFactory(factory)) { | ||
this.setFactory(factory); | ||
} | ||
return factory; | ||
} | ||
}, | ||
factory: { | ||
type: ['hash', { | ||
element: ['object', { | ||
instanceOf: 'Factories/Abstract' | ||
}] | ||
}], | ||
default: {} | ||
}, | ||
object: { | ||
_object: { | ||
type: ['hash'], | ||
default: {} | ||
}, | ||
objectCreator: { | ||
_objectCreator: { | ||
type: ['hash'], | ||
default: {} | ||
}, | ||
getter: { | ||
type: ['function'] | ||
} | ||
}, | ||
methods: { | ||
set: function(name, factory, object) { | ||
var that = this; | ||
var objects = this._resolveObjects(name, factory, object); | ||
_.each(objects, function(factoryObjects, factory) { | ||
_.each(factoryObjects, function(object, name) { | ||
that._setObjectCreator([name], that._createObjectCreator(factory, object)); | ||
}); | ||
}); | ||
return this; | ||
}, | ||
has: function(name) { | ||
return this.hasObject(name) || this.hasObjectCreator(name); | ||
return this._hasObject([name]) || this._hasObjectCreator([name]); | ||
}, | ||
get: function(name) { | ||
if (!this.hasObject(name)) { | ||
if (!this.hasObjectCreator(name)) { | ||
throw new Error('Factory method for object "' + name + "' does not exists!'"); | ||
} | ||
this.setObject(name, this.getObjectCreator(name).call()); | ||
this.removeObjectCreator(name); | ||
this._checkObject(name); | ||
if (!this._hasObject([name])) { | ||
this._setObject([name], this._getObjectCreator([name]).call())._removeObjectCreator([name]); | ||
} | ||
return this._getObject([name]); | ||
}, | ||
return this.getObject(name); | ||
remove: function(name) { | ||
this._checkObject(name); | ||
return (this._hasObject([name]) && this._removeObject([name])) || (this._hasObjectCreator([name]) && this._removeObjectCreator([name])); | ||
}, | ||
set: function( /* (name, type, factory) | (types) */ ) { | ||
if (_.isObject(arguments[0])) { | ||
var factories = arguments[0]; | ||
for (var factory in factories) { | ||
for (var name in factories[factory]) { | ||
this.setObjectCreator(name, this.createObjectCreator(factory, factories[factory][name])); | ||
} | ||
} | ||
} else { | ||
this.setObjectCreator(arguments[0], this.createObjectCreator(arguments[1], arguments[2])); | ||
setFactory: function(fields, value) { | ||
if (_.isUndefined(value)) { | ||
value = fields; | ||
fields = undefined; | ||
} | ||
return this; | ||
if (value && value.__clazz && value.__clazz.__isSubclazzOf('/InjectorJS/Factories/Abstract')) { | ||
return this.__setPropertyValue(['factory', value.getName()], value); | ||
} | ||
return this.__setPropertyValue(['factory'].concat(_.isString(fields) ? fields.split('.') : fields || []), value); | ||
}, | ||
getGetterMethod: function() { | ||
if (!this.hasGetter()) { | ||
var that = this; | ||
hasFactory: function(factory) { | ||
var factoryName = _.isString(factory) ? factory : factory.getName(); | ||
return this.__hasPropertyValue(['factory', factoryName]); | ||
}, | ||
this.setGetter(function(name) { | ||
return that.get(name); | ||
}) | ||
setDefaultFactory: function(factory) { | ||
return this.setFactory(factory); | ||
}, | ||
_checkObject: function(name) { | ||
if (!this.has(name)) { | ||
throw new Error('Object "' + name + "' does not exists!'"); | ||
} | ||
}, | ||
return this.getGetter(); | ||
_resolveObjects: function(name, factory, object) { | ||
var that = this; | ||
var objects = {}; | ||
var defaultFactory = this.getDefaultFactory().getName(); | ||
if (_.isObject(name)) { | ||
objects = name; | ||
} else { | ||
if (_.isUndefined(object)) { | ||
object = factory; | ||
factory = undefined; | ||
} | ||
if (_.isUndefined(factory)) { | ||
factory = defaultFactory; | ||
} | ||
objects[factory] = {}; | ||
objects[factory][name] = object; | ||
} | ||
_.each(objects, function(factoryObjects, factory) { | ||
if (!that.hasFactory(factory)) { | ||
if (!(defaultFactory in objects)) { | ||
objects[defaultFactory] = {}; | ||
} | ||
objects[defaultFactory][factory] = factoryObjects; | ||
delete objects[factory]; | ||
} | ||
}); | ||
return objects; | ||
}, | ||
createObjectCreator: function(factoryName, factoryMethod) { | ||
if (_.isUndefined(factoryName)) { | ||
factoryMethod = factoryName; | ||
_createObjectCreator: function(factoryName, object) { | ||
if (_.isUndefined(object)) { | ||
object = factoryName; | ||
factoryName = undefined; | ||
@@ -130,9 +193,10 @@ } | ||
var that = this; | ||
var factory = !_.isUndefined(factoryName) ? this.getFactory(factoryName) : this.getDefaultFactory(); | ||
return function() { | ||
var params = _.isFunction(factoryMethod) ? factoryMethod.call(factory, that.getGetterMethod()) : factoryMethod; | ||
var factory = !_.isUndefined(factoryName) ? that.getFactory(factoryName) : that.getDefaultFactory(); | ||
return factory.create(params); | ||
var params = _.isFunction(object) ? object.call(that) : object; | ||
return _.isFunction(factory) ? factory(params) : factory.create(params); | ||
} | ||
@@ -145,40 +209,46 @@ } | ||
return { | ||
constants: { | ||
PROCESSORS: { | ||
type: meta('/ClazzJS/Property/Type'), | ||
constraints: meta('/ClazzJS/Property/Constraints'), | ||
converters: meta('/ClazzJS/Property/Converters') | ||
properties: { | ||
processor: { | ||
type: ['hash', { | ||
element: 'function' | ||
}], | ||
default: function() { | ||
return { | ||
type: function(paramValue, metaData, paramName, object) { | ||
return meta('/ClazzJS/Property/Type').apply(paramValue, metaData, paramName, [], object); | ||
}, | ||
constraints: function(paramValue, metaData, paramName, object) { | ||
return meta('/ClazzJS/Property/Constraints').apply(paramValue, metaData, paramName, [], object); | ||
}, | ||
converters: function(paramValue, metaData, paramName, object) { | ||
return meta('/ClazzJS/Property/Converters').apply(paramValue, metaData, paramName, [], object); | ||
}, | ||
default: function(paramValue, metaData, paramName, object) { | ||
if (_.isUndefined(paramValue) || _.isNull(paramValue)) { | ||
paramValue = _.isFunction(metaData) ? metaData.call(object) : metaData; | ||
} | ||
return paramValue; | ||
} | ||
}; | ||
} | ||
} | ||
}, | ||
methods: { | ||
process: function(value, meta, name) { | ||
process: function(paramValue, metaData, paramName, object) { | ||
var options = ['converters', 'constraints', 'default', 'type']; | ||
paramName = paramName || 'unknown'; | ||
object = object || this; | ||
for (var i = 0, ii = options.length; i < ii; ++i) { | ||
if (!(options[i] in meta)) { | ||
continue; | ||
var that = this; | ||
var processors = this.getProcessor(); | ||
_.each(metaData, function(data, option) { | ||
if (!(option in processors)) { | ||
return; | ||
} | ||
switch (options[i]) { | ||
paramValue = processors[option].call(that, paramValue, data, paramName, object); | ||
}); | ||
case 'type': | ||
case 'constraints': | ||
case 'converters': | ||
value = this.const('PROCESSORS')(options[i])().apply(value, meta[options[i]], name); | ||
break; | ||
case 'default': | ||
var defaultValue = meta[options[i]]; | ||
if (_.isFunction(defaultValue)) { | ||
defaultValue = defaultValue.call(); | ||
} | ||
if (_.isUndefined(value) || _.isNull(value)) { | ||
value = defaultValue; | ||
} | ||
break; | ||
} | ||
} | ||
return value; | ||
return paramValue; | ||
} | ||
@@ -189,4 +259,14 @@ } | ||
namespace('Factories', function(clazz) { | ||
clazz('Abstract', function(self, parameterProcessor) { | ||
clazz('Abstract', function(self) { | ||
return { | ||
properties: { | ||
parameterProcessor: { | ||
type: ['object', { | ||
instanceOf: '/InjectorJS/ParameterProcessor' | ||
}], | ||
default: function() { | ||
return clazz('/InjectorJS/ParameterProcessor').create(); | ||
} | ||
} | ||
}, | ||
methods: { | ||
@@ -202,3 +282,3 @@ getName: function() { | ||
}, | ||
getParamsDefinitions: function() { | ||
getParamsDefinition: function() { | ||
return {}; | ||
@@ -208,10 +288,12 @@ }, | ||
var paramsDefinition = this.getParamsDefinitions(); | ||
var that = this; | ||
var paramsDefinition = this.getParamsDefinition(); | ||
var parameterProcessor = this.getParameterProcessor(); | ||
for (var param in params) { | ||
_.each(params, function(value, param) { | ||
if (!(param in paramsDefinition)) { | ||
throw new Error('Parameter "' + param + '" does not defined!'); | ||
} | ||
params[param] = parameterProcessor.process(params[param], paramsDefinition[param], param); | ||
} | ||
params[param] = parameterProcessor.process(value, paramsDefinition[param], param, that); | ||
}); | ||
@@ -223,4 +305,12 @@ return params; | ||
}); | ||
clazz('Clazz', 'Abstract', function(slef, clazz) { | ||
clazz('Clazz', 'Abstract', function(slef) { | ||
return { | ||
properties: { | ||
clazz: { | ||
type: 'function', | ||
default: function() { | ||
return ClazzJS.clazz; | ||
} | ||
} | ||
}, | ||
methods: { | ||
@@ -230,10 +320,9 @@ getName: function() { | ||
}, | ||
getParamsDefinitions: function() { | ||
getParamsDefinition: function() { | ||
return { | ||
name: { | ||
type: ['string'], | ||
required: true | ||
type: 'string' | ||
}, | ||
parent: { | ||
type: ['function'] | ||
type: 'function' | ||
}, | ||
@@ -247,2 +336,3 @@ deps: { | ||
createObject: function(params) { | ||
var clazz = this.getClazz(); | ||
return clazz(params.name, params.parent, params.deps) | ||
@@ -253,7 +343,7 @@ } | ||
}); | ||
clazz('Parameter', 'Abstract', function(self) { | ||
clazz('Object', 'Abstract', function(self) { | ||
return { | ||
methods: { | ||
getName: function() { | ||
return 'parameter'; | ||
return 'object'; | ||
}, | ||
@@ -272,7 +362,7 @@ create: function(value) { | ||
}, | ||
getParamsDefinitions: function() { | ||
getParamsDefinition: function() { | ||
return { | ||
class: { | ||
type: ['function'], | ||
required: true | ||
type: ['function'] | ||
}, | ||
@@ -285,5 +375,3 @@ init: { | ||
type: ['hash', { | ||
element: { | ||
type: 'array' | ||
} | ||
element: 'array' | ||
}], | ||
@@ -294,19 +382,22 @@ default: {} | ||
}, | ||
createObject: function(params) { | ||
var service = construct(params.class, params.init); | ||
for (var method in params.call) { | ||
service[service].apply(service, params.call[method]); | ||
} | ||
// Create '_createService' function for this purpose for parameters applying to clazz constructor. | ||
var service = this._createService(params.class, params.init); | ||
_.each(params.call, function(params, method) { | ||
service[method].apply(service, params); | ||
}); | ||
return service; | ||
}, | ||
function construct(klass, params) { | ||
var K = function() { | ||
return klass.apply(this, params); | ||
}; | ||
K.prototype = klass.prototype; | ||
_createService: function(klass, params) { | ||
var K = function() { | ||
return klass.apply(this, params); | ||
}; | ||
K.prototype = klass.prototype; | ||
return new K(); | ||
} | ||
return new K(); | ||
} | ||
@@ -320,24 +411,21 @@ } | ||
var Injector = clazz('/InjectorJS/Injector'); | ||
var ParameterProcessor = clazz('/InjectorJS/ParameterProcessor'); | ||
var injector = Injector.create(); | ||
var Injector = clazz('Injector'); | ||
var ParameterProcessor = clazz('ParameterProcessor'); | ||
var parameterProcessor = ParameterProcessor.create(); | ||
var AbstractFactory = clazz('/InjectorJS/Factories/Abstract', [parameterProcessor]); | ||
var AbstractFactory = clazz('Factories/Abstract'); | ||
var ParameterFactory = clazz('/InjectorJS/Factories/Parameter', AbstractFactory); | ||
var ClazzFactory = clazz('/InjectorJS/Factories/Clazz', AbstractFactory, [clazz]); | ||
var ServiceFactory = clazz('/InjectorJS/Factories/Service', AbstractFactory); | ||
var ObjectFactory = clazz('Factories/Object', AbstractFactory); | ||
var ClazzFactory = clazz('Factories/Clazz', AbstractFactory); | ||
var ServiceFactory = clazz('Factories/Service', AbstractFactory); | ||
var parameterFactory = ParameterFactory.create(); | ||
var objectFactory = ObjectFactory.create(); | ||
var clazzFactory = ClazzFactory.create(); | ||
var serviceFactory = ServiceFactory.create(); | ||
injector | ||
.setFactory(parameterFactory.getName(), parameterFactory) | ||
.setFactory(clazzFactory.getName(), clazzFactory) | ||
.setFactory(serviceFactory.getName(), serviceFactory) | ||
.setDefaultFactory(parameterFactory); | ||
var injector = Injector.create() | ||
.setFactory(objectFactory) | ||
.setFactory(clazzFactory) | ||
.setFactory(serviceFactory) | ||
.setDefaultFactory(objectFactory); | ||
@@ -347,6 +435,7 @@ return { | ||
Abstract: AbstractFactory, | ||
Parameter: ParameterFactory, | ||
Object: ObjectFactory, | ||
Clazz: ClazzFactory, | ||
Service: ServiceFactory | ||
}, | ||
Injector: Injector, | ||
@@ -353,0 +442,0 @@ ParameterProcessor: ParameterProcessor, |
@@ -1,2 +0,2 @@ | ||
!function(a,b,c,d){if("function"==typeof define&&define.amd)define(b,c,d);else if("object"==typeof exports&&exports){for(var e=0,f=c.length;f>e;++e){var g=c[e];"string"==typeof g&&(g=g.replace(/([A-Z]+)/g,function(a){return"-"+a.toLowerCase()}).replace(/^-/,""),c[e]=require(g))}var h=d.apply(a,c);for(var i in h)exports[i]=h[i]}else{for(var e=0,f=c.length;f>e;++e){var g=c[e];if("string"==typeof g){if(!(g in a))throw new Error('"'+b+'" dependent on non exited module "'+g+'"!');c[e]=a[g]}}a[b]=d.apply(a,c)}}(new Function("return this")(),"InjectorJS",["ClazzJS"],function(a,b){var c=a.namespace,d=a.clazz,e=a.meta;c("InjectorJS",function(a,c){a("Injector",function(a){return{properties:{defaultFactory:{type:["object",{instanceOf:"Factories/Abstract"}],constraints:{exists:function(a){return this.hasFactory(a.getName())}}},factory:{type:["hash",{element:["object",{instanceOf:"Factories/Abstract"}]}],"default":{}},object:{type:["hash"],"default":{}},objectCreator:{type:["hash"],"default":{}},getter:{type:["function"]}},methods:{has:function(a){return this.hasObject(a)||this.hasObjectCreator(a)},get:function(a){if(!this.hasObject(a)){if(!this.hasObjectCreator(a))throw new Error('Factory method for object "'+a+"' does not exists!'");this.setObject(a,this.getObjectCreator(a).call()),this.removeObjectCreator(a)}return this.getObject(a)},set:function(){if(_.isObject(arguments[0])){var a=arguments[0];for(var b in a)for(var c in a[b])this.setObjectCreator(c,this.createObjectCreator(b,a[b][c]))}else this.setObjectCreator(arguments[0],this.createObjectCreator(arguments[1],arguments[2]));return this},getGetterMethod:function(){if(!this.hasGetter()){var a=this;this.setGetter(function(b){return a.get(b)})}return this.getGetter()},createObjectCreator:function(a,c){_.isUndefined(a)&&(c=a,a=b);var d=this,e=_.isUndefined(a)?this.getDefaultFactory():this.getFactory(a);return function(){var a=_.isFunction(c)?c.call(e,d.getGetterMethod()):c;return e.create(a)}}}}}),a("ParameterProcessor",function(a){return{constants:{PROCESSORS:{type:e("/ClazzJS/Property/Type"),constraints:e("/ClazzJS/Property/Constraints"),converters:e("/ClazzJS/Property/Converters")}},methods:{process:function(a,b,c){for(var d=["converters","constraints","default","type"],e=0,f=d.length;f>e;++e)if(d[e]in b)switch(d[e]){case"type":case"constraints":case"converters":a=this.const("PROCESSORS")(d[e])().apply(a,b[d[e]],c);break;case"default":var g=b[d[e]];_.isFunction(g)&&(g=g.call()),(_.isUndefined(a)||_.isNull(a))&&(a=g)}return a}}}}),c("Factories",function(a){a("Abstract",function(a,b){return{methods:{getName:function(){throw new Error("You must specify type name in child clazz!")},create:function(a){return this.createObject(this.processParams(a))},createObject:function(a){throw new Error('You must realize "createObject" method in child clazz!')},getParamsDefinitions:function(){return{}},processParams:function(a){var c=this.getParamsDefinitions();for(var d in a){if(!(d in c))throw new Error('Parameter "'+d+'" does not defined!');a[d]=b.process(a[d],c[d],d)}return a}}}}),a("Clazz","Abstract",function(a,b){return{methods:{getName:function(){return"clazz"},getParamsDefinitions:function(){return{name:{type:["string"],required:!0},parent:{type:["function"]},deps:{type:["array"],"default":[]}}},createObject:function(a){return b(a.name,a.parent,a.deps)}}}}),a("Parameter","Abstract",function(a){return{methods:{getName:function(){return"parameter"},create:function(a){return a}}}}),a("Service","Abstract",function(a){return{methods:{getName:function(){return"service"},getParamsDefinitions:function(){return{"class":{type:["function"],required:!0},init:{type:["array"],"default":[]},call:{type:["hash",{element:{type:"array"}}],"default":{}}}},createObject:function(a){function b(a,b){var c=function(){return a.apply(this,b)};return c.prototype=a.prototype,new c}var c=b(a.class,a.init);for(var d in a.call)c[c].apply(c,a.call[d]);return c}}}})})});var f=d("/InjectorJS/Injector"),g=d("/InjectorJS/ParameterProcessor"),h=f.create(),i=g.create(),j=d("/InjectorJS/Factories/Abstract",[i]),k=d("/InjectorJS/Factories/Parameter",j),l=d("/InjectorJS/Factories/Clazz",j,[d]),m=d("/InjectorJS/Factories/Service",j),n=k.create(),o=l.create(),p=m.create();return h.setFactory(n.getName(),n).setFactory(o.getName(),o).setFactory(p.getName(),p).setDefaultFactory(n),{Factory:{Abstract:j,Parameter:k,Clazz:l,Service:m},Injector:f,ParameterProcessor:g,injector:h,parameterProcessor:i}}); | ||
!function(a,b,c,d){if("function"==typeof define&&define.amd)define(b,c,d);else if("object"==typeof exports&&exports){for(var e=0,f=c.length;f>e;++e){var g=c[e];"string"==typeof g&&(g=g.replace(/([A-Z]+)/g,function(a){return"-"+a.toLowerCase()}).replace(/^-/,""),c[e]=require(g))}var h=d.apply(a,c);for(var i in h)exports[i]=h[i]}else{for(var e=0,f=c.length;f>e;++e){var g=c[e];if("string"==typeof g){if(!(g in a))throw new Error('"'+b+'" dependent on non exited module "'+g+'"!');c[e]=a[g]}}a[b]=d.apply(a,c)}}(new Function("return this")(),"InjectorJS",["ClazzJS"],function(a,b){var c=a.namespace,d=c("InjectorJS").get("clazz"),e=c("InjectorJS").get("meta"),f=a._;c("InjectorJS",function(c,d){c("Injector",function(a){return{properties:{factory:{type:["hash"],"default":{}},defaultFactory:{converters:{fromString:function(a){return f.isUndefined(a)&&(a=this.getFactory(a)),a}},constraints:{exists:function(a){return this.hasFactory(a)}},"default":function(){var a=c("Factories/Object").create();return this.hasFactory(a)||this.setFactory(a),a}},_object:{type:["hash"],"default":{}},_objectCreator:{type:["hash"],"default":{}}},methods:{set:function(a,b,c){var d=this,e=this._resolveObjects(a,b,c);return f.each(e,function(a,b){f.each(a,function(a,c){d._setObjectCreator([c],d._createObjectCreator(b,a))})}),this},has:function(a){return this._hasObject([a])||this._hasObjectCreator([a])},get:function(a){return this._checkObject(a),this._hasObject([a])||this._setObject([a],this._getObjectCreator([a]).call())._removeObjectCreator([a]),this._getObject([a])},remove:function(a){return this._checkObject(a),this._hasObject([a])&&this._removeObject([a])||this._hasObjectCreator([a])&&this._removeObjectCreator([a])},setFactory:function(a,c){return f.isUndefined(c)&&(c=a,a=b),c&&c.__clazz&&c.__clazz.__isSubclazzOf("/InjectorJS/Factories/Abstract")?this.__setPropertyValue(["factory",c.getName()],c):this.__setPropertyValue(["factory"].concat(f.isString(a)?a.split("."):a||[]),c)},hasFactory:function(a){var b=f.isString(a)?a:a.getName();return this.__hasPropertyValue(["factory",b])},setDefaultFactory:function(a){return this.setFactory(a)},_checkObject:function(a){if(!this.has(a))throw new Error('Object "'+a+"' does not exists!'")},_resolveObjects:function(a,c,d){var e=this,g={},h=this.getDefaultFactory().getName();return f.isObject(a)?g=a:(f.isUndefined(d)&&(d=c,c=b),f.isUndefined(c)&&(c=h),g[c]={},g[c][a]=d),f.each(g,function(a,b){e.hasFactory(b)||(h in g||(g[h]={}),g[h][b]=a,delete g[b])}),g},_createObjectCreator:function(a,c){f.isUndefined(c)&&(c=a,a=b);var d=this;return function(){var b=f.isUndefined(a)?d.getDefaultFactory():d.getFactory(a),e=f.isFunction(c)?c.call(d):c;return f.isFunction(b)?b(e):b.create(e)}}}}}),c("ParameterProcessor",function(a){return{properties:{processor:{type:["hash",{element:"function"}],"default":function(){return{type:function(a,b,c,d){return e("/ClazzJS/Property/Type").apply(a,b,c,[],d)},constraints:function(a,b,c,d){return e("/ClazzJS/Property/Constraints").apply(a,b,c,[],d)},converters:function(a,b,c,d){return e("/ClazzJS/Property/Converters").apply(a,b,c,[],d)},"default":function(a,b,c,d){return(f.isUndefined(a)||f.isNull(a))&&(a=f.isFunction(b)?b.call(d):b),a}}}}},methods:{process:function(a,b,c,d){c=c||"unknown",d=d||this;var e=this,g=this.getProcessor();return f.each(b,function(b,f){f in g&&(a=g[f].call(e,a,b,c,d))}),a}}}}),d("Factories",function(b){b("Abstract",function(a){return{properties:{parameterProcessor:{type:["object",{instanceOf:"/InjectorJS/ParameterProcessor"}],"default":function(){return b("/InjectorJS/ParameterProcessor").create()}}},methods:{getName:function(){throw new Error("You must specify type name in child clazz!")},create:function(a){return this.createObject(this.processParams(a))},createObject:function(a){throw new Error('You must realize "createObject" method in child clazz!')},getParamsDefinition:function(){return{}},processParams:function(a){var b=this,c=this.getParamsDefinition(),d=this.getParameterProcessor();return f.each(a,function(e,f){if(!(f in c))throw new Error('Parameter "'+f+'" does not defined!');a[f]=d.process(e,c[f],f,b)}),a}}}}),b("Clazz","Abstract",function(b){return{properties:{clazz:{type:"function","default":function(){return a.clazz}}},methods:{getName:function(){return"clazz"},getParamsDefinition:function(){return{name:{type:"string"},parent:{type:"function"},deps:{type:["array"],"default":[]}}},createObject:function(a){var b=this.getClazz();return b(a.name,a.parent,a.deps)}}}}),b("Object","Abstract",function(a){return{methods:{getName:function(){return"object"},create:function(a){return a}}}}),b("Service","Abstract",function(a){return{methods:{getName:function(){return"service"},getParamsDefinition:function(){return{"class":{type:["function"]},init:{type:["array"],"default":[]},call:{type:["hash",{element:"array"}],"default":{}}}},createObject:function(a){var b=this._createService(a.class,a.init);return f.each(a.call,function(a,c){b[c].apply(b,a)}),b},_createService:function(a,b){var c=function(){return a.apply(this,b)};return c.prototype=a.prototype,new c}}}})})});var g=d("Injector"),h=d("ParameterProcessor"),i=h.create(),j=d("Factories/Abstract"),k=d("Factories/Object",j),l=d("Factories/Clazz",j),m=d("Factories/Service",j),n=k.create(),o=l.create(),p=m.create(),q=g.create().setFactory(n).setFactory(o).setFactory(p).setDefaultFactory(n);return{Factory:{Abstract:j,Object:k,Clazz:l,Service:m},Injector:g,ParameterProcessor:h,injector:q,parameterProcessor:i}}); | ||
//# sourceMappingURL=dist/InjectorJS.min.map |
@@ -7,2 +7,3 @@ "use strict"; | ||
grunt.loadNpmTasks('grunt-contrib-uglify'); | ||
grunt.loadNpmTasks('grunt-contrib-jasmine'); | ||
grunt.loadNpmTasks('grunt-jsbeautifier'); | ||
@@ -26,2 +27,14 @@ | ||
}, | ||
jasmine: { | ||
test: { | ||
src: ["<%= concat.dev.dest %>"], | ||
options: { | ||
specs: ['tests/specs/**/*.js'], | ||
vendor: [ | ||
'node_modules/clazz-js/dist/ClazzJS.js', | ||
'tests/prefix.js' | ||
] | ||
} | ||
} | ||
}, | ||
uglify: { | ||
@@ -47,5 +60,5 @@ min: { | ||
} | ||
}) | ||
}); | ||
grunt.registerTask('default', ['concat', 'uglify', 'jsbeautifier']); | ||
grunt.registerTask('default', ['concat', 'jasmine', 'uglify', 'jsbeautifier']); | ||
}; |
{ | ||
"name": "injector-js", | ||
"title": "InjectorJS", | ||
"version": "0.1.1", | ||
"description": "IoC container for JavaScript", | ||
"author": { | ||
"name": "Aleksey Podskrebyshev (Alex Pods)", | ||
"email": "aleksey.podskrebyshev@gmail.com", | ||
"url": "http://alexpods.com" | ||
}, | ||
"keywords": [ | ||
"dependency", | ||
"injection", | ||
"di", | ||
"ioc", | ||
"container", | ||
"service", | ||
"inject", | ||
"injector", | ||
"dependency injection" | ||
], | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "http://github.com/alexpods/InjectorJS.git" | ||
}, | ||
"dependencies": { | ||
"clazz-js": "~0.3.1" | ||
}, | ||
"devDependencies": { | ||
"grunt": "~0.4.1", | ||
"grunt-contrib-concat": "~0.3.0", | ||
"grunt-contrib-uglify": "~0.2.4", | ||
"grunt-jsbeautifier": "~0.2.3" | ||
}, | ||
"readmeFilename": "README.md" | ||
"name": "injector-js", | ||
"title": "InjectorJS", | ||
"version": "0.2.0", | ||
"description": "Simple Dependency Injection Container for JavaScript", | ||
"author": { | ||
"name": "Aleksey Podskrebyshev (Alex Pods)", | ||
"email": "aleksey.podskrebyshev@gmail.com", | ||
"url": "http://alexpods.com" | ||
}, | ||
"main": "dist/InjectorJS.js", | ||
"keywords": [ | ||
"dependency", | ||
"injection", | ||
"di", | ||
"ioc", | ||
"container", | ||
"service", | ||
"inject", | ||
"injector", | ||
"dependency injection" | ||
], | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "http://github.com/alexpods/InjectorJS.git" | ||
}, | ||
"dependencies": { | ||
"clazz-js": "~0.5.1" | ||
}, | ||
"devDependencies": { | ||
"grunt": "~0.4.2", | ||
"grunt-contrib-concat": "~0.3.0", | ||
"grunt-contrib-uglify": "~0.2.7", | ||
"grunt-contrib-jasmine": "~0.5.2", | ||
"grunt-jsbeautifier": "~0.2.6" | ||
}, | ||
"readmeFilename": "README.md" | ||
} |
135
README.md
InjectorJS | ||
========== | ||
Dependency Injection for JavaScript | ||
InjectorJS is a simple Dependency Injection Container for JavaScript. It helps you to remove of hard-corded | ||
dependencies and make it possible to change them at any time. | ||
Documentation | ||
------------- | ||
> This docs describe many features of the library, but not all. Use source to learn InjectorJS better. | ||
###Installation### | ||
For installation read [related chapter](https://github.com/alexpods/InjectorJS/blob/master/docs/installation.md). | ||
###Usage### | ||
> Online working version of fol;owing examples is available on plunker: http://plnkr.co/edit/SDXdO5. Feel free to play around with it! | ||
Definition of simple objects (parameters): | ||
```js | ||
injector.set('name', 'Bob'); | ||
injector.set('PI', 3.14); | ||
injector.set('currentTime', new Date()); | ||
``` | ||
Defition of objects by factory functions: | ||
```js | ||
injector.set('auto', function() { | ||
return { | ||
color: this.get('auto_color'), | ||
type: this.get('auto_type') | ||
}); | ||
``` | ||
Factory functions has access to current injector making it possible to references to other objects (inject dependencies). | ||
Objects are created only when you require them. These cause to that order of the definitions does not matter and there is no performance penalty. | ||
You can define several objects in one set method call: | ||
```js | ||
injector.set({ | ||
auto_color: function() { | ||
return Math.random() < 0.5 ? 'black' : 'white'; | ||
}, | ||
auto_type: function() { | ||
return Math.random() < 0.5 ? 'hatchback' : 'sedan'; | ||
}, | ||
auto: function() { | ||
return { | ||
color: this.get('auto_color'), | ||
type: this.get('auto_type') | ||
}; | ||
} | ||
}); | ||
``` | ||
You can add object factory to injector to simplify creation of common type objects. Before creation object value will be passed to appropriate object factory: | ||
```js | ||
injector.setFactory('x60', function(value) { | ||
return value*60; | ||
}); | ||
injector.set('hours_in_minutes', 'x60', function() { | ||
return 5; | ||
}); | ||
console.log(injector.get('hours_in_minutes')); // 300 | ||
injector.setFactory('join', { | ||
create: function(strings) { | ||
return strings.join(' '); | ||
} | ||
}); | ||
injector.set('hello', 'join', ['hello', 'world', '!']); | ||
console.log(injector.get('hello')); // hello world ! | ||
``` | ||
As you see object factory can be a function or an object with create method. By default there are 3 object factories: | ||
* Object Factory - default factory - just return object; | ||
* Service Factory - create instances of classes; | ||
* Clazz Factory - create clazzes (see [ClazzJS](https://github.com/alexpods/ClazzJS)) | ||
```js | ||
injector.set({ | ||
service: { | ||
person: function() { | ||
return { | ||
class: this.get('person_class'), | ||
init: [this.get('person_age')], | ||
call: { | ||
setName: [this.get('person_name')] | ||
} | ||
} | ||
} | ||
}, | ||
clazz: { | ||
person_class2: function() { | ||
return { | ||
name: 'Some/Clazz/Name', | ||
parent: 'Some/Clazz/Parent', | ||
deps: [10,20,30] | ||
} | ||
} | ||
}, | ||
person_class: function() { | ||
var Person = function(age) { | ||
this.name = undefined; | ||
this.age = age; | ||
}; | ||
Person.prototype.setName = function(name) { | ||
this.name = name; | ||
} | ||
return Person; | ||
}, | ||
person_age: 10, | ||
person_name: 'Bob' | ||
}); | ||
var person = injector.get('person'); | ||
console.log(person.name); // 'Bob' | ||
console.log(person.age); // 10 | ||
``` | ||
Dependencies | ||
------------ | ||
* ClazzJS (https://github.com/alexpods/ClazzJS) | ||
License | ||
------- | ||
Copyright (c) 2013 Aleksey Podskrebyshev. Licensed under the MIT license. | ||
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/c5cb0521484ffc4a85e86105fef31a0a "githalytics.com")](http://githalytics.com/alexpods/injectorjs) | ||
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/alexpods/injectorjs/trend.png)](https://bitdeli.com/free "Bitdeli Badge") | ||
@@ -1,3 +0,11 @@ | ||
clazz('Abstract', function(self, parameterProcessor) { | ||
clazz('Abstract', function(self) { | ||
return { | ||
properties: { | ||
parameterProcessor: { | ||
type: ['object', { instanceOf: '/InjectorJS/ParameterProcessor' }], | ||
default: function() { | ||
return clazz('/InjectorJS/ParameterProcessor').create(); | ||
} | ||
} | ||
}, | ||
methods: { | ||
@@ -13,3 +21,3 @@ getName: function() { | ||
}, | ||
getParamsDefinitions: function() { | ||
getParamsDefinition: function() { | ||
return {}; | ||
@@ -19,10 +27,12 @@ }, | ||
var paramsDefinition = this.getParamsDefinitions(); | ||
var that = this; | ||
var paramsDefinition = this.getParamsDefinition(); | ||
var parameterProcessor = this.getParameterProcessor(); | ||
for (var param in params) { | ||
_.each(params, function(value, param) { | ||
if (!(param in paramsDefinition)) { | ||
throw new Error('Parameter "' + param + '" does not defined!'); | ||
} | ||
params[param] = parameterProcessor.process(params[param], paramsDefinition[param], param); | ||
} | ||
params[param] = parameterProcessor.process(value, paramsDefinition[param], param, that); | ||
}); | ||
@@ -29,0 +39,0 @@ return params; |
@@ -1,3 +0,11 @@ | ||
clazz('Clazz', 'Abstract', function(slef, clazz) { | ||
clazz('Clazz', 'Abstract', function(slef) { | ||
return { | ||
properties: { | ||
clazz: { | ||
type: 'function', | ||
default: function() { | ||
return ClazzJS.clazz; | ||
} | ||
} | ||
}, | ||
methods: { | ||
@@ -7,10 +15,9 @@ getName: function() { | ||
}, | ||
getParamsDefinitions: function() { | ||
getParamsDefinition: function() { | ||
return { | ||
name: { | ||
type: ['string'], | ||
required: true | ||
type: 'string' | ||
}, | ||
parent: { | ||
type: ['function'] | ||
type: 'function' | ||
}, | ||
@@ -24,2 +31,3 @@ deps: { | ||
createObject: function(params) { | ||
var clazz = this.getClazz(); | ||
return clazz(params.name, params.parent, params.deps) | ||
@@ -26,0 +34,0 @@ } |
@@ -7,7 +7,7 @@ clazz('Service', 'Abstract', function(self) { | ||
}, | ||
getParamsDefinitions: function() { | ||
getParamsDefinition: function() { | ||
return { | ||
class: { | ||
type: ['function'], | ||
required: true | ||
type: ['function'] | ||
}, | ||
@@ -19,3 +19,3 @@ init: { | ||
call: { | ||
type: ['hash', { element: { type: 'array' }}], | ||
type: ['hash', { element: 'array' }], | ||
default: {} | ||
@@ -25,19 +25,22 @@ } | ||
}, | ||
createObject: function(params) { | ||
var service = construct(params.class, params.init); | ||
for (var method in params.call) { | ||
service[service].apply(service, params.call[method]); | ||
} | ||
// Create '_createService' function for this purpose for parameters applying to clazz constructor. | ||
var service = this._createService(params.class, params.init); | ||
_.each(params.call, function(params, method) { | ||
service[method].apply(service, params); | ||
}); | ||
return service; | ||
}, | ||
function construct(klass, params) { | ||
var K = function() { | ||
return klass.apply(this, params); | ||
}; | ||
K.prototype = klass.prototype; | ||
_createService: function(klass, params) { | ||
var K = function() { | ||
return klass.apply(this, params); | ||
}; | ||
K.prototype = klass.prototype; | ||
return new K(); | ||
} | ||
return new K(); | ||
} | ||
@@ -44,0 +47,0 @@ } |
clazz('Injector', function(self) { | ||
return { | ||
properties: { | ||
factory: { | ||
type: ['hash'], | ||
default: {} | ||
}, | ||
defaultFactory: { | ||
type: ['object', { instanceOf: 'Factories/Abstract' }], | ||
converters: { | ||
fromString: function(factory) { | ||
if (_.isUndefined(factory)) { | ||
factory = this.getFactory(factory); | ||
} | ||
return factory; | ||
} | ||
}, | ||
constraints: { | ||
exists: function(factory) { | ||
return this.hasFactory(factory.getName()); | ||
return this.hasFactory(factory); | ||
} | ||
}, | ||
default: function() { | ||
var factory = clazz('Factories/Object').create(); | ||
if (!this.hasFactory(factory)) { | ||
this.setFactory(factory); | ||
} | ||
return factory; | ||
} | ||
}, | ||
factory: { | ||
type: ['hash', { element: ['object', { instanceOf: 'Factories/Abstract' }] }], | ||
default: {} | ||
}, | ||
object: { | ||
_object: { | ||
type: ['hash'], | ||
default: {} | ||
}, | ||
objectCreator: { | ||
_objectCreator: { | ||
type: ['hash'], | ||
default: {} | ||
}, | ||
getter: { | ||
type: ['function'] | ||
} | ||
}, | ||
methods: { | ||
set: function(name, factory, object) { | ||
var that = this; | ||
var objects = this._resolveObjects(name, factory, object); | ||
_.each(objects, function(factoryObjects, factory) { | ||
_.each(factoryObjects, function(object, name) { | ||
that._setObjectCreator([name], that._createObjectCreator(factory, object)); | ||
}); | ||
}); | ||
return this; | ||
}, | ||
has: function(name) { | ||
return this.hasObject(name) || this.hasObjectCreator(name); | ||
return this._hasObject([name]) || this._hasObjectCreator([name]); | ||
}, | ||
get: function(name) { | ||
if (!this.hasObject(name)) { | ||
if (!this.hasObjectCreator(name)) { | ||
throw new Error('Factory method for object "' + name + "' does not exists!'"); | ||
} | ||
this.setObject(name, this.getObjectCreator(name).call()); | ||
this.removeObjectCreator(name); | ||
this._checkObject(name); | ||
if (!this._hasObject([name])) { | ||
this._setObject([name], this._getObjectCreator([name]).call())._removeObjectCreator([name]); | ||
} | ||
return this._getObject([name]); | ||
}, | ||
return this.getObject(name); | ||
remove: function(name) { | ||
this._checkObject(name); | ||
return (this._hasObject([name]) && this._removeObject([name])) | ||
|| (this._hasObjectCreator([name]) && this._removeObjectCreator([name])); | ||
}, | ||
set: function(/* (name, type, factory) | (types) */) { | ||
if (_.isObject(arguments[0])) { | ||
var factories = arguments[0]; | ||
for (var factory in factories) { | ||
for (var name in factories[factory]) { | ||
this.setObjectCreator(name, this.createObjectCreator(factory, factories[factory][name])); | ||
} | ||
} | ||
setFactory: function(fields, value) { | ||
if (_.isUndefined(value)) { | ||
value = fields; | ||
fields = undefined; | ||
} | ||
else { | ||
this.setObjectCreator(arguments[0], this.createObjectCreator(arguments[1], arguments[2])); | ||
if (value && value.__clazz && value.__clazz.__isSubclazzOf('/InjectorJS/Factories/Abstract')) { | ||
return this.__setPropertyValue(['factory', value.getName()], value); | ||
} | ||
return this; | ||
return this.__setPropertyValue(['factory'].concat(_.isString(fields) ? fields.split('.') : fields || []), value); | ||
}, | ||
getGetterMethod: function() { | ||
if (!this.hasGetter()) { | ||
var that = this; | ||
hasFactory: function(factory) { | ||
var factoryName = _.isString(factory) ? factory : factory.getName(); | ||
return this.__hasPropertyValue(['factory', factoryName]); | ||
}, | ||
this.setGetter(function(name) { | ||
return that.get(name); | ||
}) | ||
setDefaultFactory: function(factory) { | ||
return this.setFactory(factory); | ||
}, | ||
_checkObject: function(name) { | ||
if (!this.has(name)) { | ||
throw new Error('Object "' + name + "' does not exists!'"); | ||
} | ||
return this.getGetter(); | ||
}, | ||
createObjectCreator: function(factoryName, factoryMethod) { | ||
_resolveObjects: function(name, factory, object) { | ||
if (_.isUndefined(factoryName)) { | ||
factoryMethod = factoryName; | ||
factoryName = undefined; | ||
var that = this; | ||
var objects = {}; | ||
var defaultFactory = this.getDefaultFactory().getName(); | ||
if (_.isObject(name)) { | ||
objects = name; | ||
} | ||
else { | ||
if (_.isUndefined(object)) { | ||
object = factory; | ||
factory = undefined; | ||
} | ||
if (_.isUndefined(factory)) { | ||
factory = defaultFactory; | ||
} | ||
objects[factory] = {}; | ||
objects[factory][name] = object; | ||
} | ||
_.each(objects, function(factoryObjects, factory) { | ||
if (!that.hasFactory(factory)) { | ||
if (!(defaultFactory in objects)) { | ||
objects[defaultFactory] = {}; | ||
} | ||
objects[defaultFactory][factory] = factoryObjects; | ||
delete objects[factory]; | ||
} | ||
}); | ||
return objects; | ||
}, | ||
_createObjectCreator: function(factoryName, object) { | ||
if (_.isUndefined(object)) { | ||
object = factoryName; | ||
factoryName = undefined; | ||
} | ||
var that = this; | ||
var factory = !_.isUndefined(factoryName) ? this.getFactory(factoryName) : this.getDefaultFactory(); | ||
return function() { | ||
var params = _.isFunction(factoryMethod) | ||
? factoryMethod.call(factory, that.getGetterMethod()) | ||
: factoryMethod; | ||
var factory = !_.isUndefined(factoryName) | ||
? that.getFactory(factoryName) | ||
: that.getDefaultFactory(); | ||
return factory.create(params); | ||
var params = _.isFunction(object) | ||
? object.call(that) | ||
: object; | ||
return _.isFunction(factory) ? factory(params) : factory.create(params); | ||
} | ||
@@ -89,0 +161,0 @@ } |
clazz('ParameterProcessor', function(self) { | ||
return { | ||
constants: { | ||
PROCESSORS: { | ||
type: meta('/ClazzJS/Property/Type'), | ||
constraints: meta('/ClazzJS/Property/Constraints'), | ||
converters: meta('/ClazzJS/Property/Converters') | ||
properties: { | ||
processor: { | ||
type: ['hash', { element: 'function' }], | ||
default: function() { | ||
return { | ||
type: function(paramValue, metaData, paramName, object) { | ||
return meta('/ClazzJS/Property/Type').apply(paramValue, metaData, paramName, [], object); | ||
}, | ||
constraints: function(paramValue, metaData, paramName, object) { | ||
return meta('/ClazzJS/Property/Constraints').apply(paramValue, metaData, paramName, [], object); | ||
}, | ||
converters: function(paramValue, metaData, paramName, object) { | ||
return meta('/ClazzJS/Property/Converters').apply(paramValue, metaData, paramName, [], object); | ||
}, | ||
default: function(paramValue, metaData, paramName, object) { | ||
if (_.isUndefined(paramValue) || _.isNull(paramValue)) { | ||
paramValue = _.isFunction(metaData) | ||
? metaData.call(object) | ||
: metaData; | ||
} | ||
return paramValue; | ||
} | ||
}; | ||
} | ||
} | ||
}, | ||
methods: { | ||
process: function(value, meta, name) { | ||
process: function(paramValue, metaData, paramName, object) { | ||
var options = ['converters', 'constraints', 'default', 'type']; | ||
paramName = paramName || 'unknown'; | ||
object = object || this; | ||
for (var i = 0, ii = options.length; i < ii; ++i) { | ||
if (!(options[i] in meta)) { | ||
continue; | ||
var that = this; | ||
var processors = this.getProcessor(); | ||
_.each(metaData, function(data, option) { | ||
if (!(option in processors)) { | ||
return; | ||
} | ||
switch (options[i]) { | ||
paramValue = processors[option].call(that, paramValue, data, paramName, object); | ||
}); | ||
case 'type': | ||
case 'constraints': | ||
case 'converters': | ||
value = this.const('PROCESSORS')(options[i])().apply(value, meta[options[i]], name); | ||
break; | ||
case 'default': | ||
var defaultValue = meta[options[i]]; | ||
if (_.isFunction(defaultValue)) { | ||
defaultValue = defaultValue.call(); | ||
} | ||
if (_.isUndefined(value) || _.isNull(value)) { | ||
value = defaultValue; | ||
} | ||
break; | ||
} | ||
} | ||
return value; | ||
return paramValue; | ||
} | ||
@@ -42,0 +48,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
54867
26
945
142
5
3
+ Addedclazz-js@0.5.2(transitive)
- Removedclazz-js@0.3.3(transitive)
Updatedclazz-js@~0.5.1