registerModules static method

Future<void> registerModules(
  1. List<ZenModule> modules,
  2. ZenScope scope
)

Register and load modules with dependency resolution

Validates upfront, then loads in correct order. Throws immediately on any error - no complex rollback.

Implementation

static Future<void> registerModules(
  List<ZenModule> modules,
  ZenScope scope,
) async {
  if (modules.isEmpty) return;

  // 1. Collect all dependencies
  final allModules = _collectAllDependencies(modules);

  // 2. Validate - throws if circular dependencies
  _validateDependencyGraph(allModules);

  // 3. Check all module dependencies are available
  for (final module in allModules) {
    for (final dep in module.dependencies) {
      if (!_modules.containsKey(dep.name) &&
          !allModules.any((m) => m.name == dep.name)) {
        throw StateError(
            'Missing dependency: "${dep.name}" required by "${module.name}"');
      }
    }
  }

  // 4. Calculate load order
  final loadOrder = _calculateLoadOrder(allModules);

  ZenLogger.logInfo(
      'Loading ${loadOrder.length} modules: ${loadOrder.map((m) => m.name).join(' → ')}');

  // 5. Load modules in dependency order
  for (final module in loadOrder) {
    // Skip if already loaded
    if (_modules.containsKey(module.name)) {
      ZenLogger.logDebug('⏭️  Skipped (already loaded): ${module.name}');
      continue;
    }

    // Register dependencies
    module.register(scope);

    // Initialize
    await module.onInit(scope);

    // Mark as loaded
    _modules[module.name] = module;

    ZenLogger.logInfo('✅ Loaded: ${module.name}');
  }

  ZenLogger.logInfo('✅ All ${loadOrder.length} modules loaded successfully');
}