# sdif

> Simple Dependency Injection Framework

Latest version **1.0.7** (published 2019-11-13) · MIT license · 0 weekly downloads

## Install

```sh
npm install sdif
pnpm add sdif
yarn add sdif
bun add sdif
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.7 |
| Published | 2019-11-13 |
| First published | 2019-10-25 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 12.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Georgii Kurtanidze |
| Maintainers | marsi |
| Keywords | dependency, injection, di, ioc |

## Links

- npm: https://www.npmjs.com/package/sdif
- Repository: https://github.com/geokur/sdi
- Homepage: https://github.com/geokur/sdi#readme
- Issues: https://github.com/geokur/sdi/issues
- npm.io page: https://npm.io/package/sdif

## Alternatives

- [memory-cache](https://npm.io/package/memory-cache.md) — 795.0K weekly downloads
- [@httptoolkit/proxy-agent](https://npm.io/package/@httptoolkit/proxy-agent.md) — 11.2K weekly downloads
- [express-cache-controller](https://npm.io/package/express-cache-controller.md) — 5.3K weekly downloads
- [http-cache-middleware](https://npm.io/package/http-cache-middleware.md) — 4.5K weekly downloads
- [cache2](https://npm.io/package/cache2.md) — 1.5K weekly downloads

## Recent versions

- 1.0.7 (latest) — 2019-11-13
- 1.0.6 — 2019-11-12
- 1.0.5 — 2019-11-07
- 1.0.4 — 2019-11-06
- 1.0.3 — 2019-11-06
- 1.0.2 — 2019-10-28
- 1.0.1 — 2019-10-25

## README

# Simple Dependency Injection Framework
## Background
This DI framework supports only constructor injection. Internally it uses object destructuring.
## Install
```shell
npm install sdif
```
# Quick start
All quickstart code is stored in repo: https://github.com/geokur/sdif-examples
## Injection of Class and Value
Let's create class representing a car:
```javascript
class Car {
    constructor({ model, engine, transmission }) {
        this.model = model
        this.engine = engine
        this.transmission = transmission
    }
    get specs() {
        return  this.model + ' specs:\n\t' + 
            this.engine.specs + '\n\t' +
            this.transmission.specs
    }
}
```
This class has 3 dependencies: model, engine and transmission.
Let's create 2 classes: 'Engine' and 'Transmission'. And constant 'model'.
```javascript
class DieselEngine {
    constructor() {
        this.fuel = 'Diesel'
        this.type = 'I'
        this.cylinders = 4
        this.size = 1995
        this.power = 143
    }
    get specs() {
        return `Engine: ${this.fuel} ${this.type}-${this.cylinders} ${this.size} cm3 ${this.power} PS`
    }
}

class AutomaticTransmission {
    constructor() {
        this.type = 'Automatic'
        this.gears = 6
    }
    get specs() {
        return `Transmission: ${this.type} ${this.gears} gear`
    }
}

const bmwModel = 'BMW 118d'
```
Now let's assemble a car instance
```javascript
const { Bindings, Container } = require('sdif')

const bindings = new Bindings()

bindings.bindClass(Car) // shortcut for bindings.bind('car').toClass(Car)
bindings.bind('model').toValue(bmwModel)
bindings.bind('engine').toClass(DieselEngine)
bindings.bind('transmission').toClass(AutomaticTransmission)

const container = new Container(bindings)

const bmw118 = container.getInstance('car')
```
Try to log to console the car's specs
```shell
console.log(bmw118.specs)
```
Expected output will be:
```
BMW 118d specs:
	Engine: Diesel I-4 1995 cm3 143 PS
	Transmission: Automatic 6 gear
```
## Key to key binding
You can bind another key to existing binding. The example above can be changed so we bind all classes and afterwords bind keys `engine` and `transmission` to keys already bound to specific classes.
```javascript
// ...

// Bind all classes
bindings.bindClass(Car, DieselEngine, AutomaticTransmission)

// Bind `engine` and `transmission` keys to keys bound to classes
bindings.bind('engine').toKey('dieselEngine')
bindings.bind('transmission').toKey('automaticTransmission')

// ...
```
## Singleton binding
```javascript
const { Bindings, Container } = require('sdif')

class InMemoryLogger {
    constructor() {
        this.rows = []
    }
    log(row) {
        this.rows.push(row)
    }
    printLog() {
        this.rows.forEach(row => console.log(row))
    }
}

class CheckoutService {
    constructor({ logger, orderService }) {
        this.logger = logger
        this.orderService = orderService
    }
    checkout(purchase) {
        this.logger.log(`Checkout purchase: ${purchase}`)
        this.orderService.createOrder(purchase)
    }
}

class OrderService {
    constructor({ logger }) {
        this.logger = logger
    }
    createOrder(purchase) {
        this.logger.log(`Create order for: ${purchase}`)
    }
}

const bindings = new Bindings()
bindings.bindClass(CheckoutService, OrderService)
// Bind Logger as Singleton to share its instance
bindings.bind('logger').toClass(InMemoryLogger).asSingleton()

const container = new Container(bindings)

const logger = container.getInstance('logger')
const checkoutService = container.getInstance('checkoutService')

checkoutService.checkout('iPhone 11')

logger.printLog()
```
Expected output:
```
Checkout purchase: iPhone 11
Create order for: iPhone 11
```
## Getting instance through destructuring
Above example can be changed to use Dependencies class. This will allow getting of instances through destructuring where property names are keys we used in bindings:
```javascript
const { Bindings, Container, Dependencies } = require('sdif')
// ...

// ...
/* Change getting instance from:

    const logger = container.getInstance('logger')
    const checkoutService = container.getInstance('checkoutService')

to destructuring:
*/

const dependencies = new Dependencies(container)
const { logger, checkoutService } = dependencies

//...
```
## Bindings loading
There is a way to automate binding by usage of BindingsLoader class. It will recursevely require files and create bindings.
Lets assume all classes from example above are placed in separate files in folder 'loaded'. Then bindings loading will look like this:
```javascript
const path = require('path')
const { Bindings, Container, Dependencies, BindingsLoader } = require('sdif')

const loadedPath = path.join(__dirname, 'loaded')
const bindings = new Bindings()

// Load bindings
BindingsLoader.loadDir(loadedPath, bindings)

/* After this command bindings will be the same as we would
manually require all classes from files and bind using:
    bindings.bindClass(CheckoutService, OrderService, InMemoryLogger)
*/

// The only binding which needs to be set manually to bind 'logger` to existing binding 
// and specify that it should be singleton 
bindings.bind('logger').toKey('inmemoryLogger').asSingleton()

// ...
```

---
_Source: https://npm.io/package/sdif · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
