Dependency Injection
Manage services and dependencies with MoroJS's sophisticated dependency injection container. Support for multiple scopes, lifecycle hooks, interceptors, and advanced patterns.
On this page
Clean Architecture with DI
MoroJS includes a sophisticated dependency injection system for managing services, dependencies, and application architecture with support for multiple scopes and lifecycle hooks.
Quick Start
Basic Service Registration
typescript
Loose Coupling
Services depend on interfaces, not implementations. Easy to swap dependencies.
Testability
Mock dependencies easily for unit testing without changing code.
Lifecycle Management
Control service lifecycle with scopes, initialization, and cleanup hooks.
Container APIs: Basic vs Enhanced
MoroJS provides two APIs for working with dependency injection: the Basic Container and the Enhanced Container. Choose based on your needs for simplicity versus advanced features.
Basic Container
Simple and direct
Direct registration with simple factory functions. Great for straightforward use cases and quick setup.
Best for:
- • Quick prototypes
- • Simple applications
- • When you don't need advanced features
- • Direct, straightforward DI
Enhanced Container
Powerful and flexible
Chainable method calls that read like natural language. Includes advanced features like lifecycle hooks, scopes, timeouts, interceptors, and more.
Best for:
- • Production applications
- • Complex dependency graphs
- • Lifecycle management
- • Service scopes (singleton, transient, etc.)
Quick Reference: Which Should I Use?
Service Scopes
MoroJS supports four different service scopes to control how and when service instances are created. Choose the right scope based on your service's lifecycle requirements.
| Scope | Lifetime | When to Use |
|---|---|---|
| Singleton | One instance for entire app | Database, cache, config |
| Transient | New instance every time | Request IDs, factories |
| Request | One instance per HTTP request | User context, tracing |
| Module | One instance per module | Module-specific state |
Singleton
A single instance is created and shared across the entire application. Perfect for stateful services like database connections, caches, and configuration.
Transient
A new instance is created every time the service is requested. Ideal for lightweight, stateless services and unique identifiers.
Request Scope
One instance is created per HTTP request and shared across that request. Perfect for user context, request-specific state, and per-request logging.
Module Scope
One instance is created per module for isolation. Great for module-specific caches, state, and services that shouldn't be shared globally.
Service Registration
Accessing the Container
The container is accessible in different contexts throughout your application. Choose the pattern that best fits your architecture.
In Routes
Via req.app
Access the container through the request object in any route handler.
Singleton Export
Recommended
Export the container from a central file for use anywhere.
Pass App Instance
For modules
Pass the app instance to modules and access the container there.
In Middleware
Via req.app
Access services in middleware through the request object.
Registration Methods
Basic Registration
Simple function-based registration. Perfect for quick setup and small applications.
Class-Based
Register class instances with proper dependency injection and lifecycle management.
Enhanced Container (Chainable Methods)
The enhanced container provides a powerful chainable methods for advanced service registration with dependencies, lifecycle hooks, and more.
With Dependencies
typescript
With Lifecycle Hooks
typescript
Advanced Features
Service Timeout and Fallback
typescript
Optional Dependencies
typescript
Service Interceptors
typescript
Service Decorators
typescript
Service Tags for Batch Resolution
typescript
Async Service Initialization
typescript