
container-ioc
is a Dependency Injection / Inversion of Control (IoC) container package for Javascript and Node.js applications powered by Typescript . It manages the dependencies between classes, so that applications stay easy to change and maintain as they grow.

Features:
- Well-known Angular DI API.
- No external dependencies.
- Life Time control.
- Hierarchical containers.
- Resolves values using Classes, Factories and Values.
- Descriptive error messages.
- 97% test coverage.
Quick start
Installation:
npm install --save container-ioc
Typescript:
import { Container, Inject, Injectable } from 'container-ioc';
let container = new Container();
@Injectable()
class App {}
interface IService {}
@Injectable()
class Service implements IService {
constructor(@Inject('IService') public service: IService) {}
}
let providers = [
{ token: App, useClass: App },
{ token: 'IService', useClass: Service }
];
container.register(providers);
let app = container.resolve(App);
Javascript:
Use alternative syntax for declaring injections shown below and don't use interfaces. See examples/javascript for more.
@Injectable(['IService'])
class Service {
constructor(service) {
this.service = service;
}
}
Examples:
Code examples below are written in Typescript.
Life Time control.
By default, containers resolve singletons. You can change that by setting provider's attribute LifeTime to LifeTime.PerRequest.
import { Container, Injectable, LifeTime } from 'container-ioc';
const container = new Container();
@Injectable()
class A {}
container.register([
{ token: A, useClass: A, lifeTime: LifeTime.PerRequest }
]);
const instance1 = container.resolve(A);
const instance2 = container.resolve(A);
Hierarchical containers.
If a provider wasn't found in a container it will look up in ascendant containers if there are any:
import { Container } from 'container-ioc';
@Injectable()
class A {}
let parentContainer = new Container();
let childContainer = parentContainer.createScope();
parentContainer.register({ token: 'IA', useClass: A });
childContainer.resolve('IA');
Using Factories
container.register([
{
token: 'TokenForFactory',
useFactory: () => {
return 'any-value';
}
}
]);
container.register([
{ token: 'EnvProvider', useClass: EnvProvider },
{
token: 'TokenForFactory',
useFactory: (envProvider) => {
return 'something';
},
inject: ['EnvProvider']
}
]);
Using Values
container.register([
{ token: 'IConfig', useValue: {}}
]);
Shortcut for Classes
container.register([
App
]);
Is the same as:
container.register([
{ token: App, useClass: App }
]);
Best Practise, use InjectionToken
Use InjectionToken instances for tokens instead of string/class literals,
it saves from using hardcoded string and helps in keeping abstractions intact.
Before:
interface IService {}
@Injectable()
class ConcreteService {}
container.register({ token: 'IService', useClass: ConcreteService });
container.resolve('IService');
After:
interface IService {}
const TService = new InjectionToken<IService>('IService');
@Injectable()
class ConcreteService {}
container.register({ token: TService, useClass: ConcreteService });
container.resolve(TService);
Contribution:
Become a contributor to this project. Feel free to submit an issue or a pull request.
see CONTRIBUTION.md for more information.