injektor
Version:
The simple dependency injection for Devebot
266 lines (198 loc) • 7.12 kB
Markdown
# injektor
[](https://nodei.co/npm/injektor/)
With injektor (and almost of dependency injection libraries), a developer can manage the service objects in a common "place" called **container** and doesn't care about assigning the dependent parameters to a service when it is invoked.
## Usage
### Installation
Install injektor module:
```shell
$ npm install --save injektor
```
### Example
In your program, create the container:
```javascript
var Injektor = require('injektor');
var injektor = new Injektor();
```
Register an object or define a service with some dependencies as follows:
```javascript
injektor
.registerObject('greeting', {
greet: function() {
return 'Hello world!';
}
});
injektor
.defineService('service1', function(fullname) {
var self = fullname;
this.sayHello = function(name) {
console.log('Hello ' + name + ". I'm " + self);
};
})
.registerObject('fullname', 'Computer');
injektor
.defineService('service2', function() {
this.sayWellcome = function(name) {
console.log('Wellcome to ' + name);
};
});
```
Uses the `lookup()` method to get services or `invoke()` method to evaluate the services:
```javascript
injektor.lookup('service1').sayHello('Ubuntu');
injektor.invoke(function (greeting, service1, service2) {
console.log(greeting.greet());
console.log('\n');
service1.sayHello('Injektor');
service2.sayWellcome('Vietnam');
});
```
The console will display the text below:
```plain
Hello world!
Hello Injektor. I'm Computer
Wellcome to Vietnam
```
## API
### Constructor
#### `new Injektor(args)`
`args` can be:
* `args.detectCyclicDependencies` - enables/disables dependency cycle detection (default: `true`).
* `args.nameResolvingStrictMode` - enables/disables name resolving strict mode (default: `false`).
* `args.allowLookupDuplicateNames` - allows to return the fisrt matching name of duplicate short names (default: `false`).
* `args.separator` - delimiter character (default: `/`).
Example:
```javascript
var Injektor = require('injektor');
var injektor = new Injektor({
separator: ':'
});
```
### Methods
#### `injektor.defineService(name, constructor, opts)`
Method `defineService()` registers a service name with its constructor. The parameters include:
* `name` - a case-sensitive string that presents the name of the defined service. The name must contain only letters, digits and underscore characters. It must start with a letter.
* `constructor` - a function that is used with the `new` operator to create a new object.
This object is cached by `injektor` and returned by `lookup()`.
* `opts.scope` - a namespace of the scope in which this service/object belongs to.
* `opts.exceptions` - a reference to an empty array that will collect thrown exceptions (if any) and prevent function crack.
Method `defineService()` returns the `injektor` object itself.
#### `injektor.registerObject(name, valueOrObject, opts)`
Method `registerObject()` registers an object or a value (`number`, `boolean`, `null`,...) with its name. The parameters are similar to `defineService()` method, excepts the second parameter is a value or an object. It also returns the `injektor` object.
#### `injektor.lookup(name, opts)`
Method `lookup()` instantiates a service with injected dependencies into object, caches it for the next use, and returns it. This method contains the following parameters:
* `name` - the name of a service or an object that should be retrieved.
* `opts.scope` - a namespace of the scope in which this method finds the service or the object (default: undefined).
* `opts.exceptions` - similar to `defineService()` method (default: undefined).
#### `injektor.invoke(name_1, ..., name_n, callback)`
Method `invoke()` retrieves an array of services or objects that are identified by
`name_1, ..., name_n`, and push them as the parameters to the `callback` function.
This method will return the `callback`'s returned value.
## Dependency Annotations
### Object schema annotation
```javascript
var Injektor = require('injektor');
var injektor = new Injektor();
var MyResource = function(params) {
params = params || {};
var fullname = params.fullname;
var document = params.document;
this.process = function(action) {
console.log('The developer %s will %s the document %s',
fullname, action, JSON.stringify(document));
};
};
MyResource.argumentSchema = {
"type": "object",
"properties": {
"fullname": { "type": "string" },
"document": { "type": "object" }
}
};
injektor
.defineService('myResource', MyResource)
.registerObject('fullname', 'Peter Pan')
.registerObject('document', {
type: 'Book',
content: 'Peter and Wendy'
});
injektor.lookup('myResource').process('open');
```
The console will display the following text:
```plain
The developer Peter Pan will open the document {"type":"Book","content":"Peter and Wendy"}
```
### Object properties annotation
```javascript
var Injektor = require('injektor');
var injektor = new Injektor();
var MyResource = function(params) {
params = params || {};
var fullname = params.fullname;
var document = params.document;
this.process = function(action) {
console.log('The developer %s will %s the document %s',
fullname, action, JSON.stringify(document));
};
};
MyResource.argumentProperties = [ "fullname", "document" ];
injektor
.defineService('myResource', MyResource)
.registerObject('fullname', 'Peter Pan')
.registerObject('document', {
type: 'Book',
content: 'Peter and Wendy'
});
injektor.lookup('myResource').process('open');
```
The console will display the following text:
```plain
The developer Peter Pan will open the document {"type":"Book","content":"Peter and Wendy"}
```
### Explicit name annotation
```javascript
var Injektor = require('injektor');
var injektor = new Injektor();
injektor
.defineService('recipe', ['steps', 'object',
function(steps, object) {
steps = steps || [];
this.action = function(name) {
console.log('Hello, the instruction of %s is:', name);
steps.forEach(function(step) {
console.log(' - %s the %s', step, object);
});
};
}
])
.registerObject('steps', [
'clean', 'boil', 'peel', 'eat'
])
.registerObject('object', 'Eggs');
injektor
.invoke(['recipe', function(rp) {
rp.action('Peter Pan');
}]);
```
### Implicit name annotation
```javascript
var Injektor = require('injektor');
var injektor = new Injektor();
injektor
.defineService('recipe', function(steps, object) {
steps = steps || [];
this.action = function(name) {
console.log('Hello, the instruction of %s is:', name);
steps.forEach(function(step) {
console.log(' - %s the %s', step, object);
});
};
});
injektor
.registerObject('steps', [
'clean', 'boil', 'peel', 'eat'
])
.registerObject('object', 'Eggs');
injektor.lookup('recipe').action('Peter Pan');
```
## License
MIT