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. Dependency resolution is complete:
  //    _collectAllDependencies() already recursively collected every
  //    transitive dependency declared by each module. If a module object
  //    is reachable from the root list, all its sub-dependencies are too.
  //    No additional "missing dependency" check is needed here.

  // 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');
}