Skippy is designed to be an easy to use, robust, and well tested dependencies container. No magic inside.
- Instantiate service as described in the dependencies configuration.
- Configure what should be used as service constructor parameters: you can pass another services as reference, parameters, or any values you have configured.
- Manage singleton instance of service (not defined by design pattern, but by configuration).
- Call custom method on service instance to finish it configuration.
- Check the dependencies graph to avoid cyclic dependencies.
- Allowing injection of service mock (only in test environment:
NODE_ENV="test"
).
- Introspect JSDoc or parameters name to determine witch service should be inject in a constructor function. You have to define service dependencies in a configuration file.
- Coffee
- Manage service scope (allowing private service, who can only be used to instantiate other service, not exposed to the world)
- Use factory service to generate another service (delayed, the post service creation hooks do a part of the job for now)
- Generate a lazy loading proxy function (delayed, until ES6 proxy is well supported)
npm install --save skippy
var SkippyFactory = require('skippy').ContainerFactory;
// See configuration section for the configuration details
var services = [/* ... */];
var parameters = {/* ... */}
var container = SkippyFactory.create(services, parameters);
var fooServiceInstance = container.getService('foo');
var barParameterValue = container.getParameter('bar');
container.destroy();
The parameter configuration format is a simple key/value object:
var foo = "foo value";
module.exports = {
"parameterName": "parameterValue",
"foo": foo,
"bar": 42
}
The parameter name should be a string. The value could be anything.
The services configuration format is an array of individual service configuration:
module.exports = [
{
"name": "foo.serviceA",
"service": require("./ServiceA"),
"singleton": true
},
{
"name": "foo.serviceB",
"service": require("./ServiceB"),
"singleton": false,
"arguments": [
"@foo.serviceC"
]
},
{
"name": "foo.serviceC",
"service": require("./ServiceC"),
"arguments": [
"%baz%",
42,
"@foo.serviceA"
]
},
{
"name": "foo.serviceD",
"service": require("./ServiceD"),
"arguments": [
"@foo.serviceA",
"@foo.serviceB"
]
},
{
"name": "foo.serviceD",
"service": require("./ServiceD"),
"calls": {
"setLocale": [
"@foo.serviceB",
"%default.locale%"
]
}
];
A service configuration have four possible keys:
name
(string
, mandatory): the service name.service
(function
, mandatory): the service constructor function reference.singleton
(boolean
, optional, defaulttrue
): Iftrue
, the service will be a singleton. Iffalse
, a new service will be instantiated each time.arguments
(array
, optional, default empty array): An array of the value to inject in the service constructor (see "Arguments" section for more informations).calls
(object
, optional, default empty array): A map of the method to call on the service, each method should have itarguments
array (see "Arguments" section for more informations).
3 types of arguments type:
- A string like
@foo
: use another service as argument value (here an instance of the service namedfoo
). - A string like
%baz%
: use the corresponding parameter value as argument (here thebaz
parameter). - Any other value (scalar, object, function...) will be directly used as an argument.