everyModuleAppsOf function
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));
}
}