inceptor

1.0.1 • Public • Published

Inceptor.js

Build Status Coverage Status

Sauce Test Status

Ownership-driven dependency injection for JavaScript

Usually, dependency injection frameworks rely on central container to retrieve dependencies.

In contrast, this ownership-driven approach spawn scopes when these dependencies are created.

Features:

  • Very small (5kb minified).
  • Does not depend on any other library.
  • Works everywhere! Both node.js and browser are supported.
  • Re-uses familiar loading mechanisms such as requirejs or node's require.
  • Does not need string names to map objects.
  • Code is well-tested.
  • Scopes can be tested in isolation without dependency map.
  • Once dependency map is used, it becomes immutable.
  • No global variables or containers!

How does it work?

This container turns the problem on its head: instead of creating a dependency when your code requests it, Inceptor.js does the reverse.

It runs your code when all dependencies are created.

Let's look at simple example.

Suppose we have a simple logger that logs our messages to multiple backends.

In traditional DI, we would inject the backends into the logger constructor.

Here, we do the reverse: we tell the backend to require the logger.

Let's see the code for logger:

var Logger = inceptor.scope({
    initialize: function() {
        this.backends = [];
    },

    log: function(message) {
        for (var i = 0; i < this.backends.length; i++) {
            this.backends[i].log(message);
        }
    }
});

Here, we achieved the abstraction: the logger knows nothing about the backends, the only thing it requires is that they implement the log() method.

Let's see the code for backend:

var Backend = inceptor.scope([Logger], {
    initialize: function(logger) {
        logger.backends.push(this);
    },

    log: function(message) {
        console.log(message);
    }
});

Here, the backend receives the logger over the first argument, and adds itself to the list.

Somewhere at the root of the project, we add both the Logger and the Backend to dependency map:

var deps = inceptor.load(
    Logger,
    Backend,
);

And later create the logger using this map:

var logger = deps.create(Logger);
logger.log('Hello!');

Receive the Hello! in console!

If we later need a different Backend implementation, or want to silence the logs, we don't need to touch the logger, just modify the backend.

So, we have achieved what is required from the dependency injection.

The big difference here is that lifetime of all objects spawned by logger depend directly on the lifetime of logger. If a new logger is created, the whole tree of dependent objects is created too.

Usage in frameworks

Intrigued? See how it can be used in your environment:

License

MIT

Package Sidebar

Install

npm i inceptor

Weekly Downloads

0

Version

1.0.1

License

MIT

Last publish

Collaborators

  • nercury