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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@contextjs/di

v25.1.0

Published

Object-oriented dependency injection for TypeScript — class-based, extensible, and transformer-powered.

Readme

@contextjs/di

Tests  npm  License

A TypeScript-first, object-oriented dependency injection container with interface support, zero decorators, and full transformer-based resolution.

Features

  • Interface-based service registration with generics (yes, this is possible)
  • Transformer-based constructor metadata extraction
  • Singleton and transient lifetimes
  • Full constructor injection, including primitives
  • Runtime circular dependency detection
  • Fallback to global constructors (String, Number, etc.)
  • Scoped resolution support via onResolve hook
  • Clean, extensible design with 100% test coverage

Installation

npm i @contextjs/di

Quick Start

Jump to: API ReferenceAdvanced FeaturesPhilosophyTesting

1. Define services

interface ILogger {
    log(message: string): void;
}

class ConsoleLogger implements ILogger {
    log(message: string) {
        console.log('[LOG]', message);
    }
}

2. Register services

import { ServiceCollection } from '@contextjs/di';

const services = new ServiceCollection();
services.addSingleton<ILogger, ConsoleLogger>();

3. Resolve services

const logger = services.resolve<ILogger>();
logger?.log('Hello from DI!');

4. Use dependencies in Application

import '@contextjs/di';
import { Application } from '@contextjs/system';

interface ILogger {
    log(message: string): void;
}

class ConsoleLogger implements ILogger {
    log(message: string) {
        console.log('[LOG]', message);
    }
}

const application = new Application();
application.useDependencyInjection();

application.services.addTransient<ILogger, ConsoleLogger>();


application.onRun(async () => {
    const logger = application.services.resolve<ILogger>();
    logger?.log('Application is running with dependency injection!');
});

await application.runAsync();

Core Concepts

Service Collection

Acts as the container that stores service registrations and resolves instances.

Lifetimes

  • singleton: One instance per container
  • transient: A new instance per resolution

Interface Support

The transformer compiles your registration call into metadata so that interfaces can be resolved automatically, with no need for runtime tokens or reflection.

Advanced Features

API with strong typing

services.addSingleton<IInterface, Implementation>();
services.resolve<IInterface>();

Circular Dependency Detection

Detects loops and throws a CircularDependencyException with a readable chain trace.

Fallback Resolution

If a dependency isn't registered but exists on globalThis (e.g. String, Number), it will attempt to instantiate it directly.

Hookable onResolve

Control resolution at runtime (e.g. for scoped or per-request lifetimes):

services.onResolve = ({ name, lifetime, service }) => {
    if (lifetime === 'scoped') {
        return requestScope.getOrCreate(name, () => new service.type());
    }
    return null;
};

Manual registration (optional)

services.dependenciesAccessor.set('ILogger', {
    lifetime: 'singleton',
    type: ConsoleLogger,
    parameters: []
});

Testing

This project maintains 100% test coverage across:

  • Constructor metadata parsing
  • Singleton vs. transient lifetimes
  • Circular reference handling
  • globalThis fallback
  • Interface registration
  • onResolve overrides

Philosophy

Many DI containers in the JS/TS ecosystem rely on decorators and metadata reflection. These approaches are fragile, hard to test, and incompatible with interface-based architecture.

@contextjs/di takes a different path:

  • No decorators
  • Full static type safety
  • Zero runtime dependency metadata
  • A container designed for OOP in TypeScript

API Reference

For detailed API documentation, please refer to the API Reference.