Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@adonisjs/fold

Package Overview
Dependencies
Maintainers
2
Versions
111
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@adonisjs/fold

Dependency manager and ioc container for your next NodeJs application

  • 5.0.3
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
36K
decreased by-4.05%
Maintainers
2
Weekly downloads
 
Created
Source

AdonisJs Fold 🚀

Dependency manager and IoC container for Node.js

travis-image appveyor-image coveralls-image npm-image

Adonis fold is zero dependency library to enable Dependency Injection in your apps using an IoC container.

The library itself is pretty lean. However, offers handful of tools to make DI easier and simpler.

  • Zero depedencies.
  • Support for fakes to ease testing.
  • Gazallion times faster than Node.js require.

Using IoC container for simple apps can become overkill. Use it when you are creating an eco-system of plugins and wants them to play together gracefully using a global dependency store.

Getting started

The first step it to install the package from npm as follows.

npm i @adonisjs/fold

# Using Yarn
yarn add @adonisjs/fold

Next, is to use package by importing the container.

const { Ioc } = require('@adonisjs/fold')
const ioc = new Ioc()

ioc.bind('unique/namespace', () => {
  return 'value'
})

The bind receives 2 arguments.

  1. The namespace is the unique name for the binding.
  2. The factory function is executed everytime the dependency is fetched from the container and return value is used.

If you want the factory functions to be executed only once, then make use of the singleton instead of bind.

ioc.singleton('unique/namespace', () => {
  return 'value'
})

What is Dependency Injection?

Dependency Injection is a simple concept of injecting dependencies during the creation of an object vs being dependent on them globally.

In the following example we require the database service and mailer to perform user registeration.

const db = require('./db')
const mailer = require('./mailer')

class UserService {
  async register (userData) {
    await db.create(userData)
    await mailer.sendEmail('email-template', userData.email)
  }
}

Now, if you want to test the above UserService, there is no simply way to use a different implementation of mailer or db.

Let's refactor the above code and accept the dependencies as constructor arguments.

class UserService {
  constructor (db, mailer) {
    this.db = db
    this.mailer = mailer
  }

  async register (userData) {
    await this.db.create(userData)
    this.mailer.sendEmail('email-template', userData.email)
  }
}

With the refactored code, testing UserService is simple, since you can inject alternate implementations of db and mailer during testing.

What is IoC container?

If classes makes use of Dependency Injection, there has to be someone to inject these dependencies in the right order.

Imagine, before using the internal modules of a framework like AdonisJs, you have to manually build classes by injecting dependencies to them.

const Mail = require('@adonisjs/mail')
const { Config, View } = require('@adonisjs/framework')

const config = new Config(__dirname)
const view = new View(config)
const mailer = new Mail(config, view)

mailer.send()

The above code will quickly spin out of your hands for many reasons.

  1. It will take lots of brain power to decide, where and when to construct these classes.
  2. If an internal module like @adonisjs/mail changes the order of arguments, then the package has to be released as a breaking change.
  3. Finally, as an application developer, why should you even care about building these objects from hand.

Using IoC container

Now that we understand Dependency Injection and the need of container, let's see how to use the container in an application.

Frameworks like AdonisJs uses this module to build an entire eco-system of modules. All the framework modules are registered to the container and your application pulls them from container only.

This approach has several benefits

  1. The user of the framework, won't have to manually construct classes. The creator of the module constructs them and binds them to the container.
  2. All dependencies inside the container can use each other, without requiring them in a hard coded way. The concept is generally known as loose coupling.
  3. Makes the testing easier, since faking the value of a namespace inside a container is simpler than proxying require calls.
const { Ioc } = require('@adonisjs/fold')
const container = new Ioc()

container.bind('Config', function () {
  return {
    appKey: process.env.APP_KEY,
    database: {
      // config
    },
    redis: {
      // config
    }
  }
})

module.exports = { container }

Now anywhere inside your application, you can fetch the config from the container using it's namespace.

const { container } = require('./app')
container.use('Config') // returns object

Building an eco-system of plugins on top of this approach enables loose coupling and better development experience.

Concrete classes with DI

class Config {
  constructor (configObject) {
  }

  get (key) {
    // return value of a key inside the config object
  }
}

class Redis {
  constructor (config) {
  }
}

class Cache {
  constructor (config, redis) {
  }
}

Binding them to the container

container.bind('App/Config', function () {
  return new Config({
    redis: {
      // config
    },
    cache: {
      // config
    }
  })
})

container.bind('App/Redis', function () {
  return new Redis(container.use('App/Config'))
})

container.bind('App/Cache', function () {
  return new Cache(container.use('App/Redis'), container.use('App/Config'))
})

Now anywhere inside your application, you can use the Cache object without worrying about how to build it.

const cache = container.use('App/Cache')

Usage with Typescript

Change log

The change log can be found in the CHANGELOG.md file.

Contributing

Everyone is welcome to contribute. Please go through the following guides, before getting started.

  1. Contributing
  2. Code of conduct

Authors & License

Harminder Virk and contributors.

MIT License, see the included MIT file.

Keywords

FAQs

Package last updated on 10 Feb 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc