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

dil

v2.0.4

Published

dil, in hindi/urdu literal meaning heart, is a DI container in typescript nodejs

Downloads

6

Readme

Dil: Your Heartfelt Dependency Injection Container for TypeScript & JavaScript

Dil, literally meaning "heart" in Hindi/Urdu, is a simple, intuitive, and lightweight Dependency Injection (DI) container designed to bring testability, maintainability, and scalability to your TypeScript and JavaScript applications.

Say goodbye to manual dependency management and tight coupling. With Dil, you register your services once, and the container handles resolving and injecting them wherever they're needed. This empowers you to build modular, loosely coupled codebases that are a joy to work with and easy to test.


✨ Why Dil?

  • Simplicity at its Core: A minimal API that's easy to learn and integrate into any project.
  • Boosts Testability: Easily swap out dependencies with mocks or stubs for isolated unit testing.
  • Promotes Loose Coupling: Decouple your components, making your codebase more flexible and easier to refactor.
  • Manages Lifecycles: Supports both transient (new instance every time) and singleton (single shared instance) services.
  • TypeScript-First: Built with TypeScript for excellent type inference and a smooth developer experience.

🚀 Installation

Getting started with Dil is straightforward:

npm install dil
# or
yarn add dil

📖 Usage & Examples

Dil's API is designed for clarity. You register your services with the container and then resolve them when you need an instance.

Core Methods

| Method | Parameters | Description | | :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | register<T>(key, Class, dependencies?) | key (string, required): A unique string identifier for the service.<br>Class (T, required): The constructor function of the class to register.<br>dependencies (string[], optional): An array of string keys representing the dependencies this class needs, in the exact order of its constructor parameters. | Registers a service as transient. A new instance of Class will be created and returned every time it's resolved. If dependencies are provided, Dil will resolve these first and pass them to Class's constructor in the specified order. | | registerTransient<T>(key, Class, dependencies?) | Same as register<T> | Explicitly registers a service as transient. (Identical behavior to register<T>). | | registerSingleton<T>(key, Class, dependencies?) | Same as register<T> | Registers a service as a singleton. The Class will be instantiated only once the first time it's resolved. Subsequent resolutions will return the same instance. Dependencies are resolved and passed to the constructor as with transient services. | | resolve<T>(key) | key (string, required): The unique string identifier of the registered service you wish to resolve. | Resolves and returns an instance of the registered service. If the service has dependencies, Dil will automatically resolve and inject them into its constructor. Returns the appropriate lifecycle instance (new for transient, existing for singleton). |

Example Walkthrough

Let's illustrate how to use Dil with a common scenario: logging and user management.

// services/LoggerService.ts
export class LoggerService {
  log(message: string): void {
    console.log(`[LOG]: ${message}`);
  }

  error(message: string): void {
    console.error(`[ERROR]: ${message}`);
  }
}

Now, a service that depends on our LoggerService:

// services/UserService.ts
import { LoggerService } from './LoggerService';

export class UserService {
  // Dil expects constructor parameters to match the order of declared dependencies
  constructor(private logger: LoggerService) {}

  getUserById(id: string) {
    this.logger.log(`Attempting to fetch user with ID: ${id}`);
    // ... actual logic to fetch user
    return { id: id, name: "Dil User" }; // Dummy data
  }
}

And another service using the same logger:

// services/EmployeeService.ts
import { LoggerService } from './LoggerService';

export class EmployeeService {
  constructor(private logger: LoggerService) {}

  getEmployeeById(id: string) {
    this.logger.log(`Attempting to fetch employee with ID: ${id}`);
    // ... actual logic to fetch employee
    return { id: id, name: "Dil Employee" }; // Dummy data
  }
}

Finally, register and resolve your services using the container:

// app.ts (Your application's entry point)
import { container } from 'dil';
import { LoggerService } from './services/LoggerService';
import { UserService } from './services/UserService';
import { EmployeeService } from './services/EmployeeService';

// --- Registering Services with Dil ---

// Register LoggerService as a Singleton.
// It doesn't have any dependencies, so the 'dependencies' array is omitted.
container.registerSingleton<LoggerService>('loggerService', LoggerService);

// Register UserService as Transient.
// It depends on 'loggerService', so we pass its key in the dependencies array.
// The order here MUST match the constructor parameter order in UserService.
container.register<UserService>('userService', UserService, ["loggerService"]);

// Register EmployeeService as Transient.
// It also depends on 'loggerService'.
container.register<EmployeeService>('empService', EmployeeService, ["loggerService"]);


// --- Resolving and Using Services ---

console.log("--- Resolving UserService ---");
const userService = container.resolve<UserService>('userService');
const user = userService.getUserById("123");
console.log("User:", user);

console.log("\n--- Resolving EmployeeService ---");
const employeeService = container.resolve<EmployeeService>('empService');
const employee = employeeService.getEmployeeById("A789");
console.log("Employee:", employee);

// Since LoggerService is a singleton, both userService and employeeService
// will receive the *same instance* of LoggerService.
const anotherUserService = container.resolve<UserService>('userService');
console.log("\nAre logger instances the same?", userService['logger'] === anotherUserService['logger']); // true

🛣️ Future Enhancements

We're continuously working to make Dil even more powerful and developer-friendly. Future plans include:

  • Decorator-based Dependency Resolution: For a more concise and type-safe way to define dependencies directly on your classes (e.g., @injectable(), @inject('ILogger')).
  • Asynchronous Service Resolution: Support for services that require async initialization.
  • Improved Error Diagnostics: Clearer messages for common issues like missing dependencies or circular dependencies.

🤝 Contributing

We welcome contributions! If you have suggestions, bug reports, or want to contribute code, please feel free to open an issue or submit a pull request on our GitHub repository.