build method

List<IModuleCodeContributor> build(
  1. List<IModuleContributorFactory> rootFactories,
  2. ModuleProfile profile, {
  3. required StrictMode strictMode,
  4. Logger? logger,
})

Builds module instances using rootFactories and profile.

  • Adds core factories (flutter_core, contracts) implicitly via coreModuleKeys.
  • In strict mode throws when a module or its dependency is unsupported or missing in the registry. In lenient mode logs a warning and skips.

Implementation

List<IModuleCodeContributor> build(
  List<IModuleContributorFactory> rootFactories,
  ModuleProfile profile, {
  required StrictMode strictMode,
  Logger? logger,
}) {
  final allRequestedFactories = <IModuleContributorFactory>[
    ...coreModuleKeys
        .map((key) => registry[key])
        .whereType<IModuleContributorFactory>(),
    ...rootFactories,
  ];

  final moduleNameToInstance = <String, IModuleCodeContributor>{};
  final processedModuleNames = <String>{};

  IModuleCodeContributor? tryCreateModuleInstance(
    IModuleContributorFactory factory,
  ) {
    if (!factory.supports(profile)) {
      final message = 'Module factory ${factory.runtimeType} '
          'does not support profile: $profile';
      if (strictMode == StrictMode.strict) {
        logger?.err('❌ $message');
        throw StateError(message);
      } else {
        logger?.warn('⚠️ $message. Skipping.');
        return null;
      }
    }

    return factory.create(profile);
  }

  void addModuleAndDependencies(IModuleCodeContributor module) {
    final moduleName = module.moduleDescriptor.name;
    if (processedModuleNames.contains(moduleName)) return;
    processedModuleNames.add(moduleName);

    for (final dependencyName in module.moduleDescriptor.dependsOn) {
      final dependencyFactory = registry[dependencyName];
      if (dependencyFactory == null) {
        final message = 'Unknown dependency: $dependencyName for $moduleName';
        if (strictMode == StrictMode.strict) {
          logger?.err('❌ $message');
          throw StateError(message);
        } else {
          logger?.warn('⚠️ $message. Skipping $moduleName');
          return; // skip this module in lenient mode
        }
      }

      final alreadyPresent = moduleNameToInstance.containsKey(dependencyName);
      final dependencyInstance = moduleNameToInstance[dependencyName] ??
          tryCreateModuleInstance(dependencyFactory);
      if (dependencyInstance == null) {
        // Unsupported dependency in lenient mode → skip current module
        logger?.warn(
          '⚠️ Dependency $dependencyName not available for $moduleName. '
          'Skipping $moduleName',
        );

        return;
      }

      moduleNameToInstance[dependencyName] = dependencyInstance;
      if (!alreadyPresent) {
        logger?.detail(
          '🔗 Resolved transitive dependency: '
          '$dependencyName (required by $moduleName)',
        );
      }
      addModuleAndDependencies(dependencyInstance);
    }

    moduleNameToInstance[moduleName] = module;
  }

  for (final factory in allRequestedFactories) {
    final instance = tryCreateModuleInstance(factory);
    if (instance == null) continue;
    addModuleAndDependencies(instance);
  }

  // Resolve final order using provided resolver
  final built = moduleNameToInstance.values.toList();
  return resolver.resolve(built);
}