everyModuleAppsOf function

Future<({List<MatrixApp> apps, List<ContractResult> failed})> everyModuleAppsOf(
  1. List<SmfModule> modules, {
  2. Map<String, String?> roleOptions = const {},
  3. bool withoutExternalSteps = false,
})

The apps with every module of modules: those that the contract harness builds for each combination of the providers of the roles that take one, each with as many modules as one app can have (see ContractHarness.casesOfAll), with their MatrixApp.everyModuleWith. The apps and the options of their roles are those of matrixOf.

With withoutExternalSteps, they are the apps with every module that needs nothing outside the app: without the modules whose steps after generation need an external service, such as a network account (PostGenStep.external), which a run that skips external setup leaves for later, so that the app is complete once it is generated, and it starts. The modules that depend on them, directly or not, and those that are then left without a provider of a role they require, stay out too, and each of the other roles gets one app for each of its providers that are left.

Implementation

Future<({List<MatrixApp> apps, List<ContractResult> failed})> everyModuleAppsOf(
  List<SmfModule> modules, {
  Map<String, String?> roleOptions = const {},
  bool withoutExternalSteps = false,
}) async {
  // The providers of each role in the order of all modules, which the
  // everyModuleWith of each app is relative to.
  final names = ModuleRegistry(modules);
  var registry = names;
  while (true) {
    final (:apps, :failed, :external) = await _everyModuleOf(
      ContractHarness(registry, roleOptions: roleOptions),
      names,
      withoutExternalSteps: withoutExternalSteps,
    );
    if (external.isEmpty) return (apps: apps, failed: failed);
    registry = ModuleRegistry(_without(registry.modules, external));
  }
}