Package Exports
- @ooneex/container
- @ooneex/container/package.json
Readme
@ooneex/container
Dependency injection container built on Inversify -- manages service lifecycle with singleton, transient, and request-scoped registrations and automatic dependency resolution.
Features
✅ Dependency Injection - Full DI container with automatic dependency resolution
✅ Multiple Scopes - Support for Singleton, Transient, and Request scopes via EContainerScope
✅ Service Aliases - Register services with string aliases for flexible resolution
✅ Constant Values - Store and retrieve constant values with string or symbol identifiers
✅ Type-Safe - Full TypeScript support with generic type parameters on get and getConstant
✅ Inversify Based - Built on the Inversify library with a shared singleton DI instance
✅ Shared Instance - Pre-configured global container instance exported for convenience
✅ Service Lifecycle - Add, get, has, and remove services and constants programmatically
Installation
bun add @ooneex/containerUsage
Basic Usage
import { container, EContainerScope } from '@ooneex/container';
class UserService {
public getUsers() {
return [{ id: 1, name: 'John' }];
}
}
// Register as singleton (default)
container.add(UserService);
// Resolve instance
const userService = container.get(UserService);
console.log(userService.getUsers());Different Scopes
import { container, EContainerScope } from '@ooneex/container';
class DatabaseConnection {
public readonly id = Math.random();
}
class RequestLogger {
public readonly id = Math.random();
}
class TemporaryWorker {
public readonly id = Math.random();
}
// Singleton - same instance throughout app lifetime
container.add(DatabaseConnection, EContainerScope.Singleton);
// Request - new instance per request context
container.add(RequestLogger, EContainerScope.Request);
// Transient - new instance every time
container.add(TemporaryWorker, EContainerScope.Transient);
const db1 = container.get(DatabaseConnection);
const db2 = container.get(DatabaseConnection);
console.log(db1.id === db2.id); // true (singleton)
const worker1 = container.get(TemporaryWorker);
const worker2 = container.get(TemporaryWorker);
console.log(worker1.id === worker2.id); // false (transient)Using Aliases
import { container } from '@ooneex/container';
class EmailService {
public send(to: string, message: string) {
console.log(`Sending to ${to}: ${message}`);
}
}
container.add(EmailService);
container.addAlias('mailer', EmailService);
// Resolve by alias
const mailer = container.get<EmailService>('mailer');
mailer.send('user@example.com', 'Hello!');Constants
import { container } from '@ooneex/container';
// Store configuration values
container.addConstant('app.name', 'My Application');
container.addConstant('app.version', '1.0.0');
container.addConstant('app.config', {
debug: true,
maxConnections: 100
});
// Retrieve constants
const appName = container.getConstant<string>('app.name');
const config = container.getConstant<{ debug: boolean }>('app.config');
console.log(appName); // "My Application"
console.log(config.debug); // trueWith Decorators
import { injectable, inject, container } from '@ooneex/container';
@injectable()
class Logger {
public log(message: string) {
console.log(`[LOG] ${message}`);
}
}
@injectable()
class UserRepository {
constructor(@inject(Logger) private readonly logger: Logger) {}
public findAll() {
this.logger.log('Finding all users');
return [];
}
}
container.add(Logger);
container.add(UserRepository);
const repo = container.get(UserRepository);
repo.findAll();API Reference
Classes
Container
Main dependency injection container class.
Constructor:
new Container()Methods:
add(target: Constructor, scope?: EContainerScope): void
Registers a class with the container.
Parameters:
target- The class constructor to registerscope- Optional scope (default:EContainerScope.Singleton)
Example:
container.add(MyService);
container.add(MyService, EContainerScope.Transient);get<T>(target: Constructor | string): T
Resolves an instance from the container.
Parameters:
target- Class constructor or alias string
Returns: The resolved instance
Throws: ContainerException if resolution fails
Example:
const service = container.get(MyService);
const aliased = container.get<MyService>('myService');has(target: Constructor | string): boolean
Checks if a service is registered.
Parameters:
target- Class constructor or alias string
Returns: true if registered, false otherwise
Example:
if (container.has(MyService)) {
const service = container.get(MyService);
}remove(target: Constructor | string): void
Removes a registered service.
Parameters:
target- Class constructor or alias string
Example:
container.remove(MyService);addConstant<T>(identifier: string | symbol, value: T): void
Registers a constant value.
Parameters:
identifier- String or symbol identifiervalue- The constant value
Example:
container.addConstant('api.url', 'https://api.example.com');getConstant<T>(identifier: string | symbol): T
Retrieves a constant value.
Parameters:
identifier- String or symbol identifier
Returns: The constant value
Throws: ContainerException if not found
Example:
const apiUrl = container.getConstant<string>('api.url');hasConstant(identifier: string | symbol): boolean
Checks if a constant is registered.
Parameters:
identifier- String or symbol identifier
Returns: true if registered, false otherwise
removeConstant(identifier: string | symbol): void
Removes a registered constant.
Parameters:
identifier- String or symbol identifier
addAlias<T>(alias: string, target: Constructor): void
Creates an alias for a registered service.
Parameters:
alias- String alias nametarget- The target class constructor
Example:
container.add(EmailService);
container.addAlias('mailer', EmailService);Enums
EContainerScope
| Value | Description |
|---|---|
Singleton |
Single instance shared across all requests |
Transient |
New instance created on every resolution |
Request |
New instance per request context |
Exported Functions
injectable()
Decorator to mark a class as injectable (re-exported from Inversify).
inject()
Decorator to inject dependencies (re-exported from Inversify).
Global Instance
import { container } from '@ooneex/container';A pre-configured global container instance is exported for convenience.
Advanced Usage
Custom Container Instance
import { Container } from '@ooneex/container';
const myContainer = new Container();
myContainer.add(MyService);Service Factory Pattern
import { container, injectable } from '@ooneex/container';
@injectable()
class ConfigService {
private readonly config: Record<string, unknown> = {};
public set(key: string, value: unknown): void {
this.config[key] = value;
}
public get<T>(key: string): T {
return this.config[key] as T;
}
}
container.add(ConfigService);
const config = container.get(ConfigService);
config.set('database.host', 'localhost');Error Handling
import { container, ContainerException } from '@ooneex/container';
try {
const service = container.get(UnregisteredService);
} catch (error) {
if (error instanceof ContainerException) {
console.error('Service not found:', error.message);
}
}Integration with Ooneex Framework
import { container } from '@ooneex/container';
import { decorator } from '@ooneex/service';
@decorator.service()
class PaymentService {
public processPayment(amount: number) {
// Payment logic
}
}
// Service is automatically registered by the decorator
const paymentService = container.get(PaymentService);License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development Setup
- Clone the repository
- Install dependencies:
bun install - Run tests:
bun run test - Build the project:
bun run build
Guidelines
- Write tests for new features
- Follow the existing code style
- Update documentation for API changes
- Ensure all tests pass before submitting PR
Made with ❤️ by the Ooneex team