https://github.com/magicmark/lentildi
💉 Lightweight + Simple ES6 Dependency Injection :)
https://github.com/magicmark/lentildi
Last synced: 9 months ago
JSON representation
💉 Lightweight + Simple ES6 Dependency Injection :)
- Host: GitHub
- URL: https://github.com/magicmark/lentildi
- Owner: magicmark
- Created: 2016-07-31T00:51:18.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2017-09-25T02:34:28.000Z (over 8 years ago)
- Last Synced: 2025-03-22T14:11:23.693Z (about 1 year ago)
- Language: JavaScript
- Homepage:
- Size: 45.9 KB
- Stars: 6
- Watchers: 1
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README

LentilDI
========
[](https://travis-ci.org/magicmark/LentilDI)
[](https://coveralls.io/github/magicmark/LentilDI?branch=master)
[](https://www.npmjs.com/package/lentildi)
Lightweight + Simple ES6 Dependency Injection :)
**LentilDI** lets you build apps without the pain of having to instantiate, wire up, and manually manage your dependency tree. LentilDI emphasises:
* Reduction of boilerplate dependency juggling
* Ease of module testing
Check out the [hello world](https://github.com/magicmark/LentilDI/blob/master/examples/hello_world/index.js) example for a quick introduction.
## Install
```
$ npm install --save lentildi
```
## Example
With LentilDI, you can go from something like this:
```javascript
const tuba = new Tuba();
const horn = new Horn();
const percussion = new Percussion();
const conductor = new Conductor('Snoop Dogg');
const brassSection = new BrassSection(conductor, tuba, horn, fs, os);
...
const orchestra = new Orchestra(conductor, brassSection, percussion);
```
To something like this:
```javascript
const lentil = new Lentil();
lentil.setArgs(Conductor, ['Snoop Dogg']);
const orchestra = lentil.create(Orchestra);
```
### Automatic Dependency Wiring
Typically, we might pass in our dependencies (including built-in objects) and bind them to `this` in large constructors such as this:
```javascript
class BrassSection extends LentilBase {
constructor (conductor, tuba, horn, fs, os) {
this.conductor = conductor;
this.tuba = tuba;
this.horn = horn;
this.fs = fs;
this.os = os;
}
loadSheetMusic () {
const sheetMusic = this.conductor.getScore();
this.fs.readFile(sheetMusic, ...
}
...
```
When we use LentilDI, we get that wiring done for us for free:
```javascript
class BrassSection extends LentilBase {
static lentilDeps () {
return {
conductor: Conductor,
tuba: Tuba,
horn: Horn,
fs,
os,
}
}
loadSheetMusic () {
const sheetMusic = this.conductor.getScore();
this.fs.readFile(sheetMusic, ...
}
...
```
### Testing
Testing modules is easy as pie - just create your module as normal!
If you want to override anything in `lentilDeps`, just pass an object as the last argument to your constructor.
```javascript
it('BrassSection should play some music', function () {
const dummyConductor = { ... };
const dummyTuba = { ... };
const dummyHorn = { ... };
// Note that we don't have to override fs or os
// We can let Lentil assign them as default values
const brassSection = new BrassSection({
conductor: dummyConductor,
tuba: dummyTuba,
horn: dummyHorn,
});
brassSection.playMusic();
...
});
```
### More Examples
Check out some full example apps (with tests!) [here](https://github.com/magicmark/LentilDI/tree/master/examples).
## LentilDep
You can specify different types of dependencies in your `lentilDeps` declaration.
Currently, Lentil understands 3 types of dependencies:
* `LentilDep.Provided`
* `LentilDep.Regular`
* `LentilDep.Lentil`
### LentilDep.Provided
For cases where you might have an externally instantiated class (e.g. a logger) that you want to be available in any of your modules:
```javascript
const logger = log4js.getLogger('My Logger');
const lentil = new Lentil();
lentil.provide('logger', logger);
const myApp = lentil.create(MyApp);
```
Your logger instance will now be available as normal through `this.logger` inside a Lentil module:
```javascript
class SomeModule extends LentilBase {
static lentilDeps () {
return {
logger: LentilDep.Provided('logger'),
}
}
doSomething() {
this.logger.info( ... );
}
}
```
### LentilDep.Regular
This is the default type where values are simply passed along to your module.
Unless otherwise specified, this is how Lentil will treat a dependency.
```javascript
class SomeModule extends LentilBase {
static lentilDeps () {
return {
whatever: 'Whatever',
}
}
}
```
'Whatever' would now be available through `this.whatever`. (This is particularly useful for built in objects such as `os`, `console` etc.)
For the sake of clarity, note that this is functionally equivalent to the following:
```javascript
class SomeModule extends LentilBase {
static lentilDeps () {
return {
// This is not recommended as Lentil can do this wrapping for us.
whatever: LentilDep.Regular('Whatever'),
}
}
}
```
### LentilDep.Lentil
For sub-dependencies that you wish Lentil to also construct (i.e. other modules that extend from LentilBase.)
Similar to LentilDep.Regular, you do not need to explicitly wrap modules in this; Lentil will do this for you.
```javascript
class SomeOtherModule extends LentilBase {
static lentilDeps () {
return {
someModule: SomeModule,
}
}
}
```
This is equivalent to the following:
```javascript
class SomeOtherModule extends LentilBase {
static lentilDeps () {
return {
// This is not recommended as Lentil can do this wrapping for us.
someModule: LentilDep.Lentil(SomeModule),
}
}
}
```
## Constructor Arguments
You can pass in arguments to your modules (useful for one-offs such as config values).
To do so, pass an array of arguments to `lentil.setArgs`:
```javascript
const lentil = new Lentil();
lentil.setArgs(Conductor, ['Snoop Dogg']);
...
```
Inside your module, your arguments are available as normal.
(Remember to call `super`.)
```javascript
class Conductor extends LentilBase {
constructor (conductorName, ...args) {
super(...args);
console.log(`Orchestra is being conducted by ${conductorName}`);
}
...
}
```
## Full Documentation
Coming Soon
## Contributing
Please do!
## Why 'Lentil'?
I like lentils
## Licence
MIT