A modern, lightweight dependency injection container for TypeScript with decorators, inspired by industry-leading frameworks.
The DI library that doesn't make you want to inject yourself with coffee ☕
NexusDI is a modern, lightweight dependency injection (DI) container for TypeScript and Node.js. It uses TypeScript decorators and a modular architecture to help you write scalable, testable, and maintainable applications. Inspired by frameworks like InversifyJS, tsyringe, TypeDI, and NestJS, NexusDI brings a developer-friendly API to your JavaScript and TypeScript projects. Works seamlessly in Node.js and modern JavaScript environments.
We want your input!
NexusDI thrives on community input!
We have a number of open RFCs and discussions, and your feedback can help guide the direction of the project.
Jump in and let us know what you think!
👉 Share your ideas and feedback in the Ideas Discussions
We look forward to hearing from you!
- 🚀 TypeScript Decorators – Harness the power of TypeScript decorators for robust, type-safe dependency injection
- 🧩 Powerful Module System - Organize your application into modules with support for both static and dynamic configuration
- ⚡ Dynamic Configuration - Static methods for environment-specific module configuration (inspired by industry leaders)
- 🎯 Developer-Friendly API - Clean and intuitive API that makes dependency management simple
- 📦 Lightweight - Low dependency, minimal bundle size
- 🔧 Flexible - Support for both class-based and factory providers
- TypeScript-first: Designed for modern TypeScript and JavaScript projects.
- Zero bloat: Minimal dependencies, small bundle size, and no runtime dependencies.
- TypeScript decorators: Uses TypeScript's
experimentalDecoratorsfor clean, intuitive code. - Modular & extensible: Organize your app with modules, plugins, and dynamic configuration.
- Testable: Easily mock or override providers for unit and integration testing.
- Inspired by the best: Familiar patterns for those coming from InversifyJS, tsyringe, TypeDI or NestJS.
NexusDI is an alternative to:
- InversifyJS
- tsyringe
- TypeDI
- NestJS DI system
A consumer that imports Nexus, Service, Inject, and Token from @nexusdi/core@0.3.2, registers two services, and resolves one comes to 6,247 bytes minified and 2,257 bytes gzipped, bundled with esbuild 0.28.2 (--bundle --minify --format=esm, target: ES2022, experimentalDecorators) against the published npm package; see scripts/measure-bundle-0.3.mjs to reproduce it or measure another import combination. NexusDI 0.4 will include a reproducible benchmark harness that compares DI containers on bundle size, startup, resolve time, and build time.
👉 See the Performance & Bundle Size article for methodology and details.
npm install @nexusdi/coretsconfig.json
{
"compilerOptions": {
"target": "ES2022", // or later
"experimentalDecorators": true,
"useDefineForClassFields": true
}
}Note: Only these options are required for NexusDI v0.3+.
import { Nexus, Service, Token, Inject } from '@nexusdi/core';
// Define service interface and token
interface IUserService {
getUsers(): Promise<User[]>;
}
const USER_SERVICE = new Token<IUserService>('UserService');
// Create service with dependency injection
@Service(USER_SERVICE)
class UserService implements IUserService {
constructor(@Inject(LOGGER_SERVICE) private logger: ILoggerService) {}
async getUsers(): Promise<User[]> {
this.logger.info('Fetching users');
return [{ id: 1, name: 'John' }];
}
}
// Use the container
const container = new Nexus();
container.set(UserModule);
const userService = container.get(USER_SERVICE);NexusDI supports dynamic module configuration with a simple base class approach:
import { Module, DynamicModule } from '@nexusdi/core';
interface DatabaseConfig {
host: string;
port: number;
database: string;
}
const DATABASE_CONFIG = Symbol('DATABASE_CONFIG');
@Module({
providers: [DatabaseService], // Simplified format - uses @Service decorator token
})
class DatabaseModule extends DynamicModule<DatabaseConfig> {
protected readonly configToken = DATABASE_CONFIG;
}
// Usage
const container = new Nexus();
// Synchronous configuration
container.set(
DatabaseModule.config({
host: 'localhost',
port: 5432,
database: 'dev_db',
}),
);
// Asynchronous configuration
container.set(
DatabaseModule.configAsync(async () => ({
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT),
database: process.env.DB_NAME,
})),
);We welcome contributions! Please see our Contributing Guide for details.
MIT License - see LICENSE for details.