load static method
Loads the flavor configuration from the YAML file.
If excludeValidation is true, the config is loaded without full validation.
Implementation
static FlavorConfig load([bool excludeValidation = false]) {
// Check for legacy JSON first for seamless loading before migration
final legacyFile = File(p.join(root, '.flavor_cli.json'));
if (legacyFile.existsSync() && !File(_configPath).existsSync()) {
try {
final content = legacyFile.readAsStringSync();
final jsonMap = jsonDecode(content) as Map<String, dynamic>;
if (jsonMap['platforms'] == null) {
jsonMap['platforms'] = detectPlatforms();
}
if (excludeValidation) return FlavorConfig.fromJson(jsonMap);
return ConfigValidator.validate(jsonMap);
} catch (e) {
// Fallthrough to yaml error
}
}
final file = File(_configPath);
if (!file.existsSync()) {
throw Exception(
'❌ flavor_cli: flavor_cli.yaml not found. Run init first.',
);
}
try {
final content = file.readAsStringSync();
final yamlMap = loadYaml(content);
final jsonMap = YamlUtils.yamlToMap(yamlMap);
if (jsonMap['platforms'] == null) {
jsonMap['platforms'] = detectPlatforms();
}
if (excludeValidation) {
return FlavorConfig.fromJson(jsonMap);
}
// Will throw FormatException with properly formatted error if invalid
try {
return ConfigValidator.validate(jsonMap);
} on FormatException catch (e) {
var repaired = false;
var config = FlavorConfig.fromJson(jsonMap);
// Self-healing: If flavor_app_names contains keys not defined in flavors
if (e.message.contains('flavor_app_names') &&
!e.message.contains('application_id') &&
!e.message.contains('bundle_id') &&
config.flavorAppNames != null) {
final flavorsSet = config.flavors.toSet();
final validAppNames = Map<String, String>.from(config.flavorAppNames!)
..removeWhere((key, _) => !flavorsSet.contains(key));
config = config.copyWith(flavorAppNames: validAppNames);
repaired = true;
}
// Self-healing: If the production_flavor is not in flavors
if (e.message.contains('production_flavor') &&
!e.message.contains('application_id') &&
!e.message.contains('bundle_id') &&
config.flavors.isNotEmpty &&
!config.flavors.contains(config.productionFlavor)) {
config = config.copyWith(
productionFlavor: config.flavors.first,
);
repaired = true;
}
if (repaired) {
try {
// Re-validate to ensure it's fully correct now
final validated = ConfigValidator.validate(config.toJson());
save(validated);
return validated;
} catch (_) {
// Fall through and rethrow original if repair was insufficient
}
}
rethrow;
}
} on FormatException {
rethrow;
} catch (e) {
throw FormatException('❌ flavor_cli: invalid config YAML format.\n$e');
}
}