npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tjforryan/ioc-container

v1.0.4

Published

> A simple IoC (Inversion of Control) Container, using Dependency Injection

Readme

IoC Container

A simple IoC (Inversion of Control) Container, using Dependency Injection

Installation

You can see the package on npm

npm i --save @tjforryan/ioc-container
yarn add @tjforryan/ioc-container

Why?

As applications grow so does the number of dependencies that exist between modules. Having all of these modules aware of their dependencies can hurt maintainability.

That's where inversion of control comes in. IoC allows modules to work against abstracted interfaces instead of the concrete dependencies themselves. Dependency Injection is one way of doing this, where a module is supplied its dependencies, allowing the module to only have knowledge of the interface it is working with.

However, as Dependency Injection pushes all the dependencies higher, this can make applications very top heavy. This can result in instantiating lots of dependencies at the highest level and then having to pass them into all of the other modules that need them. This in turn can result in some very messy and boilerplate heavy code, especially where modules are nested.

This IoC Container aims to solve that problem. By performing instantiation itself it removes a lot of unnecessary boilerplate and, by abstracting away the dependency graph, it makes maintaining those dependencies easier.

Usage

Importing

Using ES6 import:

import IocContainer from '@tjforryan/ioc-container';

Using require:

const IocContainer = require('@tjforryan/ioc-container').default;

API

Creating a new container

const container = new IocContainer();

When first created no dependencies will exist on the container.

Adding a dependency

There are two ways to add dependencies, depending on how you want them to be injected.

container.registerClass(<key>, <dependency>)
  • This should only be used for dependencies that need to be instantiated.
  • <key> is a string, which is used to refer to this dependency.
  • <dependency> is the class that will be instantiated as this dependency, when resolved.
container.registerVar(<key>, <dependency>)
  • This should be used for dependencies that don't need to be instantiated (eg: config variables, pre-existing instances etc).
  • <key> is a string, which is used to refer to this dependency.
  • <dependency> is the value that will be passed in as this dependency, when resolved.

Linking dependencies

container.bindDependency(<parentKey>, <childKey>, <index>)
  • For this to work there should already be two dependencies registered with the keys passed to this function. The parent needs to be a class (ie: registered using container.registerClass).
  • <parentKey> is a string that refers to the parent, which will have the dependency injected.
  • <childKey> is a string, that refers to the child, which will be the dependency that is injected.
  • <index> is the argument index which the dependency will be injected into the parent.
container.resolve(<key>)
  • If the key refers to a non-class dependency (one registered using container.registerVar), that value will be returned.
  • If the key refers to a class dependency (one registered using container.registerClass), first any sub-dependencies will be resolved (perhaps recursing through multiple levels). Then a new instance of the class registered for this dependency will be returned, with the resolved sub-dependencies being passed in to the constructor.
  • <key> is a string that refers to the dependency that will be retrieved from the container.

Notes on usage

  • Circular dependencies are not supported. Instead, when attempting to resolve one, the container will error, with information to help identify where the circular dependency is.
  • Once a dependency is registered, if another dependency is registered with the same key it will overwrite the original. This can allow for hot-swapping of dependencies.
  • It's recommended that keys exist, as constants, in some central location. This will help to prevent mistakes or even collisions.
  • If multiple modules need the same class dependency injected these will be separate instances. If your class isn't a singleton and it is important that only one instance is used and you can do this by instantiating it yourself and using container.registerVar instead of container.registerClass.
  • The package has a generated type declaration file. for use with Typescript.

Example

  • The classes used below can be found under /examples.
  • This IoC container is aimed at abstracting away dependency issues, when dependency management has become complex and hard to maintain. This is only a toy example and, although it demonstrates its usage, is not representative of the best times to use this package. This simpler example is used purely for readability.
import IocContainer from '@tjforryan/ioc-container';

import Sauce from './classes/Sauce';
import Sandwich from './classes/Sandwich';
import FancyRestaurant from './classes/FancyRestaurant';

const KEYS = {
  RESTAURANT: 'RESTAURANT',
  DISH: 'DISH',
  INGREDIENT: 'INGREDIENT',
  CHEF_NAME: 'CHEF_NAME'
};

// A new container is created
const container = new IocContainer();

// Dependencies are registered with reference keys
container.registerClass(KEYS.RESTAURANT, FancyRestaurant);
container.registerClass(KEYS.DISH, Sandwich);
container.registerClass(KEYS.INGREDIENT, Sauce);

container.registerVar(KEYS.CHEF_NAME, 'Pierre');

// Dependencies are bound to sub-dependencies using their keys
container.bindDependency(KEYS.RESTAURANT, KEYS.CHEF_NAME, 0);
container.bindDependency(KEYS.RESTAURANT, KEYS.DISH, 1);
container.bindDependency(KEYS.DISH, KEYS.INGREDIENT, 0);

// Here the top level module is resolved, with its dependencies resolved for it.
// In this case the restaurant resolves as an instance of the FancyRestaurant class.
// It receives the string 'Pierre' and an instance of the Sandwich class.
// The Sandwich class in turn has had its own dependencies resolved, before instantiation.
const restaurant = container.resolve(KEYS.RESTAURANT);