typesoft / container-ioc

Inversion of Control container & Dependency Injection for Javascript and Node.js apps powered by Typescript.
https://www.npmjs.com/package/container-ioc
MIT License
102 stars 25 forks source link
container dependency dependency-injection dependency-manager di es2015 es2016 es2017 es6 factory inject injection injector inversion-of-control ioc lifetime service-locator typescript

alt text

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.

npm version Build Status npm Gitter chat license

Features:

Examples:

Installation:

npm install --save container-ioc

Basics:

Code examples below are written in Typescript. Check examples/javascript for examples written in Javascript.

Step 1. Define your interfaces and types.

Possible values for types: Symbol, string, Object.

interface IApplication {
    run(): void;
}

interface IService {
    serve(): void;
}

const TApplication = Symbol('IApplication');

const TService = Symbol('IService');

Step 2. Declare dependencies with decorators Injectable and Inject.

import { Injectable, Inject } from 'container-ioc';

@Injectable()
export class Application implements IApplication {
    constructor(@Inject(TService) private service: IService) {}

    run(): void {
        this.service.serve();
    }
}

@Injectable()
export class Service implements IService {
    serve(): void {
        // serves
    }
}

Step 3. Create a container and register types in there.

import { Container } from 'container-ioc';

let container = new Container();

container.register([
    { token: TApplication, useClass: Application },
    { token: TService, useClass: Service }
]);

Step 4. Resolve value from the container.

let app = container.resolve(TApplication);

app.run();

Step 2 for Javascript.

Since Javascript does not support parameter decorators, use alternative API for declaring dependencies. In this case we don't use Inject decorator. See examples/javascript for more.

@Injectable([TService]) class Service { constructor(service) { this.service = service; } }


### Life Time control
> By default, containers resolve singletons when using **useClass** and **useFactory**.
Default life time for all items in a container can be set by passing an option object to it's contructor with **defailtLifeTime** attribute. Possible values: **LifeTime.PerRequest** (resolves instances) and **LifeTime.Persistent** (resolves singletons);

```typescript
import { LifeTime } from 'container-ioc';

const container = new Container({
    defaultLifeTime: LifeTime.PerRequest
});

You can also specify life time individually for each item in a container by specifying lifeTime attribute.

container.register([
    {
        token: TService,
        useClass: Service,
        lifeTime: LifeTime.PerRequest
    }
]);
container.register([
    {
        token: TService,
        useFactory: () => {
            return {
                serve(): void {}
            }
        },
        lifeTime: LifeTime.Persistent
    }
]);

Hierarchical containers

If a container can't find a value within itself, it will look it up in ascendant containers. There a 3 ways to set a parent for a container.

1. Container.createChild() method.
const parentContainer = new Container();
const childContainer = parentContainer.createChild();
2. Container.setParent() method.
const parent = new Container();
const child = new Container();

child.setParent(parent);
3. Via Container's constructor with options.
const parent = new Container();
const child = new Container({
    parent: parent
});

Using Factories

/* Without injections */
container.register([
    {
        token: 'TokenForFactory',
        useFactory: () => {
            return 'any-value';
        }
    }
]);

/* With injections */
container.register([
    { token: 'EnvProvider', useClass: EnvProvider },
    {
        token: 'TokenForFactory',
        useFactory: (envProvider) => {
            // do something
            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 }
]);

Contribution

Become a contributor to this project. Feel free to submit an issue or a pull request.

see CONTRIBUTION.md for more information.

Please see also our Code of Conduct.