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

dry-di

v0.5.10

Published

DRY-DI: ES5/6 Dependency Injection where you Don't Repeat Yourself. Now with 100% more Interfaces!

Readme

DRY-DI

DRY-DI: ES5/6* Dependency Injection where you Don't Repeat Yourself.

  • Works in the Browser or in NodeJS!
  • Now with 100% more Interfaces!
  • Duck-Type verification!
  • No dependencies!
  • MIT License!

TL;DR

The following example requires Babel and transform-class-properties.

class InterfaceType {
    method(){ throw "Not Implemented!"; }
}

class B {
    method(){ console.log("B.method()"); }
}

class A {
    static "@inject" = {
        injectedProperty: InterfaceType
    }
    otherMethod(){
        this.injectedProperty.method();
    }
}

bind(B).to(InterfaceType);
bind(A).to("name").singleton();
getInstance("name").otherMethod();

INSTALL

npm install --save dry-di

You should also install Babel, as ES6 has some limitations.

Yet another DI container?!

Well, I was annoyed by 3 things in other DI libraries:

  • Dependency on larger frameworks and/or TypeScript.
  • Verbose and/or hard-to-read code.
  • Verbose and/or hard-to-read code.

So I wrote a tiny little framework where you write code like this:

// get the dry-di functions
let {bind, inject, getInstanceOf} = require('dry-di')

// create an IFood class to serve as an Interface
class IFood{
    eat(){ throw "Interface" };
}

// Doritos may not really be food (does not extend IFood). 
// But it sure does look like food... so good enough.
class Doritos{
    eat(){
        console.log("eating doritos");
    }
}

// Create a Mouth for the eating of IFood.
class Mouth{
    constructor(){
        
        console.log("creating mouth");
        
        // food is an injected property.
        this.food.eat(); 

    }

    again(){
        console.log("eating some more...");
        this.food.eat();
    }
}

// Mouths require things that look like IFood.
// IFood-like things go in the "food" property.
inject({ food:IFood }).into( Mouth ); 

// register Doritos as a kind of IFood.
bind(Doritos).to(IFood);

// register Mouth as a singleton called "main".
bind(Mouth).to("main").singleton(); 

// Create a Mouth
// Create Doritos
// Inject doritos into mouth.
// Call the Mouth constructor.
// Return mouth
let mouth = getInstanceOf("main"); // HERE BE MAGIC!         

// Mouth is a singleton, so don't create a new one.
// Just get the previous one, instead.
// Then eat some more!
getInstanceOf("main").again();  

Properties are automatically injected before the constructor is called. This feature isn't possible in ES6, however, so you must use a transpiler to convert it to ES5. On the other hand, that means you don't need to do this common pattern all over the place:

class A {
    dependency1:IPropertyType;
    dependency2:IPropertyType;
    dependency3:IPropertyType;
    constructor( 
            dependency1:IPropertyType, 
            dependency2:IPropertyType, 
            dependency3:IPropertyType 
        ){
        this.dependency1 = dependency1;
        this.dependency2 = dependency2;
        this.dependency3 = dependency3;
    }
}

When you have lots of classes with lots of dependencies, this gets old fast.

If you're using Babel for transpiling, you can make use of the "transform-class-properties" plugin to put your injections inside the class:

class Cabbage extends IFood {

    static "@inject" = {
        color:"IColor"
    };

    eat(){
        console.log("eating " + this.color + " cabbage");
    }

}

Injection Tags

It is possible to use tags for disambiguation. In the following example, Doritos will get injected into the Mouth as food, but not as healthyFood.

// Mouths require things that look like IFood.
// IFood-like things go in the "food" property.
inject({ 
    food:IFood, // inject IFood, regardless of tags
    healthyFood:[IFood, {healthy:true}], // inject IFood tagged healthy
}).into( Mouth ); 

// register Doritos as a kind of IFood.
bind(Doritos).to(IFood);

// register Cabbage as healthy IFood.
bind(Cabbage).to(IFood).withTags({ healthy:true });

It is also possible to inject arrays of things with the syntax:

inject({foods:[ IFood,[] ]}).into( Mouth ); // inject all foods

Of course, this can be used together with tags and/or static properties:

static "@inject" = { foods:[ IFood,[], {tasty:true}] }; // inject all tasty foods

Strings as Interfaces & Explicit Injection Binding

Also visible in the example is that you can use names instead of interface classes. This allows you to do things like instancing classes from HTML or defining variations of a class:

// Believe it or not, Cabbage actually is food!
class Cabbage extends IFood {

    static "@inject" = {
        color:"IColor"
    };

    eat(){
        console.log("eating " + this.color + " cabbage");
    }
}

bind(Cabbage).to("PurpleCabbage").injecting( ["purple", "IColor"] );
bind(Cabbage).to("GreenCabbage").injecting( ["green", "IColor"] );

Here, two variants of Cabbage are defined, with different injections for the IColor type. This can be combined with tags for diferenciation or used with array injection, if you need all the different types of cabbage.