A dependency injection system with destructuring. Combines a common pattern of using a single destructuring argument to avoid confusing the order of arguments to high-parity functions, possibly with many optional parameters.
To install the dependency injection system, use npm install
npm install --save idd
Then, from other peer directories, you can require the files as properties on the directory's default export
lib/config.js
export default function () {
return {
language: 'ru-ru',
level: 'info'
};
};
lib/greeter.js
export default ({config, Logger}) => {
const logger = new Logger();
return {
greet: () => {
if (config.language === 'en-us') {
logger.log('Hello World!');
} else if (config.language === 'ru-ru') {
logger.log('Привет, мир!');
} else {
logger.error('unsupported language ' + config.language);
}
}
};
};
lib/Logger.js
import chalk from 'chalk';
export default () => class Logger {
constructor() {
this.level = process.env.LEVEL;
}
log(msg) {
if (this.level !== 'quiet') {
console.log(msg);
}
}
error(msg) {
if (this.level !== 'quiet' && this.level !== 'silent') {
chalk.red(msg);
}
}
};
index.js
import path from 'path';
import idd from '../../../..';
const {greeter} = idd(path.join(__dirname, 'lib'));
greeter.greet();
Then the output would be 'Hello World!'. If you were to change config to be instead
export default function() {
language: 'ru-ru',
level: 'error'
}
Then the output would be 'Привет, мир!'.
A good dependency injection system should make unit testing easy. To mock out your dependencies, just provide an optional third option with the mocks
import {sinon} from 'sinon';
import idd from 'idd';
import test from 'ava';
test('Greet was called', t => {
const greet = sinon.spy();
const config = { greeting: 'Hello World!'};
const {greeter} = idd('./lib', { config, greet });
greeter.greet();
t.true(greet.calledOnce);
});