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

minjex

v0.5.0

Published

Minimal dependency injection for Node.js with TypeScript support

Readme

Dependency Injection for Node.js

A simple and intuitive asynchronous Dependency Injection library for Node.js with full TypeScript support and comprehensive test coverage.

Node.js TypeScript Test Coverage

Why Dependency Injection?

Dependency Injection vs. Pub-Sub/Event Listeners

| Aspect | Dependency Injection | Pub-Sub/Event Listeners | |--------|---------------------|-------------------------| | Execution Timing | Executes when dependencies are available | Fires immediately when event is emitted | | Dependency Management | Creates dependency graph, resolves in correct order | No dependency tracking, manual coordination required | | Error Handling | Centralized validation and error handling | Scattered across multiple listeners | | Type Safety | Full TypeScript support with compile-time checking | Limited type safety, runtime errors common | | Testing | Easy to mock and test individual components | Complex setup with event mocking | | Coupling | Loose coupling through interfaces | Tight coupling to event names and signatures |

When to Use This Library

✅ Use Dependency Injection when:

  • You need to coordinate multiple services that depend on each other
  • You want to ensure services are initialized in the correct order
  • You need type-safe dependency resolution
  • You want to easily test and mock individual components
  • You need to handle complex initialization sequences

❌ Use Pub-Sub/Event Listeners when:

  • You need immediate, fire-and-forget notifications
  • You want to decouple completely unrelated components
  • You need one-to-many communication patterns
  • You're building real-time systems with immediate responses

Example: Dependency Injection vs. Event Listeners

Event Listeners (Immediate Execution):

// Event listeners fire immediately, even if dependencies aren't ready
eventBus.on('userCreated', (user) => {
  // This might fail if database isn't connected yet
  database.saveUser(user);
});

eventBus.on('userCreated', (user) => {
  // This might fail if email service isn't configured
  emailService.sendWelcomeEmail(user);
});

// Fires immediately - listeners might fail
eventBus.emit('userCreated', user);

Dependency Injection (Coordinated Execution):

// Dependencies are resolved in correct order
injector.resolve(['database', 'emailService'], (db, email) => {
  // Both services are guaranteed to be ready
  db.saveUser(user);
  email.sendWelcomeEmail(user);
});

// Register dependencies when they're actually ready
injector.register('database', databaseConnection);
injector.register('emailService', emailService);

Features

  • Full TypeScript Support - Complete type definitions and IntelliSense
  • Modern Node.js - Requires Node.js 20+ with latest features
  • Asynchronous Resolution - Lazy dependency resolution
  • High Test Coverage - 97.95% overall coverage, 100% source code coverage
  • Zero Dependencies - Only uses lodash for utility functions
  • Lightweight - Minimal overhead and bundle size

Requirements

  • Node.js 20.0.0 or higher
  • TypeScript 5.0 or higher (for development)

Installation

npm install --save minjex

Quick Start

JavaScript

const DependencyInjector = require('minjex');

const injector = new DependencyInjector();

// Register dependencies
injector.register('database', { host: 'localhost', port: 5432 });
injector.register('apiKey', 'your-api-key-here');

// Resolve dependencies
injector.resolve(['database', 'apiKey'], (db, key) => {
  console.log('Database:', db);
  console.log('API Key:', key);
  // Your application logic here
});

TypeScript

import DependencyInjector, { DependencyInjectionOptions } from 'minjex';

interface DatabaseConfig {
  host: string;
  port: number;
}

const injector = new DependencyInjector();

// Register dependencies with type safety
injector.register('database', { host: 'localhost', port: 5432 } as DatabaseConfig);
injector.register('apiKey', 'your-api-key-here');

// Resolve dependencies with full type support
injector.resolve(['database', 'apiKey'], (db: DatabaseConfig, key: string) => {
  console.log('Database:', db);
  console.log('API Key:', key);
});

API Reference

Constructor

new DependencyInjector(options?: DependencyInjectionOptions)

Options:

  • debug?: boolean - Enable debug logging (default: false)
  • dependencies?: Record<string, any> - Pre-register dependencies
  • dependants?: Record<string, Resolver[]> - Pre-register dependants

Methods

register(dependencyKey: string, dependencyValue: any): void

Registers a dependency that can be resolved later.

injector.register('service', new MyService());
injector.register('config', { timeout: 5000 });

resolve(dependencies: string[], resolver: ResolverFunction): void

Resolves dependencies and invokes the resolver function when all dependencies are available.

injector.resolve(['service', 'config'], (service, config) => {
  // This function is called when both 'service' and 'config' are available
  service.initialize(config);
});

inject(dependencies: string[]): void

Manually triggers dependency injection for the specified dependencies.

Advanced Usage

Lazy Resolution

Dependencies can be registered after resolvers are defined:

// Define resolver first
injector.resolve(['userService'], (userService) => {
  console.log('User service is ready!');
});

// Register dependency later
setTimeout(() => {
  injector.register('userService', new UserService());
}, 1000);

Context Access

Access dependencies through the this context:

injector.resolve(['db', 'cache'], function() {
  const database = this.db;
  const cache = this.cache;
  
  // Use dependencies
  database.query('SELECT * FROM users');
});

Dependency Change Detection

Resolvers are automatically re-invoked when dependencies change:

injector.resolve(['config'], (config) => {
  console.log('Config updated:', config);
});

injector.register('config', { version: '1.0' }); // Resolver called
injector.register('config', { version: '1.0' }); // Not called (same value)
injector.register('config', { version: '2.0' }); // Resolver called again

Debug Mode

Enable debug logging to track dependency resolution:

const injector = new DependencyInjector({ debug: true });

injector.register('test', 'value');
// Output: [DependencyInjection] register [Arguments] { '0': 'test', '1': 'value' }
// Output: [DependencyInjection] inject [ 'test' ]

Development

Prerequisites

  • Node.js 20+
  • npm or yarn

Setup

git clone https://github.com/serendipious/node-dependency-injection.git
cd node-dependency-injection
npm install

Building

npm run build

Testing

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test -- --reporter=html

Code Quality

The project maintains high code quality standards:

  • TypeScript with strict type checking
  • Pre-commit hooks that run tests and coverage checks
  • 97.95% test coverage with comprehensive test suite
  • Automated quality gates prevent commits that don't meet standards

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

License

BSD License - see LICENSE file for details.

Changelog

v0.5

  • Initial release as minjex
  • TypeScript migration from CoffeeScript
  • Node.js 20+ support
  • Comprehensive test suite (97.95% coverage)
  • Full type definitions
  • Pre-commit hooks for quality assurance
  • Modern documentation and contribution guidelines