register method
Register a module with full lifecycle management
Lifecycle:
- Check dependencies
- Call onBind(AirDI)
- Call onInit(AirDI)
- Add to registered modules
Implementation
Future<void> register(AppModule module) async {
if (_modules.any((m) => m.id == module.id)) {
debugPrint('ModuleManager: Module ${module.id} already registered');
return;
}
// Check required dependencies (with version if specified)
for (final depSpec in module.dependencies) {
// Parse dependency specification (e.g., "auth:^1.0.0" or just "auth")
final parts = depSpec.split(':');
final depId = parts[0];
final versionReq = parts.length > 1 ? parts[1] : null;
final depModule = _modules.where((m) => m.id == depId).firstOrNull;
if (depModule == null) {
throw StateError(
'ModuleManager: Module "${module.id}" requires "$depId" '
'but it is not registered. Register dependencies first.',
);
}
// Verify version compatibility if version requirement is specified
if (versionReq != null) {
if (!_checkVersionCompatibility(depModule.version, versionReq)) {
debugPrint(
'\x1B[33m[ModuleManager] Warning: Module "${module.id}" requires "$depId" '
'version $versionReq, but ${depModule.version} is installed.\x1B[0m',
);
}
}
}
// Log optional dependencies that are missing
for (final depSpec in module.optionalDependencies) {
final parts = depSpec.split(':');
final depId = parts[0];
if (!_modules.any((m) => m.id == depId)) {
debugPrint(
'\x1B[33m[ModuleManager] Info: Optional dependency "$depId" for "${module.id}" '
'is not available.\x1B[0m',
);
}
}
// Create context for the module
final context = ModuleContext(moduleId: module.id, moduleName: module.name);
try {
// Get DI instance
final di = AirDI();
// Register dependencies before initialization
module.onBind(di);
// Self-initialization without main.dart knowing details
await module.onInit(di);
// Only add to modules list AFTER successful initialization
_modules.add(module);
_contexts[module.id] = context;
// Emit module installed event
EventBus().emit(
ModuleInstalledEvent(
sourceModuleId: 'system',
installedModuleId: module.id,
installedModuleName: module.name,
version: module.version,
),
);
debugPrint('ModuleManager: Module ${module.id} registered successfully');
notifyListeners();
} catch (e, st) {
module.onError(e, st);
debugPrint('ModuleManager: Failed to initialize module ${module.id}: $e');
rethrow;
}
}