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

dependable

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dependable

A minimalist dependency injection framework for javascript (fully tested for node.js)

  • 0.2.3
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

Dependable

A minimalist dependency injection framework for javascript (fully tested for node.js)

Goals

  1. Allow creation of modules that can be passed dependencies instead of requiring them.
  2. Simple bootstrapping, minimal footprint
  3. Automatic

Documentation

What is Dependency Injection

In CommonJS, modules are normally defined like one of the following

exports.hello = -> "hello world"

module.exports =
  hello: "hello world"

If you have a dependency, you normally just require it. The greetings module needs some config to work.

Greetings = require "greetings"
greetings = new Greetings("en")

module.exports = ->
  hello: -> greetings.hello("world")

Instead of requiring it, and setting the config inside our module, we can require that a pre-configured greetings instance be passed in to our function.

module.exports = (greetings) ->
  hello: -> greetings.hello("world")

This is "Dependency Injection". greetings is a dependency of our module. Its dependencies are "injected", meaning they are handed to us by whoever uses our module instead of us reaching out for them.

Why Dependency Injection?

If you ever need to change your config options, such as when testing, or to hit different layers of a service, it is easier to have a pre-configured object passed in instead of creating it yourself.

Your module is a little less coupled to its dependency

You can pass in mock or alternate versions of a module if you want

This is Annoying

It is hard to remember how to construct and configure the dependencies when you want to use your module. This should be automatic. Here is an example

robot.coffee

module.exports = (greetings) ->
  hello: -> greetings.hello("world")

greetings.coffee

module.exports = (language) ->
  ...

app.coffee

# you have to do this in every file you want to use robot
Greetings = require "greetings"
greetings = Greetings("en")

Robot = require "robot"
robot = Robot greetings

itsAliiiive = -> 
  console.log robot.hello()

This gets much worse when your dependencies have dependencies of their own. You have to remember in which order to configure them so you can pass them into each other.

Using Dependenable

Dependable automates this process. In the following example, you don't need to register the modules in order, or do it more than once (it will work for dependencies of dependencies)

robot.coffee

module.exports = (greetings) ->
  hello: -> greetings.hello("world")

greetings.coffee

module.exports = (language) ->
  ...

app.coffee

# create the container, you only have to do this once.
container = require("dependable").container
deps = container()
deps.register "greetings", require("greetings")
deps.register "robot", require("robot")

robot = deps.get "robot"

itsAliiiive = -> 
  console.log robot.hello()

Using Dependable's Load

You can load files or directories instead of registering by hand. See Reference

Overriding Dependencies for Testing

When testing, you usually want most dependencies loaded normally, but to mock others. You can use overrides for this. In the example below, User depends on Friends.getInfo for it's getFriends call. By setting Friends to MockFriends we can stub the dependency, but any other dependencies User has will be passed in normally.

# boostrap.coffee
deps = container()
deps.register "Friends", require('./Friends')
deps.register "User", require('./User')

# test.coffee
describe 'User', ->
  it 'should get friends plus info', (done) ->

    MockFriends =
      getInfo: (id, cb) -> cb null, {some:"info"}

    User = deps.get "User", {Friends: MockFriends}
    User.getFriends "userId", (err, friends) ->
      # assertions
      done()

Reference

container.register(name, function) - registers a dependency by name. function can be a function that takes dependencies and returns anything, or an object itself with no dependencies.

container.load(fileOrFolder) - registers a file, using its file name as the name, or all files in a folder. Does not follow sub directories

container.get(name, overrides = {}) - returns a module by name, with all dependencies injected. If you specify overrides, the dependency will be given those overrides instead of those registerd.

container.resolve([overrides,] cb) - calls cb like a dependency function, injecting any dependencies found in the signature

deps.resolve (User) ->
  # do something with User

FAQs

Package last updated on 03 Oct 2012

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