From a4264bb5e2ac65100eba71128356b9a7bcdfa65b Mon Sep 17 00:00:00 2001 From: Sambo Chea Date: Fri, 14 May 2021 15:52:57 +0700 Subject: [PATCH] Task: Add async support and functions for configurable and add tests for async testing and updated the functions with default --- CHANGELOG.md | 6 +- README.md | 6 +- ...ample_flutter_secure_storage_provider.dart | 90 +++++++++++++++++++ lib/configurable.dart | 22 ++++- lib/configuration_provider.dart | 10 +++ lib/dotenv_configuration_provider.dart | 2 +- lib/mutable_configurable_provider.dart | 30 ++++++- lib/simple_configuration_provider.dart | 2 +- lib/system_config.dart | 31 +++++++ pubspec.yaml | 2 +- test/config_async_test.dart | 70 +++++++++++++++ 11 files changed, 263 insertions(+), 8 deletions(-) create mode 100644 example/example_flutter_secure_storage_provider.dart create mode 100644 test/config_async_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 819bdc5..16e3145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,4 +22,8 @@ ## 1.0.5 - Fixed simple provider for final configs variable -- Fixed setAll function that set itself, in simple provider \ No newline at end of file +- Fixed setAll function that set itself, in simple provider + +## 1.0.6 +- Add async function support +- Add functions for set and remove for system config and file functions \ No newline at end of file diff --git a/README.md b/README.md index d75eb12..d8844a5 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,13 @@ - [x] Support functions (getConfig, getConfigOrNull, hasConfigKey, setConfig) - [x] Support nullsafety (dart 2.12.2+) - [x] Custom configuration provider +- [x] Add Async functions support # Issue -- Flutter app not support for dotenv (.env) when run on devices +- Flutter app not support for dotenv (.env) when run on devices (because of runtime in device) + +# Resolution +- Flutter app can be use persistence storage like SharedPreference or FlutterSecureStorage to implement the configuration provider # Example diff --git a/example/example_flutter_secure_storage_provider.dart b/example/example_flutter_secure_storage_provider.dart new file mode 100644 index 0000000..8393952 --- /dev/null +++ b/example/example_flutter_secure_storage_provider.dart @@ -0,0 +1,90 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:configurable/mutable_configurable_provider.dart'; + +class LocalStorageProvider + extends MutableConfigurationProvider { + static FlutterSecureStorage _storage; + + FlutterSecureStorage _getStorage() { + if (_storage == null) { + _storage = new FlutterSecureStorage(); + } + + return _storage; + } + + @override + bool containsKey(String key) { + var _hasKey = false; + _getStorage().containsKey(key: key).then((value) => _hasKey = value); + + return _hasKey; + } + + @override + Future containsKeyAsync(String key) async { + return await _getStorage().containsKey(key: key); + } + + @override + String? getOrNull(String key, {String defaultValue}) { + String _value; + _getStorage().read(key: key).then((value) => { + _value = value + }); + + if (_value == null && defaultValue != null) { + return defaultValue; + } else { + return _value; + } + } + + @override + Future getOrNullAsync(String key, {String defaultValue}) async { + String _value = await _getStorage().read(key: key); + + if (_value == null && defaultValue != null) { + return defaultValue; + } else { + return _value; + } + } + + @override + void remove(String key) { + _getStorage().delete(key: key); + } + + @override + Future removeAsync(String key) async { + await _getStorage().delete(key: key); + } + + @override + void removeAll() { + _getStorage().deleteAll(); + } + + @override + Future removeAllAsync() async { + await _getStorage().deleteAll(); + } + + @override + void set(String key, String value) { + _getStorage().write(key: key, value: value); + } + + @override + Future setAsync(String key, String value) async { + await _getStorage().write(key: key, value: value); + } + + @override + Future setAllAsync(Map configs) async { + configs.entries.forEach((element) { + setAsync(element.key, element.value); + }); + } +} diff --git a/lib/configurable.dart b/lib/configurable.dart index fece0d8..77400ad 100644 --- a/lib/configurable.dart +++ b/lib/configurable.dart @@ -6,6 +6,11 @@ import 'package:configurable/system_config.dart'; String? getConfigOrNull(String key, {String? defaultValue}) => SystemConfig.getOrNull(key, defaultValue: defaultValue); +/// get config or null from system config in async +Future getConfigOrNullAsync(String key, + {String? defaultValue}) async => + await SystemConfig.getOrNullAsync(key, defaultValue: defaultValue); + /// get config with non-null from system config String getConfig(String key, {String? defaultValue}) => SystemConfig.get(key, defaultValue: defaultValue); @@ -13,5 +18,20 @@ String getConfig(String key, {String? defaultValue}) => /// check has config key or not from system config bool hasConfigkey(String key) => SystemConfig.containsKey(key); -/// set config into memory +/// check has config key or not from system config in async function +Future hasConfigkeyAsync(String key) async => + await SystemConfig.containsKeyAsync(key); + +/// set config into memory or custom provider void setConfig(String key, String? value) => SystemConfig.set(key, value); + +/// set config into memory or custom provider in async function +Future setConfigAsync(String key, String? value) async => + await SystemConfig.setAsync(key, value); + +/// remove config into memory or custom provider +void removeConfig(String key) => SystemConfig.remove(key); + +/// remove config into memory or custom provider in async function +Future removeConfigAsync(String key) async => + await SystemConfig.removeAsync(key); diff --git a/lib/configuration_provider.dart b/lib/configuration_provider.dart index 8b3883f..308df7c 100644 --- a/lib/configuration_provider.dart +++ b/lib/configuration_provider.dart @@ -8,4 +8,14 @@ abstract class ConfigurationProvider { /// get or null in implemented classes String? getOrNull(String key, {String? defaultValue}); + + /// check has key or not for async function + Future containsKeyAsync(String key) async { + return Future.value(containsKey(key)); + } + + /// get or null for async function + Future getOrNullAsync(String key, {String? defaultValue}) async { + return Future.value(getOrNull(key, defaultValue: defaultValue)); + } } diff --git a/lib/dotenv_configuration_provider.dart b/lib/dotenv_configuration_provider.dart index 47a892d..429b4fc 100644 --- a/lib/dotenv_configuration_provider.dart +++ b/lib/dotenv_configuration_provider.dart @@ -5,7 +5,7 @@ import 'package:configurable/dotenv/dotenv.dart' show env, load; /// /// @author sombochea /// @since 1.0.0 -class DotenvConfigurationProvider implements ConfigurationProvider { +class DotenvConfigurationProvider extends ConfigurationProvider { /// default constructor to load the platform environment DotenvConfigurationProvider() { load(); diff --git a/lib/mutable_configurable_provider.dart b/lib/mutable_configurable_provider.dart index 84f8008..a2b4c69 100644 --- a/lib/mutable_configurable_provider.dart +++ b/lib/mutable_configurable_provider.dart @@ -4,16 +4,42 @@ import 'package:configurable/configuration_provider.dart'; /// /// @author sombochea /// @since 1.0.3 -abstract class MutableConfigurationProvider implements ConfigurationProvider { +abstract class MutableConfigurationProvider extends ConfigurationProvider { /// Allow to set the value into config values void set(String key, String? value); /// Allow to set all values into config values - void setAll(Map configs); + void setAll(Map configs) { + configs.forEach((key, value) { + set(key, value); + }); + } /// Allow to remove the key from config values void remove(String key); /// Allow to remove all values from config values void removeAll(); + + /// Allow to set the value into config values in async function + Future setAsync(String key, String? value) async { + set(key, value); + } + + /// Allow to set all values into config values in async function + Future setAllAsync(Map configs) async { + configs.forEach((key, value) { + setAsync(key, value); + }); + } + + /// Allow to remove the key from config values in async function + Future removeAsync(String key) async { + remove(key); + } + + /// Allow to remove all values from config values in async function + Future removeAllAsync() async { + removeAll(); + } } diff --git a/lib/simple_configuration_provider.dart b/lib/simple_configuration_provider.dart index ece2346..46114c0 100644 --- a/lib/simple_configuration_provider.dart +++ b/lib/simple_configuration_provider.dart @@ -4,7 +4,7 @@ import 'package:configurable/mutable_configurable_provider.dart'; /// /// @author sombochea /// @since 1.0.0 -class SimpleConfigurationProvider implements MutableConfigurationProvider { +class SimpleConfigurationProvider extends MutableConfigurationProvider { final Map _configs = {}; @override diff --git a/lib/system_config.dart b/lib/system_config.dart index 0d7a934..01f24e3 100644 --- a/lib/system_config.dart +++ b/lib/system_config.dart @@ -30,8 +30,15 @@ class SystemConfig { return getProvider().getOrNull(key, defaultValue: defaultValue); } + static Future getOrNullAsync(String key, {String? defaultValue}) { + return getProvider().getOrNullAsync(key, defaultValue: defaultValue); + } + static bool containsKey(String key) => getProvider().containsKey(key); + static Future containsKeyAsync(String key) => + getProvider().containsKeyAsync(key); + /// Convert to mutable configuration provider static MutableConfigurationProvider _getMutableConfigurationProvider() { if (_provider is MutableConfigurationProvider) { @@ -46,7 +53,31 @@ class SystemConfig { _getMutableConfigurationProvider().set(key, value); } + static Future setAsync(String key, String? value) async { + await _getMutableConfigurationProvider().setAsync(key, value); + } + static void setAll(Map values) { _getMutableConfigurationProvider().setAll(values); } + + static Future setAllAsync(Map values) async { + await _getMutableConfigurationProvider().setAllAsync(values); + } + + static void remove(String key) { + _getMutableConfigurationProvider().remove(key); + } + + static Future removeAsync(String key) async { + await _getMutableConfigurationProvider().removeAsync(key); + } + + static void removeAll() { + _getMutableConfigurationProvider().removeAll(); + } + + static Future removeAllAsync() async { + await _getMutableConfigurationProvider().removeAllAsync(); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 0279224..b124cd6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: configurable description: System Configuration and Dotenv Environment for Dart and Flutter -version: 1.0.5 +version: 1.0.6 homepage: https://github.com/CUBETIQ/system-config-dart repository: https://github.com/CUBETIQ/system-config-dart.git diff --git a/test/config_async_test.dart b/test/config_async_test.dart new file mode 100644 index 0000000..5120eb5 --- /dev/null +++ b/test/config_async_test.dart @@ -0,0 +1,70 @@ +import 'package:configurable/configurable.dart' + show + getConfigOrNullAsync, + hasConfigkeyAsync, + setConfigAsync, + removeConfigAsync; +import 'package:configurable/simple_configuration_provider.dart'; +import 'package:configurable/system_config.dart'; +import 'package:test/test.dart'; + +void main() { + test('get system config by key', () async { + var key = 'app.name'; + var value = 'CUBETIQ'; + + // set simple provider + SystemConfig.setProvider(SimpleConfigurationProvider()); + + var result = await SystemConfig.getOrNullAsync(key, defaultValue: value); + + expect(value, equals(result)); + expect(value, equals(await SystemConfig.getOrNullAsync(key))); + }); + + test('get config by key with function', () async { + var key = 'app.name'; + var value = 'CUBETIQ Solution'; + + // set simple provider + SystemConfig.setProvider(SimpleConfigurationProvider()); + + var result = await getConfigOrNullAsync(key, defaultValue: value); + + expect(value, equals(result)); + expect(true, equals(await hasConfigkeyAsync(key))); + expect(value, equals(await getConfigOrNullAsync(key))); + }); + + test('set config by key and value with function', () async { + var key = 'app.name'; + var value = 'CUBETIQ Solution'; + + // set simple provider + SystemConfig.setProvider(SimpleConfigurationProvider()); + + await setConfigAsync(key, value); + + var result = await getConfigOrNullAsync(key); + + expect(value, equals(result)); + }); + + test('set and then remove config by key and value with function', () async { + var key = 'app.name'; + var value = 'CUBETIQ Solution'; + + // set simple provider + SystemConfig.setProvider(SimpleConfigurationProvider()); + + await setConfigAsync(key, value); + + var result = await getConfigOrNullAsync(key); + + expect(value, equals(result)); + + await removeConfigAsync(key); + + expect(null, equals(await getConfigOrNullAsync(key))); + }); +}