or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

binding.mdconditional.mdcontainer.mddecorators.mdindex.mdlifecycle.mdmodules.md
tile.json

tessl/npm-inversify

A powerful and lightweight inversion of control container for JavaScript and Node.js apps powered by TypeScript.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/inversify@7.9.x

To install, run

npx @tessl/cli install tessl/npm-inversify@7.9.0

index.mddocs/

InversifyJS

InversifyJS is a powerful and lightweight inversion of control (IoC) container for JavaScript and Node.js applications powered by TypeScript. It enables developers to write code that adheres to SOLID principles and encourages the use of best object-oriented programming and IoC practices. The library provides dependency injection, lifecycle management, and conditional binding features with zero runtime dependencies beyond reflection metadata.

Package Information

  • Package Name: inversify
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install inversify reflect-metadata
  • Repository: https://github.com/inversify/InversifyJS
  • Documentation: https://inversify.io

Core Imports

import { Container, injectable, inject } from "inversify";
import "reflect-metadata";

For CommonJS:

const { Container, injectable, inject } = require("inversify");
require("reflect-metadata");

Basic Usage

import { Container, injectable, inject } from "inversify";
import "reflect-metadata";

// Define interfaces
interface Warrior {
  fight(): string;
}

interface Weapon {
  hit(): string;
}

// Implement classes with decorators
@injectable()
class Katana implements Weapon {
  hit() {
    return "cut!";
  }
}

@injectable()
class Ninja implements Warrior {
  private _weapon: Weapon;

  constructor(@inject("Weapon") weapon: Weapon) {
    this._weapon = weapon;
  }

  fight() {
    return this._weapon.hit();
  }
}

// Configure container and resolve dependencies
const container = new Container();
container.bind<Warrior>("Warrior").to(Ninja);
container.bind<Weapon>("Weapon").to(Katana);

const warrior = container.get<Warrior>("Warrior");
console.log(warrior.fight()); // "cut!"

Architecture

InversifyJS is built around several key architectural components:

  • Container: The central IoC container that manages service registration, resolution, and lifecycle
  • Binding System: Fluent API for configuring how services are created and injected
  • Decorator System: TypeScript decorators for marking injectable classes and injection points
  • Resolution Engine: Handles dependency graph resolution, circular dependency detection, and service instantiation
  • Conditional Binding: Support for context-aware dependency resolution based on tags, names, and ancestry
  • Lifecycle Management: Hooks for construction/destruction events and scope management (singleton, transient, request)

Capabilities

Container Management

Core container functionality for service registration, binding configuration, and dependency resolution. The Container class provides the primary interface for IoC operations.

class Container {
  bind<T>(serviceIdentifier: ServiceIdentifier<T>): BindInFluentSyntax<T>;
  rebind<T>(serviceIdentifier: ServiceIdentifier<T>): BindInFluentSyntax<T>;
  unbind(serviceIdentifier: ServiceIdentifier): void;
  isBound(serviceIdentifier: ServiceIdentifier): boolean;
  get<T>(serviceIdentifier: ServiceIdentifier<T>): T;
  getAll<T>(serviceIdentifier: ServiceIdentifier<T>): T[];
  load(...modules: ContainerModule[]): void;
  unload(...modules: ContainerModule[]): void;
}

Container Management

Decorators and Annotations

Core decorator functions for marking classes as injectable and specifying dependency injection points. These decorators work with TypeScript's metadata reflection system.

function injectable<T>(target: Newable<T>): void;
function inject(serviceIdentifier: ServiceIdentifier): (target: any, targetKey: string, index: number) => void;
function multiInject(serviceIdentifier: ServiceIdentifier): (target: any, targetKey: string, index: number) => void;
function named(name: string): (target: any, targetKey: string, index: number) => void;
function tagged(key: string, value: any): (target: any, targetKey: string, index: number) => void;
function optional(): (target: any, targetKey: string, index: number) => void;

Decorators and Annotations

Binding Configuration

Fluent API for configuring service bindings including target specification, scope management, and conditional resolution. Supports various binding patterns from simple class binding to complex factory configurations.

interface BindToFluentSyntax<T> {
  to(constructor: Newable<T>): BindInWhenOnFluentSyntax<T>;
  toSelf(): BindInWhenOnFluentSyntax<T>;
  toConstantValue(value: T): BindWhenOnFluentSyntax<T>;
  toDynamicValue(func: (context: ResolutionContext) => T): BindInWhenOnFluentSyntax<T>;
  toFactory<T2>(factory: Factory<T2>): BindWhenOnFluentSyntax<T>;
  toProvider<T2>(provider: Provider<T2>): BindWhenOnFluentSyntax<T>;
}

interface BindInWhenOnFluentSyntax<T> {
  inSingletonScope(): BindWhenOnFluentSyntax<T>;
  inTransientScope(): BindWhenOnFluentSyntax<T>;
  inRequestScope(): BindWhenOnFluentSyntax<T>;
}

Binding Configuration

Conditional Resolution

Advanced features for context-aware dependency resolution including named bindings, tagged bindings, and ancestry-based conditional resolution. Enables sophisticated dependency injection scenarios.

interface BindWhenFluentSyntax<T> {
  when(constraint: (request: ResolutionContext) => boolean): BindOnFluentSyntax<T>;
  whenTargetNamed(name: string): BindOnFluentSyntax<T>;
  whenTargetTagged(tag: string, value: any): BindOnFluentSyntax<T>;
  whenInjectedInto(parent: Newable<any>): BindOnFluentSyntax<T>;
  whenParentNamed(name: string): BindOnFluentSyntax<T>;
  whenParentTagged(tag: string, value: any): BindOnFluentSyntax<T>;
  whenAnyAncestorIs(ancestor: Newable<any>): BindOnFluentSyntax<T>;
  whenNoAncestorIs(ancestor: Newable<any>): BindOnFluentSyntax<T>;
}

Conditional Resolution

Lifecycle Management

Lifecycle hooks and scope management for controlling service instantiation, activation, deactivation, and destruction. Supports singleton, transient, and request-scoped lifetimes.

function postConstruct(target: any, propertyKey: string): void;
function preDestroy(target: any, propertyKey: string): void;

interface BindOnFluentSyntax<T> {
  onActivation(handler: (context: ResolutionContext, injectable: T) => T): BindInFluentSyntax<T>;
  onDeactivation(handler: (injectable: T) => void): BindInFluentSyntax<T>;
}

Lifecycle Management

Module System

Container module system for organizing and packaging related service bindings. Enables modular IoC configuration and supports dynamic loading/unloading of service groups.

class ContainerModule {
  constructor(
    registry: (bind: BindFunction, unbind: UnbindFunction, isBound: IsBoundFunction, rebind: RebindFunction) => void
  );
}

interface ContainerModuleLoadOptions {
  skipDeactivation?: boolean;
}

Module System

Types

Core Service Types

type ServiceIdentifier<T = {}> = string | symbol | Newable<T> | Abstract<T>;
type Newable<T = {}> = new (...args: any[]) => T;
interface LazyServiceIdentifier<T = {}> {
  unwrap(): ServiceIdentifier<T>;
}

Factory and Provider Types

type Factory<T> = () => T;
type Provider<T> = () => Promise<T>;
type DynamicValueBuilder<T> = (context: ResolutionContext) => T;

Binding Scope Types

const bindingScopeValues: {
  Singleton: "Singleton";
  Transient: "Transient";
  Request: "Request";
};

const bindingTypeValues: {
  Instance: "Instance";
  Value: "Value";
  Constructor: "Constructor";
  Factory: "Factory";
  Provider: "Provider";
  Function: "Function";
  DynamicValue: "DynamicValue";
};

type BindingScope = keyof typeof bindingScopeValues;

Resolution Context Types

interface ResolutionContext {
  container: Container;
  currentRequest: Request;
  plan: Plan;
  addPlan(plan: Plan): void;
}

interface GetOptions {
  skipBaseClassChecks?: boolean;
}

interface GetAllOptions {
  skipBaseClassChecks?: boolean;
}

interface OptionalGetOptions extends GetOptions {
  defaultValue?: any;
}

interface GetOptionsTagConstraint {
  key: string;
  value: any;
}

interface MultiInjectOptions {
  skipDeactivation?: boolean;
  ignoreMissingBindings?: boolean;
}