The Flow Core Container is designed as a layered architecture with clear separation of concerns and well-defined boundaries between abstraction levels.
- Interfaces Only: Core package provides pure TypeScript interfaces
- No Implementation Lock-in: Works with any DI container framework
- Maximum Flexibility: Consumers can implement interfaces as needed
- Foundation Layer: Basic building blocks and utilities
- Core Layer: Primary DI/IoC contracts
- Advanced Layer: Composite and specialized interfaces
- Implementation Layer: Optional production-ready helpers
- Pure TypeScript: No external runtime dependencies
- Minimal Footprint: Interface-only design for core abstractions
- Optional Helpers: Production utilities without external deps
- Generic Support: Full TypeScript generics throughout
- Type Helpers: Utility types for enhanced developer experience
- Strict Mode: Compatible with exactOptionalPropertyTypes
Purpose: Provides basic building blocks used throughout the system
Components:
IFlowDisposable- Standard resource disposal patternIFlowAsyncDisposable- Modern async disposal with Symbol.asyncDisposeIFlowServiceMetadata- Service registration metadataIFlowServiceLifecycle- Lifecycle hook definitionsFlowServiceFactory<T>- Service factory function typeServiceToken<T>- Type-safe service identification
Responsibilities:
- Define common patterns used across all layers
- Provide type-safe primitives for service identification
- Enable proper resource management and cleanup
Purpose: Defines primary contracts for dependency injection and service management
Components:
IFlowContainer- Main DI container interfaceIFlowServiceProvider<T>- Lazy service resolutionIFlowServiceLocator- Service locator patternIFlowServiceRegistry- Registration management
Relationships:
IFlowContaineroptionally implementsIFlowDisposable- All core interfaces use Foundation Layer primitives
- Independent interfaces that can be implemented separately
Responsibilities:
- Service registration and resolution
- Container lifecycle management
- Lazy loading and service location patterns
- Registration metadata management
Purpose: Provides composite interfaces that combine multiple core capabilities
Components:
IFlowAdvancedContainer- Combines container + registry + resolverIFlowServiceResolver- Advanced resolution with circular dependency detection
Relationships:
IFlowAdvancedContainer extends IFlowContainer, IFlowServiceResolver, IFlowServiceRegistry- Composites multiple Core Layer interfaces
Responsibilities:
- Full-featured container implementations
- Circular dependency detection and resolution
- Advanced resolution patterns (fallback, pattern matching)
- Container hierarchy and event management
Purpose: Provides production-ready implementations of core interfaces
Components:
SimpleContainer- CompleteIFlowContainerimplementationContainerBuilder- Fluent API for container configurationServiceTokens- Token creation and management utilities- Type helpers and utility functions
Relationships:
SimpleContainer implements IFlowContainerContainerBuilder implements IFlowContainerBuilder- Uses Core and Foundation layer interfaces
Responsibilities:
- Production-ready implementations without external dependencies
- Extensible base classes with protected hook methods
- Type-safe token creation and management
- Fluent configuration APIs
IFlowDisposable
βββ IFlowContainer (optional)
βββ IFlowServiceLifecycle (optional)
IFlowAdvancedContainer
βββ extends IFlowContainer
βββ extends IFlowServiceResolver
βββ extends IFlowServiceRegistry
IFlowContainerBuilder
βββ creates IFlowContainer
IFlowContainerModule
βββ configures IFlowContainerBuilder
- Advanced Container: Composes multiple core interfaces for full functionality
- Container Builder: Uses modules and configuration to create containers
- Service Provider: Uses tokens for type-safe service identification
- Injectable Services: Self-describing services with dependency metadata
- Service Locator: Alternative to constructor injection
- Lazy Resolution: Deferred service creation until needed
Decision: Separate concerns into focused, single-purpose interfaces Rationale:
- Follows SOLID principles
- Allows partial implementations
- Reduces coupling between components
- Enables testing of individual concerns
Decision: Core interfaces optionally extend utility interfaces Rationale:
IFlowContaineroptionally implementsIFlowDisposable- Allows implementations to choose cleanup strategies
- Maintains interface focus while enabling resource management
Decision: Extensive use of TypeScript generics for type safety Rationale:
- Provides compile-time type checking
- Enables IntelliSense and auto-completion
- Reduces runtime errors through type safety
Decision: Provide optional, extensible implementations Rationale:
- Production-ready code without external dependencies
- Extensible through protected methods and inheritance
- Zero lock-in - pure interfaces remain separate
Implement IFlowContainer with custom resolution logic:
class MyContainer implements IFlowContainer {
// Custom implementation
}Extend provided helpers for specialized behavior:
class CustomContainer extends SimpleContainer {
protected beforeResolve<T>(token: string | symbol): void {
// Custom logic before resolution
}
}Create reusable configuration modules:
class DatabaseModule implements IFlowContainerModule {
configure(builder: IFlowContainerBuilder): void {
builder
.singleton('Database', async () => new PostgresDB())
.singleton('Repository', async (c) => new UserRepository(await c.resolve('Database')));
}
}The interfaces can wrap existing DI frameworks:
class InversifyContainerAdapter implements IFlowContainer {
constructor(private inversifyContainer: Container) {}
register<T>(token: string | symbol, factory: FlowServiceFactory<T>): void {
// Adapt to Inversify
}
}Advanced containers can manage multiple child containers:
class AdvancedContainer implements IFlowAdvancedContainer {
private children: IFlowContainer[] = [];
createScope(): IFlowContainer {
const child = new SimpleContainer(this);
this.children.push(child);
return child;
}
}Service resolution can be enhanced with middleware:
class MiddlewareContainer extends SimpleContainer {
protected async resolveService<T>(token: string | symbol): Promise<T> {
// Pre-resolution middleware
const result = await super.resolveService<T>(token);
// Post-resolution middleware
return result;
}
}- Interface Stability: Core interfaces rarely change
- Backward Compatibility: Semantic versioning ensures safe updates
- Clear Boundaries: Layer separation enables independent evolution
- Interface Contracts: Easy to mock and test individual concerns
- Helper Implementations: Comprehensive test coverage for production code
- Isolated Testing: Minimal dependencies enable focused unit tests
- Interface Overhead: Zero runtime cost for pure interfaces
- Optional Helpers: Production implementations optimized for performance
- Lazy Loading: Service provider pattern enables on-demand resolution
- Open/Closed Principle: Extend behavior without modifying core interfaces
- Plugin Architecture: Module system enables composable functionality
- Hook Points: Protected methods in helpers enable customization
This architecture documentation provides a comprehensive understanding of how the Flow Core Container is structured and how its components interact to provide a flexible, type-safe dependency injection foundation.