diff --git a/packages/configuration/CHANGELOG.md b/packages/configuration/CHANGELOG.md index ccc00a11..517932aa 100644 --- a/packages/configuration/CHANGELOG.md +++ b/packages/configuration/CHANGELOG.md @@ -1,3 +1,8 @@ +# 2.2.0 +* Allow including one configuration within another. +* Badly-formatted `.env` files will no longer issue a warning, +but instead throw an exception. + # 2.1.0 * Add `loadStandaloneConfiguration`. diff --git a/packages/configuration/lib/angel_configuration.dart b/packages/configuration/lib/angel_configuration.dart index a2bec284..3255016e 100644 --- a/packages/configuration/lib/angel_configuration.dart +++ b/packages/configuration/lib/angel_configuration.dart @@ -21,8 +21,31 @@ Future _loadYamlFile(Map map, File yamlFile, Map env, var out = {}; - for (String key in config.keys) { - out[key] = _applyEnv(config[key], env ?? {}, warn); + var configMap = config as Map; + + // Check for _include + if (configMap.containsKey('_include')) { + var include = configMap.remove('_include'); + var includeList = include is Iterable ? include.toList() : [include]; + for (var inc in includeList) { + if (inc is! String) { + warn('Included item $inc is not a String.'); + } else { + var p = yamlFile.fileSystem.path; + var includeFilePath = p.join(yamlFile.parent.path, inc); + var includeFile = yamlFile.fileSystem.file(includeFilePath); + if (!await includeFile.exists()) { + warn( + 'Included configuration file "$includeFilePath" does not exist.'); + } else { + await _loadYamlFile(out, includeFile, env, warn); + } + } + } + } + + for (String key in configMap.keys) { + out[key] = _applyEnv(configMap[key], env ?? {}, warn); } map.addAll(mergeMap( @@ -107,35 +130,21 @@ AngelConfigurer configuration(FileSystem fileSystem, String overrideEnvironmentName, String envPath}) { return (Angel app) async { - var sourceDirectory = fileSystem.directory(directoryPath); - var env = dotenv.env; - var envFile = sourceDirectory.childFile(envPath ?? '.env'); - - if (await envFile.exists()) { - try { - dotenv.load(envFile.absolute.uri.toFilePath()); - } catch (_) { - app.logger?.warning( - 'WARNING: Found an environment configuration at ${envFile.absolute.path}, but it was invalidly formatted. Refusing to load it.'); - } - } - - var environmentName = env['ANGEL_ENV'] ?? 'development'; - - if (overrideEnvironmentName != null) { - environmentName = overrideEnvironmentName; - } - - void warn(String message) { - app.logger?.warning('WARNING: $message'); - } - - var defaultYaml = sourceDirectory.childFile('default.yaml'); - await _loadYamlFile(app.configuration, defaultYaml, env, warn); - - var configFilePath = '$environmentName.yaml'; - var configFile = sourceDirectory.childFile(configFilePath); - - await _loadYamlFile(app.configuration, configFile, env, warn); + var config = await loadStandaloneConfiguration( + fileSystem, + directoryPath: directoryPath, + overrideEnvironmentName: overrideEnvironmentName, + envPath: envPath, + onWarning: app.logger == null + ? null + : (msg) => app.logger?.warning('WARNING: $msg'), + ); + app.configuration.addAll(mergeMap( + [ + app.configuration, + config, + ], + acceptNull: true, + )); }; } diff --git a/packages/configuration/pubspec.yaml b/packages/configuration/pubspec.yaml index 972ea7db..224f0a07 100644 --- a/packages/configuration/pubspec.yaml +++ b/packages/configuration/pubspec.yaml @@ -13,5 +13,7 @@ dependencies: yaml: ^2.0.0 dev_dependencies: io: ^0.3.2 + logging: ^0.11.0 pedantic: ^1.0.0 + pretty_logging: ^1.0.0 test: ^1.0.0 diff --git a/packages/configuration/test/all_test.dart b/packages/configuration/test/all_test.dart index 2f547966..0a37635e 100644 --- a/packages/configuration/test/all_test.dart +++ b/packages/configuration/test/all_test.dart @@ -4,11 +4,15 @@ import 'package:angel_framework/angel_framework.dart'; import 'package:angel_configuration/angel_configuration.dart'; import 'package:file/local.dart'; import 'package:io/ansi.dart'; +import 'package:logging/logging.dart'; +import 'package:pretty_logging/pretty_logging.dart'; import 'package:test/test.dart'; Future main() async { + Logger.root.onRecord.listen(prettyLog); + // Note: Set ANGEL_ENV to 'development' - var app = Angel(); + var app = Angel(logger: Logger('angel_configuration')); var fileSystem = const LocalFileSystem(); await app.configure(configuration(