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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@arcmantle/injector

v1.0.4

Published

Dependency injection done simple.

Readme

@arcmantle/injector

Dependency injection done simple.

A lightweight, type-safe dependency injection container for TypeScript/JavaScript applications with support for multiple binding types, lifetimes, and hierarchical containers.

Features

  • 🎯 Simple API - Intuitive fluent interface for binding and resolving dependencies
  • 🔧 Multiple Binding Types - Support for classes, factories, and constants
  • ⏱️ Lifetime Management - Singleton and transient lifetimes
  • 🏷️ Named & Tagged Bindings - Additional granularity for complex scenarios
  • 🌳 Hierarchical Containers - Parent-child container relationships
  • 📦 Module System - Organize related bindings into loadable modules
  • 💫 Activation Hooks - Post-creation instance processing
  • 🔍 TypeScript First - Full type safety and IntelliSense support

Installation

npm install @arcmantle/injector
# or
pnpm add @arcmantle/injector
# or
yarn add @arcmantle/injector

Basic Usage

Creating a Container

import { PluginContainer } from '@arcmantle/injector';

const container = new PluginContainer();

Binding Values

Constants

// Bind a constant value
container.bind('API_URL').constant('https://api.example.com');
container.bind('config').constant({ timeout: 5000, retries: 3 });

Classes

class DatabaseService {
  constructor(private container: PluginContainer) {}
}

class UserService {
  constructor(private container: PluginContainer) {
    this.db = container.get('database');
  }
}

// Bind classes (singleton by default)
container.bind('database').class(DatabaseService).singleton();
container.bind('users').class(UserService).transient();

Factories

// Bind a factory function
container.bind('logger').factory(container => {
  const config = container.get('config');
  return new Logger(config.logLevel);
}).singleton();

Resolving Dependencies

// Get a single instance
const config = container.get('config');
const userService = container.get<UserService>('users');

// Try to get (returns undefined if not bound)
const optional = container.tryGet('optional-service');

// Get all instances of a binding
const plugins = container.getAll('plugin');

Advanced Features

Named Bindings

// Bind multiple implementations with names
container.bind('database').class(PostgreSQLService).named('postgres');
container.bind('database').class(MongoDBService).named('mongo');

// Resolve by name
const pgDb = container.getNamed('database', 'postgres');
const mongoDb = container.getNamed('database', 'mongo');

Tagged Bindings

// Bind with name and tag for extra specificity
container.bind('cache')
  .class(RedisCache)
  .tagged('redis', 'production');

container.bind('cache')
  .class(MemoryCache)
  .tagged('memory', 'development');

// Resolve by name and tag
const prodCache = container.getTagged('cache', 'redis', 'production');

Activation Hooks

container.bind('service')
  .class(MyService)
  .onActivation((instance, container) => {
    // Perform additional setup
    instance.initialize();
    return instance;
  })
  .singleton();

Hierarchical Containers

const parentContainer = new PluginContainer();
const childContainer = new PluginContainer({ parent: parentContainer });

// Child containers inherit parent bindings
parentContainer.bind('shared').constant('parent-value');
console.log(childContainer.get('shared')); // 'parent-value'

// Child bindings override parent bindings
childContainer.bind('shared').constant('child-value');
console.log(childContainer.get('shared')); // 'child-value'

Module System

import { PluginModule } from '@arcmantle/injector';

// Create a module
const databaseModule = new PluginModule(({ bind, bindOnce, rebind }) => {
  bind('connection').factory(container => {
    const config = container.get('db-config');
    return new Connection(config);
  }).singleton();

  bind('repository').class(UserRepository).transient();
});

// Load the module
container.load(databaseModule);

// Unload when needed
container.unload(databaseModule);

Binding Methods

bind(identifier)

Creates a new binding, potentially overriding existing ones.

bindOnce(identifier)

Only binds if the identifier doesn't already exist. Returns undefined if already bound.

rebind(identifier)

Removes existing bindings for the identifier and creates a new one.

Resolution Methods

| Method | Description | |--------|-------------| | get(id) | Get single instance (throws if not found) | | tryGet(id) | Get single instance or undefined | | getNamed(id, name) | Get named instance | | getTagged(id, name, tag) | Get tagged instance | | getAll(id) | Get all instances as array | | tryGetAll(id) | Get all instances or empty array | | getLast(id) | Get the last registered instance |

Container Management

// Check if bindings exist
container.has('service');          // In this container only
container.exists('service');       // In this container or parents
container.hasNamed('service', 'name');
container.existsNamed('service', 'name');

// Remove bindings
container.unbind('service');       // Remove specific binding
container.unbindAll();             // Remove all bindings

TypeScript Usage

The library is designed with TypeScript in mind:

interface IUserService {
  getUser(id: string): User;
}

class UserService implements IUserService {
  getUser(id: string): User {
    // implementation
  }
}

// Type-safe binding and resolution
container.bind<IUserService>('users').class(UserService);
const userService = container.get<IUserService>('users');

Configuration Options

const container = new PluginContainer({
  defaultLifetime: 'transient',  // Default: 'singleton'
  parent: parentContainer        // Optional parent container
});

Best Practices

  1. Use Interfaces: Bind to interfaces rather than concrete classes for better testability
  2. Module Organization: Group related bindings into modules
  3. Singleton by Default: Use singletons for stateless services, transients for stateful ones
  4. Container Hierarchy: Use parent containers for shared dependencies
  5. Named Bindings: Use named bindings for multiple implementations of the same interface

License

Apache-2.0 © Kristoffer Roen-Lie

Contributing

This package is part of the @arcmantle monorepo. Please refer to the main repository for contribution guidelines.