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 🙏

© 2024 – Pkg Stats / Ryan Hefner

codependent

v3.0.8

Published

Dependency injection container for ES6 and beyond

Downloads

25

Readme

Codependent - A dependency injector

We all know about angular style dependency injection. It is nice and sweet, but what if it could be even better? Due to the conditional initialization of default parameters it can!

Requirements

This package does not work with older versions of Node. You will need Node/6.0.0 or greater.

How to create an injection container

const Codependent = require('codependent');

// Constructed with an arbitrary container name - used for error messages
const container = new Codependent('my container');

How to register objects in the container

container.constant(‹name› ‹value›)

Stores the value in the container. That simple

container.constant('hello', 'world');

container.get('hello'); // => 'world'

container.register(‹name›, ‹handler›)

The handler is a function that is dependecy injected. This is useful if you need something from the container when creating the object.

container.constant('apiUrl', 'https://path-to-my.api');
container.register('photosUrl', (apiUrl) => apiUrl + '/photos');

container.get('photosUrl'); // => 'https://path-to-my.api/photos'

container.class(‹name›, ‹class or function›)

Creates a new instance of the class every time it is injected. In an ES6 class, the constructor is injected, in an ES5 class, the function itself is injected. Either way it is newed up.

class MyClass {
    constructor(meaningOfLife) {
        this.meaningOfLife = meaningOfLife;
    }
}
container.costant('meaningOfLife', 42);
container.class('myClass', MyClass);

container.get('myClass').meaningOfLife === 42 // => true

container.singleton(‹name›, ‹class or function›)

Same as function except that only one instance will ever be created (unless the value is redefined in the container). Singletons are eagerly instantiated, so you must register it in the container before its dependencies

container.singleton('myClass', MyClass);

container.provider(‹name›, ‹handler›)

The handler function is called and injected every time you inject the value. The return value of the handler is what is injected.

let i = 0;
container.constant('message', 'hello world');
container.provider('counter', message => {
    i += 1;
    return message + ' ' + i;
});

container.get('counter'); // => 'hello world 1'
container.get('counter'); // => 'hello world 2'
container.get('counter'); // => 'hello world 3'
// ...

How to create injectable classes, functions and methods

Default argument

Arguments are lazy loaded, which enables us to inject dependencies with this sweet syntax. Admittedly it is a hack, so if you're not comfortable with that, use angular style injection.

class MyClass {
    constructor(x = isInjected) {
    }
}

function myFunc(x = isInjected) {
}

let myFunc = (x = isInjected) => {
}

let myObj = {
    myMethod(x = isInjected) {
    }
}

Angular style

class MyClass {
    constructor(isInjected) {
    }
}

function myFunc(isInjected) {
}

let myFunc = (isInjected) => {
}

let myFunc = isInjected => {
}

let myObj = {
    myMethod(isInjected) {
    }
}

How to inject

... into classes

container.instantiate(MyClass);

... into functions

container.callFunction(myFunction);

Extending a Codependent container

const containerA = new Codependent('A');
const containerB = new Codependent('B');

// let containerB access all
// values stored in containerA
containerB.extend(containerA);

containerA.constant('greeting', 'Hello world!');
containerB.get('greeting'); // => 'Hello world'

Recursive injection

How it's awesome - simplicity

When a class or provider is injected, all of its dependencies will themselves be injected. Thus it all resolves quite nicely into the desired object.

How it can be bad - infinite recursion

so if module A requires itself or if another infinite dependency recursion occurs, it will cause the call stack size to be exceeded.

How it can be remedied

Register a value or a provider depending on your needs and manually create the object.

How to dependency inject

In these examples injected and injectedAsWell are the keys that are looked up in the injection container and x is a variable the injected value is assigned to in the function or class constructor.

container.callFunction(‹function›)

Dependency inject the function and call it.

container.callFunction(function (x = injected, injectedAsWell) {
    // ...
});

container.instantiate(‹class or function›)

Dependency inject a class constructor or a function and create a new instance.

class MyClass {
    constructor(x = injected, injectedAsWell) {
        // ...
    }
}
function FnClass(x = injected, injectedAsWell) {}

container.instantiate(MyClass);
container.instantiate(FnClass);

container.get(‹name›)

Returns the injectable value. Works just the same as when you actually inject the value.

container.get('injected');

TODO

get-args

  • Refactor get-args into separate npm-module.
  • Replace regex with state machine.
  • Exhaust all possible ways a function/method can be made in es7

Container

  • If an injected class extends another class and has no constructor, the constructor of the extended class should be injected into.
    • This has some isses that needs to be worked out...

Contributer notes

Testing

npm install -g mocha npm install npm test

Not happy with something?

Send me a pull request and I will get it sorted out! Tests are mandatory for pull requests. The get-args function has tests and is working, but it is ugly and probably has suboptimal performance, so I would be happy about pull requests for that one! :)