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

dependory

v1.0.1

Published

A simple, yet powerful framework to add dependency injection to your TypeScript project.

Downloads

3

Readme

Dependory

pipeline status coverage report

A very simple, yet powerful tool to add and integrate dependency injection to your TypeScript projects using decorators.

Prerequisites

tsconfig.json

To use TypeScript decorators, you have to enable them in your tsconfig.json:

{
    "compilerOptions": {
        ...
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        ...
    }
}

experimentalDecorators allows you to use decorators in your TypeScript code and emitDecoratorMetadata allows the framework to get the metadata needed for dependency injection (like types) during runtime.

Installation

Simply install this package over npm:

$ npm i dependory

Usage

Singletons

To make use of the provided features of dependency injection, just add the decorator @Singleton() to a class:

import { Singleton } from "dependory";

@Singleton()
export class OtherClass {
    public foo: string;
    constructor() {
        this.foo = "bar";
    }
}

In another class, where you want to inject OtherClass, to the same:

import { Singleton } from "dependory";
import { OtherClass } from "./otherClass";

@Singleton()
export class MyClass {
    constructor(a: OtherClass) {
        console.log(a.foo);
    }
}

The framework will create singletons of both classes, and inject the singleton of OtherClass into the constructor of MyClass during its creation. To make use of this in an existing project, just refactor all classes to use the decorators and point node to your entry-file, the framework will create everything for you.

Transients ("Non-Singletons")

If you want to inject classes as non-singletons/transients instead of singletons, so a new instance gets created upon each injection, you can use the @Transient()-decorator.

import { Transient, Singleton } from "dependory";

// An instance gets created upon each injection
@Transient()
export class MyClass {
    private foo: string;
    constructor() {
        this.foo = "bar";
    }
}

// Only one instance will get created for all injections
@Singleton()
class Test {
    // 2 different instances get injected
    constructor(a: MyClass, b: MyClass) {
        console.log(a === b); // false
    }
}

Note: The injection in the constructor of the decorated classes will still happen.

Custom Registry

If you want to use a custom registry (not the default one), you can specify it in the decorator:

import { Singleton, Registry } from "dependory";

const myRegistry = new Registry();

@Singleton({
    registry: myRegistry
})
export class MyClass {
    private foo: string;
    constructor() {
        this.foo = "bar";
    }
}

@Transient({
    registry: myRegistry
})
export class MyOtherClass {
    private clazz: MyClass;
    constructor(clazz: MyClass) {
        this.clazz = clazz;
    }
}

Doing this, this class will be stored in your custom registry and not the the default one. This it also allows you, to scope your injections per module.

Inject class properties

If you only want to inject certain properties of a class, you can apply the @Inject() decorator to this properties.

@Inject() takes an optional parameter, which current allows you to specify the registry, from which the value to inject shall be taken from.

import { Singleton, Inject, Registry } from "dependory";

// Create an own registry for scoping our injections
const myRegistry = new Registry();

@Singleton({
    registry: myRegistry
})
class MyTestClass {
    public foo = "bar";
}

class MyClass {
    @Inject({
        registry: myRegistry
    })
    public test: MyTestClass;
}

const myInstance = new MyClass();
console.log(myInstance.test.foo); // "bar"

If registry is not provided, it will default to the general library, which gets used by the framework by default.

Inject constructor parameters

If you want to inject concrete parameters from specific registries into the constructor, you can achieve this with @Inject() aswell. Just decorate the parameter in the constructor:

import { Singleton, Inject, Registry } from "dependory";

const myRegistry = new Registry();

// We chain the decorators, so we create 2 different singletons in 2 different registries
// See "Decorator-Chaining" for details about this
@Singleton({
    registry: myRegistry
})
@Singleton()
class MyTestClass {
    public foo = Math.random();
}

// Inject the general constructor parameters from the default registry
@Singleton()
class MyClass {
    constructor(
        a: MyTestClass,
        // Inject the second parameter from another registry
        @Inject({
            registry: myRegistry
        })
        b: MyTestClass
    ) {
        console.log(a.foo === b.foo); // false
    }
}

Note: The concretely injected parameters override the parameters, that get automatically injected by the framework!

Inject via custom key

If you want to register and inject properties or parameters via custom keys, you can specify them in via the injection properties:

@Singleton({
    key: "myInjectionKey"
})
class MyClass {
    //
}

@Singleton()
class MyOtherClass {
    @Inject({
        key: "myInjectionKey"
    })
    private value: any;
}

Note: The custom key will always overwrite the class hash (the default value for a class to be injected with).

Decorator-Chaining

By default, you can chain the decorators in combination with different registries, to store classes both as singletons and as transients.

import { Singleton, Transient, Inject, Registry } from "dependory";

const myRegistry = new Registry();

@Transient({
    registry: myRegistry
})
@Singleton()
class MyClass {
    public value: numer;
    constructor() {
        this.value = Math.random();
    }
}

@Singleton({
    registry: myRegistry
})
class MyOtherClass {
    @Inject()
    private a: MyClass;
    @Inject()
    private b: MyClass;

    constructor(c: MyClass, d: MyClass) {
        console.log(this.a.value === this.b.value); // true
        console.log(c.value === d.value); // false
    }
}