# blackbox-ioc
[![Version](https://img.shields.io/bitbucket/pipelines/ellipsistechnology/blackbox-ioc-js.svg)](https://bitbucket.org/ellipsistechnology/blackbox-ioc-js/addon/pipelines/home#!/)
[![Version](https://img.shields.io/npm/v/npm.svg)](https://www.npmjs.com/)
[![License](https://img.shields.io/npm/l/oclif.svg)](https://bitbucket.org/ellipsistechnology/blackbox-ioc-js/src/master/package.json)

> A basic Inversion Of Control container for decorator based wiring of class instances and services.

Blackbox IOC offers control of two distinct types of entity: Instances and Services.

**Instances** are associated with a name and can be autowired to a class' property.

**Services** are methods that provide a service and can be associated with a name and grouped by a tag. A service object can be created for all services with a given tag and then autowired to a class' property.

## Table of Contents

- [Install](#install)
- [Usage](#usage)
- [API](#api)
- [Maintainers](#maintainers)
- [Contributing](#contributing)
- [License](#license)

## Install

This package requires [npm](https://www.npmjs.com/).
You can install it by running:
```
npm i blackbox-ioc
```

## Usage

Create a named instance of a class:
```
@named('calculator')
class Calculator {
  ...
}
```
An instance of class `Calculator` will be created and associated with the name `calculator`. The constructor must not take any parameters.

Autowire a class property to a named instance:
```
class Wrapper {
  @autowired('calculator')
  calc: Calcuator
}
```
Instances of Wrapper will automatically have the named instance of `Calculator` assigned to the `calc` property.

Create an instance using a factory method:
```
class Factories {
  @factory('logger')
  createLogger():Logger {
    ...
  }
}
```
The `createLogger` method will be called in order to create a new instance of the `Logger` class. The new instance will be associated with the name `logger`.

Identify a class as providing services:
```
@serviceClass('weather')
class WeatherService {
  getTemperature():number {
    ...
  }
  getHumidity():number {
    ...
  }
}
```
All methods in the class will become services grouped by the `weather` tag. By default, services are named according to the method names: i.e. `getTemperature` and `getHumidity`.

Create a service by name:
```
class WeatherService {
  @service('temp')
  getTemperature():number {
    ...
  }
}
```
The `getTemperature` method will provide a service named `temp` and will belong to the `default` tag.

Create a service by name and grouped with a tag:
```
class WeatherService {
  @taggedService('meteorology', 'temp')
  getTemperature():number {
    ...
  }
}
```
The `getTemperature` method will provide a service named `temp` and be grouped with any other services tagged with `meteorology`.

Autowire a class property to a service object:
```
class Wrapper {
  @autowiredService('weather')
  weatherService:any
}
```
Instances of Wrapper will automatically have a service object created and assigned to the `weatherService` property. The service object will include a method for each named service with the `weather` tag.

## API

**`@named(name:string)`** Class decorator. Creates an instance of the class and associated it with `name`.

**`@factory(name:string)`** Method decorator. Calls the method and associates the returned instance with `name`.

**`@autowired(name:string)`** Property decorator. Assigns the instance named `name` to the property.

**`@serviceClass(tag:string)`** Class decorator. Creates an instance of the class and associates it with `tag` as its name. All of the class's methods will be marked as services tagged with `tag` and named `name`.

**`@service(name:string)`** Method decorator. The method will be marked as a service tagged with `default` and named `name`.

**`@taggedService(tag:string, name:string)`** Method decorator. The method will be marked as a service tagged with `tag` and named `name`.

**`@autowiredService(tag:string)`** Property decorator. The property will be assigned a new service object including a method for each service tagged with `tag`.

## Maintainers

[@ellipsistechnology](https://github.com/ellipsistechnology)

## Contributing

PRs accepted.

Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.

## License

MIT © 2019 Ben Millar
