Intify
Declarative lightweight IoC (inversion of control) container for javascript, built for functional programming style.
Intify allows you to keep all of your dependencies in one place and lazy load them on demand.
Motivation
When you working in functional programming style you want to control every single piece of your app. And if you use Dependency injection and Inversion of control design patterns in your workflow then you have many different dependencies linked between your functions. And it becomes a pain to reach them all and keeping in mind where from each dependency comes in.
That's why I started to build very simple and lightweight injection container. I want to create handy workflow to myself.
Hope you will find it useful too.
Installation
yarn add intify
or
npm install intify
Features
- Lightweight ~ 4kb
- Built using typescript
- Very intuitive api
How it works
General scheme looks like this:
And flow is simple:
- Register all of the dependencies
- Wrap your functions with
withDeps
higher order function - Intify will take over the rest
Usage
Import
import { store, withDeps } from 'intify';
General usage
Each function with dependencies should be curried with "deps" object. For example:
const logMessage = deps =>
message => deps.log(message);
For simplier syntax you can use object destructuring:
const logMessage = ({ log }) =>
message => log(message);
Register dependencies
For register any dependency you have to call .register()
method on store
object:
import { store } from 'intify';
store.register({ dependency });
Injecting dependecies
.widthDeps()
is higher order function which returns wrapped function with provided dependencies.
import { withDeps } from 'intify';
const logMessage = deps =>
message => deps.log(message);
export default withDeps(logMessage);
Examples
Usage example
// logMessage.js
import { withDeps } from 'intify';
export const logMessage = ({ log }) =>
message => log(message);
export default withDeps(logMessage);
// index.js
import { store } from 'intify';
import log from './logger';
store.register({ log });
// somewhere else
import logMessage from './logMessage';
logMessage(myValue);
Test example
// utility.spec.js
import { utility } from './utility';
test('should works', () => {
const mockDatabase = jest.fn();
utility({ database: mockDatabase })(mockValue);
expect(mockDatabase).toBeCalled();
});
API
Store
Store with all dependencies. Currently allows to keep only 1 store at time.
Example:
import { store } from 'intify';
store.register({ database });
store.getDeps :: () -> Object
Returns object with all registered dependencies
store.subscribe :: (next) -> Observer
Experimental feature
Require "next" function which will be triggered each time when any dependency will be called.
Next will be called with object:
{
fn, // called function
name, // called function's name
args // arguments provided to called function
}
Example:
import { store } from 'intify';
const observer = store.subscribe(console.log);
// to unsubscribe just call
observer.unsubscribe();
store.unsubscribe :: () -> Void
Remove all listeners.
withDeps :: (Object) => (Function) => Function
Wrap target function with dependency store
Example:
import { withDeps } from 'intify';
const makeAddValueToDatabase = ({ database }) =>
function addValueToDatabase(newValue) {
return database.add(newValue);
}
export default withDeps(makeAddValueToDatabase); // = addValueToDatabase - with provided dependencies