Dependency injection container for TypeScript and JavaScript.
yarn add peppermint-di
or
npm install --save peppermint-di
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);
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.
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');
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);
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;
import { Container } from 'peppermint-di';
class SomeService {
// ...
}
class SomeClass {
constructor(someService) {
// ...
}
}
const container = new Container();
container.registerSingle('someService', SomeService);
const myClass = container.get(SomeClass);
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');
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 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;
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>;
}
The change log can be found here.