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

@kwyjibo-developments/typescript-dependency-injection

v0.2.0

Published

DI container for typescript project

Downloads

6

Readme

Dependency Injection for Typescript

Build status npm

Motivation

Common dependency injection packages in typescript, such as tsyringe or inversify rely on the reflect-metadata package to determine argument types and perform autowiring when constructing instances. In order to accomplish this functionality, decorators must be used to provide type information. The requirement to use decorators throughout the codebase adds increased complexity as there is no single location where all dependency information is maintained.

Without the use of reflection, the consumer is responsible for labeling services that will be available through the dependency injection container, as well as providing a dependency list for each service. This package takes the approach of using a string label for each service, as well as a string array for its dependencies, to remove the need for decorators and to permit dependency information to be defined in a single location. An additional benefit of this approach is that the library is not restricted to TypeScript, but can be used within JavaScript projects as well.

Features

  • Simple and powerful framework
  • Suitable for both JavaScript and TypeScript
  • Does not require the use of decorators

Installation

npm install @kwyjibo-developments/typescript-dependency-injection

Usage

import ServiceCollection, { Singleton, Transient } from '@kwyjibo/typescript-dependency-injection';

class Foo {}
class Bar {
    constructor(public foo: Foo) {}
}
class Baz {
    constructor(public foo: Foo) {}
}
class BarBaz {
    constructor(public bar: Bar, public baz: Baz) {}
}

const container = new ServiceCollection()
                    .registerService(Singleton.fromInstance("Foo", new Foo()))
                    .registerService(Transient.ofType("Bar", Bar).withDependencies(["Foo"]))
                    .registerService(Singleton.fromFactory("Baz", (p) => new Baz(p.resolve<Foo>("Foo"))))
                    .registerService(Singleton.ofType("BarBaz", BarBaz).withDependencies(["Bar", "Baz"]))
                    .build();

const bar = container.resolve<Bar>("Bar");

Services registered with Singleton will only be constructed once for the lifetime of the container, while services registered as Transient will be constructed each time the service is requested. Services registered as Instance will return the provided instance for all requests.

Note: Service names do not need to correspond to implentation or class names. This is only done for clarity and code maintenance.

Singleton instances

Singleton instances are constructed from the Singleton service descriptor. A singleton instance will only be constructed once for the lifetime of the container. There are three construction methods provided for creating singleton instances:

  • Singleton.ofType constructs an instance based on a constructor function of a defined type;
class Foo {}
const descriptor = Singleton.ofType("Service", Foo);

Dependencies can be specified as an array of service names in the .withDependencies method.

class Foo {}
class Bar {
    constructor(public foo: Foo) {}
}
const fooDescriptor = Singleton.ofType("ServiceName", Foo);
const barDescriptor = Singleton.ofType("BarService", Bar).withDependencies(["ServiceName"]);
  • Singleton.fromInstance stores a reference to the instance to be returned when the service is requested; and
class Foo {}
const descriptor = Singleton.fromInstance("Service", new Foo());
  • Singleton.fromFactory provides a callback function that has the ServiceProvider available to construct more complex instances.
class Foo {
    constructor (public value: number) {}
}

function serviceFactory(provider: ServiceProvider) {
    const rngService = provider.resolve<RngService>("RandomNumberGenerator");
    const randomNumber = rngService.getNumber();
    return new Foo(randomNumber);
}

const descriptor = Singleton.fromFactory("Service", serviceFactory);

Transient instances

Transient instances are constructed from the Transient service descriptor. A new transient instance will be constructed each time one is requested from the container.

Transient instances can only be constructed by specifying a constructor function.

class Foo {}
const descriptor = Transient.ofType("Service", Foo);

Dependencies can be specified as an array of service names in the .withDependencies method.

class Foo {}
class Bar {
    constructor(public foo: Foo) {}
}
const fooDescriptor = Transient.ofType("ServiceName", Foo);
const barDescriptor = Transient.ofType("BarService", Bar).withDependencies(["ServiceName"]);