npm package: @soerenuhrbach/di
Description: A lightweight dependency injection container for TypeScript/JavaScript for constructor injection. Based on [tsyringe](https://github.com/microsoft/tsyringe).
Author: Sören Uhrbach
Latest version: 1.2.3

# @soerenuhrbach/di

A lightweight dependency injection container for TypeScript/JavaScript for
constructor injection. Based on [tsyringe](https://github.com/microsoft/tsyringe).

## Installation

Install by `npm`

```sh
npm install --save @soerenuhrbach/di
```

**or** install with `yarn`

```sh
yarn add @soerenuhrbach/di
```

Modify your `tsconfig.json` to include the following settings

```json
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}
```

Add a polyfill for the Reflect API. You can use:

- [reflect-metadata](https://www.npmjs.com/package/reflect-metadata)

The Reflect polyfill import should only be added once, and before before DI is used:

```typescript
// main.ts
import "reflect-metadata";

// Your code here...
```

# API

The container performs [Constructor Injection](https://en.wikipedia.org/wiki/Dependency_injection#Constructor_injection)
on the constructors of decorated classes.

## Decorators

### @Injectable()

Class decorator factory that allows the class' dependencies to be injected at
runtime.

#### Usage

```typescript
import { Injectable } from "@soerenuhrbach/di";

@Injectable()
class Foo {
  constructor(private database: Database) {}
}

// some other file
import "reflect-metadata";
import { container } from "@soerenuhrbach/di";
import { Foo } from "./foo";

const instance = container.resolve(Foo);
```

### @Singleton()

Class decorator factory that registers the class as a singleton within the
global container.

#### Usage

```typescript
import { Singleton } from "@soerenuhrbach/di";

@Singleton()
class Foo {
  constructor() {}
}

// some other file
import "reflect-metadata";
import { container } from "@soerenuhrbach/di";
import { Foo } from "./foo";

const instance = container.resolve(Foo);
```

### @AutoInjectable()

Class decorator factory that replaces the decorated class' constructor with
a parameterless constructor that has dependencies auto-resolved.

#### Usage

```typescript
import { AutoInjectable } from "@soerenuhrbach/di";

@AutoInjectable()
class Foo {
  constructor(private database?: Database) {}
}

// some other file
import { Foo } from "./foo";

const instance = new Foo();
```

Notice how in order to allow the use of the empty constructor `new Foo()`, we
need to make the parameters optional, e.g. `database?: Database`.

### @Inject()

Parameter decorator factory that allows for interface and other non-class
information to be stored in the constructor's metadata.

#### Usage

```typescript
import { Injectable, Inject } from "@soerenuhrbach/di";

interface Database {
  // ...
}

@Injectable()
class Foo {
  constructor(@Inject("Database") private database?: Database) {}
}
```

### @InjectAll()

Parameter decorator for array parameters where the array contents will come from the container.
It will inject an array using the specified injection token to resolve the values.

#### Usage

```typescript
import { Injectable, InjectAll } from "@soerenuhrbach/di";

@Injectable()
class Foo {}

@Injectable()
class Bar {
  constructor(@InjectAll(Foo) fooArray: Foo[]) {
    // ...
  }
}
```

## Providers

A provider is registered with the DI container and provides the container the information needed to resolve an instance for a given token.

### ClassProvider

This provider is used to resolve classes by their constructor. When registering a class provider you can simply use the constructor itself, unless of course you're making an alias (a class provider where the token isn't the class itself).

#### Usage

```typescript
import { container, ClassProvider } from '@soerenuhrbach/di';

class Foo {}
const provider = new ClassProvider(Foo);
container.register("Foo", provider);
```

### ValueProvider

This provider is used to resolve a token to a given value. This is useful for registering constants, or things that have a already been instantiated in a particular way.

#### Usage

```typescript
import { container, ValueProvider } from '@soerenuhrbach/di';

const provider = new ValueProvider("Bar");
container.register("Foo", provider);
```

### TokenProvider

This provider can be thought of as a redirect or an alias, it simply states that given token _x_, resolve using token _y_.

#### Usage

```typescript
import { container, TokenProvider } from '@soerenuhrbach/di';

class Foo {}
container.register("Foo", Foo);
const provider = new TokenProvider("Foo");
container.register("FooBar", provider);
```

### FactoryProvider

This provider is used to resolve a token using a given factory. The factory has full access to the dependency container.

#### Usage

```typescript
import { container, FactoryProvider, ContainerInterface } from '@soerenuhrbach/di';

class Foo { constructor(public bar: string) {} }
const FooFactory = (container: ContainerInterface) => new Foo("Bar");
const provider = new FactoryProvider(FooFactory);
container.register("Foo", provider);
```