Skip to content

A lightweight dependency injection container for Node.js.

License

Notifications You must be signed in to change notification settings

benthepoet/fast-inject

Repository files navigation

fast-inject

Build Status Coverage Status

A lightweight dependency injection container for Node.js.

Node.js Support

This library currently supports Node.js >= 8.0.0.

Why dependency injection in Node.js?

To be honest dependency injection isn't really necessary in Node.js most of the time due to its module-based design but I created this library because I wanted the following.

  • A lightweight container that I can instantiate on every HTTP request
  • Lazy-loaded services that only get instantiated if they're used
  • The ability to decouple modules for testing without needing proxyquire
  • Eliminate relative paths to other modules

Installation

This library is intended for use in Node.js projects and can be installed with npm.

npm install fast-inject --save

Creating a basic container

Containers are merely just an object with properties for constants or services. These constants or services are provided as singletons. Services are also lazy-loaded and thus only get instantiated if they are accessed.

To setup a container you just create an Injector instance and register your constants and/or services.

const { Injector } = require('fast-inject');

// Service class
class B {
  // Expects an instance of `A` to be injected.
  constructor(a) {
    this.a = a;
  }
}

// Service class
class C {
  // Expects an instance of `B` to be injected.
  constructor(b) {
    this.b = b;
  }
}

const { container } = new Injector()
  // Constants can provide any static value (string, number, Object, Function). 
  .constant('A', 1234)
  // Services must be defined as ES6 classes and can have dependencies.
  // Any dependencies are injected into the constructor when the service is instantiated.
  .service(B, ['A'])
  // Use the `name` property of the class when one service is dependent on another.
  .service(C, [B.name]);
  
// Access a constant
console.log(container.A);
// 1234

// Access a service
console.log(container.B.a);
// 1234

// Access a nested service
console.log(container.C.b.a);
// 1234

Creating a container pipeline

In addition to using the approach above, fast-inject also allows you to build a container pipeline by means of functional composition. Ramda is used in the example below but you can use any library that supports function composition like Lodash or Underscore.js.

const R = require('ramda');
const { constant, service } = require('fast-inject');

// Service class
class B {
  // Expects an instance of `A` to be injected.
  constructor(a) {
    this.a = a;
  }
}

// Service class
class C {
  // Expects an instance of `B` to be injected.
  constructor(b) {
    this.b = b;
  }
}

// Compose the pipeline
const pipeline = R.pipe(
  constant('A', 1234),
  service(B, ['A']),
  service(C, [B.name])
);

// Create a container
const container = pipeline(Object.create(null));

The functional approach also gives you the advantage of being able to compose multiple pipelines together.

API

Classes

Injector

Functions

constant(name, value, container)Object

Define a constant on a container.

service(Class, dependencies, container)Object

Define a service on a container.

Injector

Kind: global class
Properties

Name Type Description
container Object The container instance.

new Injector()

The class for constructing a dependency container.

injector.constant(name, value) ⇒ Injector

Define a constant on the injector's container.

Kind: instance method of Injector
Returns: Injector - The Injector instance.

Param Type
name string
value *

injector.service(Class, dependencies) ⇒ Injector

Define a service on the injector's container.

Kind: instance method of Injector
Returns: Injector - The Injector instance.

Param Type
Class function
dependencies Array.<string>

constant(name, value, container) ⇒ Object

Define a constant on a container.

Kind: global function
Returns: Object - The container instance.

Param Type
name string
value *
container Object

service(Class, dependencies, container) ⇒ Object

Define a service on a container.

Kind: global function
Returns: Object - The container instance.

Param Type
Class function
dependencies Array.<string>
container Object