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

@typeix/di

v8.7.0

Published

Typescript dependency injection

Downloads

69

Readme

@typeix/di

Build Status Coverage Status npm

Dependency Injection

Dependency Injection (DI) is a design pattern used to implement IoC. It allows the creation of dependent objects outside of a class and provides those objects to a class through different ways. Using DI, we move the creation and binding of the dependent objects outside of the class that depends on them.

Installing

npm i @typeix/di --save

Decorators

| Decorator | Info | | ------------------- | ------------------------------------ | | @Injectable() | specifies that Typeix can use this class in the DI system. decorators can be used on classes only. | | @Inject() | specifies DI system, which object to provide when object is created, if there is no provider defined DI will throw error with explanation. | | @AfterConstruct() | specifies DI system, what to execute immediately after object is created. | | @CreateProvider() | decorator specifies DI system, to create new provider on injection point, this will create new object even if there is a provider defined in parent Injector. |

Interceptors

An interceptor pattern is a software design pattern that is used when software systems or frameworks want to offer a way to change, or augment, their usual processing cycle.

import {Injectable, Injector, Inject, createMethodInterceptor} from "@typeix/di";

@Injectable()
class LoggerInterceptor implements Interceptor {

  @Inject() logger: Logger;

  async invoke(method: Method): Promise<any> {
    const result = await method.invoke();
    this.logger.info(method.args.message, result);
    return result;
  }
}

export function Logger(message) {
  return createMethodInterceptor(Logger, LoggerInterceptor, {message});
};

@Injectable()
class ChildService {
  @Logger("Logging ChildService.getName result: ")
  getName(): string {
    return this.name;
  }
}

Usage

In order to create an object of some class you need to define class as @Injectable and injection points via @Inject, then when creating an instance you need to provide DI what to construct and which providers to create.

import {Injectable, Injector, Inject} from "@typeix/di";

@Injectable()
class NameService {

  @Inject("name") private name: string;

  getName() {
    return this.name;
  }
}

@Injectable()
class ChildService {

  @Inject() nameService: NameService;

  getName(): string {
    return this.nameService.getName();
  }
}

Injector.createAndResolve(ChildService, [
  {provide: "name", useValue: "Igor"},
  NameService
]).then(injector => {
  let service = injector.get(ChildService);
  return service.getName();
});

Provider Types

There are three type of providers class, value and factory provider, functions inside providers array are converted to class providers.

There are three types of providers in total: {provde, useClass} is a class provider. {provde, useFactory} is a factory provider. {provde, useValue} is a value provider.

Dependent providers?: Array<Function | IProvider> inside of provider (class and factory) are extra dependencies that are created before provider and delivered as dependencies to provider itself.

interface IProvider {
  provide: any;
  useValue?: any;
  useClass?: Function;
  useFactory?: Function;
  providers?: Array<Function | IProvider>;
}

Injector API

NOTE: By default all providers are immutable, however you can define mutable provider keys. If provider is not mutable, and you are trying to create new instance of same provider on current Injector instance, injector will throw error.

Injector.getProviders(provider: IProvider, propertyKey?: string) will return all providers which needs to be injected, if propertyKey is not defined injector will return providers for constructor.

Injector.getAllMetadataForTarget(provider: IProvider) will return all metadata, injector cache them internally. Works with class provider only.

class Injector {
  constructor(_parent?: Injector, keys?: Array<any>);
  static getProviders(provider: IProvider, propertyKey?: string): Array<IProvider>;
  // returns all metadata for provider
  static getAllMetadataForTarget(provider: IProvider): Array<IMetadata>;
  // creates new child injector, provider and providers
  static createAndResolveChild(parent: Injector, Class: Function | IProvider, providers: Array<MixedProvider>): Promise<Injector>;
  // creates new injector, provider and providers
  static createAndResolve(Class: Function | IProvider, providers: Array<MixedProvider>): Promise<Injector>;
  // creates new provider and providers
  createAndResolve(provider: IProvider, providers: Array<IProvider>): Promise<any>;
  // clens current injectables and all child injectors & providers
  destroy(): void;
  // check if providier exists on current SyncInjector instance
  has(key: any): boolean;
  // get provider value from current SyncInjector if not found bubble parrent's
  // if not found on any of parents exception is thrown.
  get(provider: string, Class?: IProvider): any;
  get<T>(provider: Type<T>, Class?: IProvider): T;
  // set provider and value
  set(key: any, value: Object): void;
  getParent(): Injector;
  setParent(injector: Injector): void;
  setName(provider: IProvider): void;
  hasChild(injector: Injector): boolean;
  addChild(injector: Injector): this;
}

Sync Injector API

Since version 8.x default Injector behavior is converted to async API, if you want to use sync api you need to use Injector.Sync.createAndResolve or Injector.Sync.createAndResolveChild difference is that Async API supports Async providers, it's allowed to use of async/await in factory and return Promises in value provider!

class SyncInjector {
  constructor(_parent?: Injector, keys?: Array<any>);
  static getProviders(provider: IProvider, propertyKey?: string): Array<IProvider>;
  // returns all metadata for provider
  static getAllMetadataForTarget(provider: IProvider): Array<IMetadata>;
  // creates new child injector, provider and providers
  static createAndResolveChild(parent: Injector, Class: Function | IProvider, providers: Array<MixedProvider>): Injector;
  // creates new injector, provider and providers
  static createAndResolve(Class: Function | IProvider, providers: Array<MixedProvider>): Injector;
  // creates new provider and providers
  createAndResolve(provider: IProvider, providers: Array<IProvider>): any;
  // clens current injectables and all child injectors & providers
  destroy(): void;
  // check if providier exists on current SyncInjector instance
  has(key: any): boolean;
  // get provider value from current SyncInjector if not found bubble parrent's
  // if not found on any of parents exception is thrown.
  get(provider: string, Class?: IProvider): any;
  get<T>(provider: Type<T>, Class?: IProvider): T;
  // set provider and value
  set(key: any, value: Object): void;
  getParent(): Injector;
  setParent(injector: Injector): void;
  setName(provider: IProvider): void;
  hasChild(injector: Injector): boolean;
  addChild(injector: Injector): this;
}