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

injectree

v0.2.0

Published

Simple dependency injection library.

Downloads

3

Readme

Injectree · GitHub license npm version Build Status codecov


A simple and intuitive dependency injection library supporting containers chaining.

Example

import { Injector, Token, provider } from 'injectree';

class Greeter {
  constructor(private readonly name: string) {}
  greet() {
    return `Hello ${this.name}!`;
  }
}
const NAME = new Token<string>();
const injector = new Injector([
    provider(NAME, {value: 'World'}),
    provider(Greeter, {deps: [NAME]}),
]);

const greeter = injector.get(Greeter);
greeter.greet(); // returns 'Hello World!'

Provider types

Value provider

Provides a value directly.

Example:

const TOKEN = new Token<string>('TOKEN');
const injector = new Injector([
  provider(TOKEN, {value: 'Hello!'}),
]);

Factory provider

Provides a value returned form the factory function. Can specify dependencies that are provided to the factory function as parameters.

Example:

const TOKEN = new Token<string>('TOKEN');
const NAME = new Token<string>('NAME');
const injector = new Injector([
  provider(TOKEN, {factory: (name: string) => `Hello ${name}!`, deps: [NAME]}),
  provider(NAME, {value: 'World'}),
]);

Class provider

Provides an instance of the class. Can specify dependencies that are provided to the constructor as parameters.

Example:

class Greeter {
  constructor(private name: string) {}
  greet() {
    return `Hello ${this.name}!`;
  }
}
const NAME = new Token<string>('NAME');
const injector = new Injector([
  provider(Greeter, {class: Greeter, deps: [NAME]}),
  provider(NAME, {value: 'World'}),
]);
// or
const injector = new Injector([
  provider(Greeter, {deps: [NAME]}), // class derived from the provider token
  provider(NAME, {value: 'World'}),
]);

Token provider

Provides a value/instance provided under another token.

Example:

const TOKEN = new Token<string>('TOKEN');
const OTHER_TOKEN = new Token<string>('OTHER_TOKEN');
const injector = new Injector([
  provider(OTHER_TOKEN, {value: 'Hello!'}),
  provider(TOKEN, {token: OTHER_TOKEN}),
]);

Default providers

The defaultProvider function allows for specifying providers for tokens that are not explicitly defined on any injector. Note that the default provider needs to be defined before the injector is created.

Example:

class Service {
  getValue() {
    return 42;
  }
}
defaultProvider(Service, {deps: []});

// later

const injector = new Injector();
const service = injector.get(Service);
service.getValue(); // return 42

Multi tokens

A multi token can hold bindings to multiple values and/or instances. Multiple providers can be specified for a single multi token.

Example:

const MULTI_TOKEN = new MultiToken<string>('MULTI_TOKEN');
defaultProvider(MULTI_TOKEN, {value: 'default'});
const injector = new Injector([
  provider(MULTI_TOKEN, {value: 'first'}),
  provider(MULTI_TOKEN, {value: 'second'}),
]);

injector.get(MULTI_TOKEN); // returns ['default', 'first', 'second']

Injectors chaining

An injector can specify its parent injector when it's created. If a provider is not found in the injector and the parent injector is specified, the search will be continued in the parent injector. In case of multi token, values and/or instances will be returned also from the parent injector.

Injection options

Injection options can be used to control the resolution process. They can be specified on the Injector.get() method or on the dep function when declaring dependencies on factory and class providers.

optional

If set to true, the injector will return undefined if no provider was defined for the token instead of throwing an error.

Example:

const TOKEN = new Token<string>('TOKEN');
const injector = new Injector();
const value: string | undefined = injector.get(TOKEN, {optional: true});
const TOKEN = new Token<string>('TOKEN');
class Service {
  constructor(readonly value: string | undefined) {}
}
const injector = new Injector([
  provider(Service, {deps: [dep(TOKEN, {optional: true})]}),
]);

from

Specifies where to search for the provider.

  • self-and-ancestors (default) - search in the current injector or any of it's ancestors,
  • self - search only in the current injector,
  • ancestors - search only in ancestor injectors.

Instances lifecycle

An instance is created right after it's resolved using the Injector.get() method (either directly or as a transitive dependency). Every successive resolution for the same token will result with the same instance being returned. An instance remains active until the injector that created it is destroyed. In case of instances created using the class provider, the [onDestroy] hook is available to give an instance a chance to clean up after itself.

Example:

import {Injector, provider, onDestroy} from 'injectree';

class Service {
  private unsubscribe: () => void;
  constructor() {
    this.unsubscribe = subscribeToSomeDataSource();
  }
  
  [onDestroy]() {
    this.unsubscribe();
    this.unsubscribe = undefined;
  }
}
const injector = new Injector([
    provider(Service, {deps: []}),
])
injector.get(Service); // Service created

// later
injector.destroy(); // Service[onDestroy] called