# Overview [![Build Status](https://drone.nitowa.xyz/api/badges/npm-packages/depents/status.svg)](https://drone.nitowa.xyz/npm-packages/depents) [![Current Version](https://img.shields.io/npm/v/depents.svg)](https://www.npmjs.com/package/depents) [![Weekly Downloads](https://img.shields.io/npm/dw/depents?color=important)](https://www.npmjs.com/package/depents) [![License Type](https://img.shields.io/npm/l/depents?color=blueviolet)](https://gitea.nitowa.xyz/docs/depents/src/branch/master/LICENSE.md) depents is a typescript dependency injection framework # How to install ``` npm i depents ``` # Quickstart (TL;DR) ```typescript import {Singleton, Inject, Injector} from 'depents' @Singleton() class AClass{ private A = 'a' getA () { return this.A } } @Singleton() class BClass{ @Inject(AClass) private a: AClass getA(){ return this.a.getA() } } console.log(Injector.resolve(BClass).getA()) //"a" ``` # Working with interfaces as non-default injection tokens As interfaces are not a runtime construct in javascript, classes have to be used in their place in order to work with injection resolution. Consider this quick example: File `MyModule/Interface.ts` ```typescript export abstract class IComponent{ get: () => string } ``` File `MyModule/Implementation.ts` ```typescript import {IComponent} from 'Interface.ts' @Singleton({ interface: IComponentB, }) export class ComponentB implements IComponent{ get(): string { return "Hello!" } } ``` File `Main.ts` ```typescript import {IComponent} from 'MyModule/Interface.ts' import {ComponentB} from 'Module/Implementation.ts' ComponentB; //see Tree shaking pitfall below Injector.resolve(IComponent).get() ``` # Tree shaking pitfall TSC will attempt to exclude unused code in order to keep the compiled JS minimal. In the above example neither `Main.ts` nor `MyModule/Interface.ts` ever reference `MyModule/Implementation.ts` and it is therefore considered unused code. This will lead to the compilation output not containing the `ComponentB` class. To forcibly include `ComponentB`, it has to be referenced at least once - even if it is a senseless operation like in the above example. # Initialization This version of depents will simply call all constructors of classes marked as `Singleton` without arguments and it is therefore recommended that the user does not place initialization logic there. Alternatively, you may provide a function named `initialize` which will be called during Singleton creation. An example: ```typescript @Singleton() export class Component{ private value: string get(): string { return this.value } initialize():void { //Called during object creation this.value = "Hello!" } } ``` If your code requires objects to be initialized in a particular order, you may pass an optional `initializationPriority` parameter to `@Singleton`. The respective initialize operations will be called in order of `initializationPriority` from **lowest to highest**. If omitted, the default value is 0. ```typescript @Singleton({ initializationPriority: 0 }) export class InitializedFirst{ private value: number get(): number { return this.value } initialize():void { this.value = 1 } } @Singleton({ initializationPriority: 1 }) export class InitializedSecond{ @Inject(InitializedFirst) private otherSingleton: InitializedFirst private value: number get(): number { return this.value } initialize():void { this.value = 1 + this.otherSingleton.get() } } console.log(Injector.resolve(InitializedSecond).get()) //2 ``` # [Full documentation](https://gitea.nitowa.xyz/docs/depents)