2.0.1 • Published 5 years ago

peppermint-di v2.0.1

Weekly downloads
2
License
MIT
Repository
github
Last release
5 years ago

peppermint-di

Dependency injection container for TypeScript and JavaScript.

npm version npm license CircleCI dependencies

Installation

yarn add peppermint-di

or

npm install --save peppermint-di

The gist

import { Container, injectable } from 'peppermint-di';

class SomeService {
    // ...
}

@injectable
class SomeClass {
    constructor(someService: SomeService) {
        // ...
    }
}


const container = new Container();

container.registerSingle(SomeService)

const myClass = container.get(SomeClass);

Table of Content

Credits

This project was originally based on this blog post by Yusuf Aytas as it appeared in this StackOverflow question.
The API is somewhat inspired by the excellent Simple Injector C# library.

Examples

TypeScript

Custom parameters

import { Container, injectable } from 'peppermint-di';

class SomeService {
    public name = 'default name';
}

@injectable
class MyClass {

    public myService: SomeService;

    constructor(myService: SomeService) {
        this.myService = myService;
    }
}

const container = new Container();

const customDep = new SomeService();
customDep.name = 'custom name';

const customParameters = new Map([
    [SomeService, customDep]
]);
const myClass = container.get(MyClass, { params: customParameters });

expect(myClass.myService).to.be.instanceOf(SomeService);
expect(myClass.myService.name).to.eql('custom name');

Interface registration

import { Container, i, injectable } from 'peppermint-di';

//
// the interface
//

interface ISomeService {
}

const ISomeService = Symbol('ISomeService');

//
// the concrete type
//

class ConcreteSomeService implements ISomeService {
}

//
// the class to resolve
//

@injectable
class MyClass {

    public myService: ISomeService;

    constructor(@i(ISomeService) myService: ISomeService) {
        this.myService = myService;
    }
}

//
// test
//

const container = new Container();
container.register(ISomeService, ConcreteSomeService);

const myClass = container.get(MyClass);

expect(myClass).to.be.instanceOf(MyClass);
expect(myClass.myService).to.be.instanceOf(ConcreteSomeService);

Instance initializers

import { Container, injectable } from 'peppermint-di';

class SomeService {
    public someFeatureFlag = false;
}

const container = new Container();

container.registerSingle(SomeService)
container.registerInitializer(SomeService, serviceInstance => {
    serviceInstance.someFeatureFlag = true;
});

const myService = container.get(SomeService);
expect(myService.someFeatureFlag).to.be.true;

JavaScript

Simple example

import { Container } from 'peppermint-di';

class SomeService {
    // ...
}

class SomeClass {
    constructor(someService) {
        // ...
    }
}


const container = new Container();

container.registerSingle('someService', SomeService);

const myClass = container.get(SomeClass);

Custom parameters

import { Container } from 'peppermint-di';

class SomeService {
    constructor() {
        this.name = 'default name';
    }
}

class MyClass {
    constructor(myService) {
        this.myService = myService;
    }
}

const container = new Container();

const customDep = new SomeService();
customDep.name = 'custom name';

const customParameters = new Map([
    ['myService', customDep]
]);
const myClass = container.get(MyClass, { params: customParameters });

expect(myClass.myService).to.be.instanceOf(SomeService);
expect(myClass.myService.name).to.eql('custom name');

API

You can find here a brief overview of the Container API.
For a more comprehensive review see the typing file.
You can also check out the library's unit tests as they contains examples for most use cases.

Container

Container key type:

type ContainerKey<T> = Constructor<T> | SimpleContainerKey;

type SimpleContainerKey = string | symbol;

Register a transient service.

Container.register<T>(key: Constructor<T>, type?: Constructor<T>): void;

Container.register<T>(key: SimpleContainerKey, type: Constructor<T>): void;

Container.registerFactory<T>(key: ContainerKey<T>, factory: Factory<T>): void;

Register a singleton service.

Container.registerSingle<T>(key: Constructor<T>, valueOrType?: T | Constructor<T>): void;

Container.registerSingle<T>(key: SimpleContainerKey, valueOrType: T | Constructor<T>): void;

Container.registerSingleFactory<T>(key: ContainerKey<T>, factory: Factory<T>): void;

Register an initializer.

type Initializer<T> = (instance: T) => void;

Container.registerInitializer<T>(key: ContainerKey<T>, initializer: Initializer<T>): void

Get an instance of T.

Container.get<T>(key: ContainerKey<T>, options?: ResolveOptions): T;

Resolve function arguments and call it.

Container.call(foo: Function, thisArg?: any, options?: ResolveOptions): any;

ResolveOptions

class ResolveOptions {

    /**
     * If set to 'true' will treat unregistered dependencies as optional
     * parameters and set their value to undefined.
     *
     * Default value: false
     */
    optionalParameters?: boolean;

    /**
     * Set to 'false' if you don't want the injector to automatically try to
     * construct unregistered constructors.
     *
     * Default value: true
     */
    constructUnregistered?: boolean;

    /**
     * Parameters specified here will be used directly instead of being resolved.
     */
    params?: Map<ContainerKey<any>, any>;
}

Changelog

The change log can be found here.

2.0.1

5 years ago

2.0.0

5 years ago

1.1.0

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago