Compare commits

...

8 Commits

15 changed files with 285 additions and 20 deletions

View File

@ -15,4 +15,22 @@
- Add mutable configuration provider
- Split tests file
- Fixed and nullable functions
- Able to set or remove config from system config
- Able to set or remove config from system config
## 1.0.4
- Fixed format classes and files
## 1.0.5
- Fixed simple provider for final configs variable
- 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
- Add TextFormatter for format the string with args
## 1.0.7
- Removed example "example_flutter_secure_storage_provider.dart"
## 1.0.8
- Fixed Text Formatter on dynamic to string

View File

@ -1,11 +1,20 @@
# Dart Configurable Environment
[![Pub](https://img.shields.io/pub/v/configurable.svg)](https://pub.dartlang.org/packages/configurable)
- [x] Allow to get property from env file
- [x] Cache property for runtime
- [x] Dotenv file support (use DotenvConfigurationProvider)
- [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 (because of runtime in device)
# Resolution
- Flutter app can be use persistence storage like SharedPreference or FlutterSecureStorage to implement the configuration provider
# Example

View File

@ -0,0 +1,14 @@
import 'package:configurable/text_formatter.dart';
void main(List<String> args) {
var text1 = 'Hello, {0}, then do this it by {1}!';
var text2 = 'Hello, {firstName}, then do this it by {lastName}!';
var result1 = TextFormatter(text1).format(['Sambo', 'Chea']);
var result2 = TextFormatter(text2).decorate({
'firstName': 'Sambo',
'lastName': 'Chea',
});
print('Result 1 => $result1');
print('Result 2 => $result2');
}

View File

@ -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<String?> 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<bool> 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<void> 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<void> removeConfigAsync(String key) async =>
await SystemConfig.removeAsync(key);

View File

@ -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<bool> containsKeyAsync(String key) async {
return Future.value(containsKey(key));
}
/// get or null for async function
Future<String?> getOrNullAsync(String key, {String? defaultValue}) async {
return Future.value(getOrNull(key, defaultValue: defaultValue));
}
}

View File

@ -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();

View File

@ -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<String, String?> configs);
void setAll(Map<String, String?> 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<void> setAsync(String key, String? value) async {
set(key, value);
}
/// Allow to set all values into config values in async function
Future<void> setAllAsync(Map<String, String?> configs) async {
configs.forEach((key, value) {
setAsync(key, value);
});
}
/// Allow to remove the key from config values in async function
Future<void> removeAsync(String key) async {
remove(key);
}
/// Allow to remove all values from config values in async function
Future<void> removeAllAsync() async {
removeAll();
}
}

View File

@ -4,16 +4,16 @@ import 'package:configurable/mutable_configurable_provider.dart';
///
/// @author sombochea
/// @since 1.0.0
class SimpleConfigurationProvider implements MutableConfigurationProvider {
Map<String, String?> configs = {};
class SimpleConfigurationProvider extends MutableConfigurationProvider {
final Map<String, String?> _configs = {};
@override
String? getOrNull(String key, {String? defaultValue}) {
var value = configs[key];
var value = _configs[key];
/// if value is null, then set the default value and return it back
if (value == null) {
configs[key] = defaultValue;
_configs[key] = defaultValue;
return defaultValue;
}
@ -22,26 +22,26 @@ class SimpleConfigurationProvider implements MutableConfigurationProvider {
@override
bool containsKey(String key) {
return configs.containsKey(key);
return _configs.containsKey(key);
}
@override
void set(String key, String? value) {
configs[key] = value;
_configs[key] = value;
}
@override
void remove(String key) {
configs.remove(key);
_configs.remove(key);
}
@override
void removeAll() {
configs.clear();
_configs.clear();
}
@override
void setAll(Map<String, String?> configs) {
configs.addAll(configs);
_configs.addAll(configs);
}
}

View File

@ -30,8 +30,15 @@ class SystemConfig {
return getProvider().getOrNull(key, defaultValue: defaultValue);
}
static Future<String?> getOrNullAsync(String key, {String? defaultValue}) {
return getProvider().getOrNullAsync(key, defaultValue: defaultValue);
}
static bool containsKey(String key) => getProvider().containsKey(key);
static Future<bool> 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<void> setAsync(String key, String? value) async {
await _getMutableConfigurationProvider().setAsync(key, value);
}
static void setAll(Map<String, String?> values) {
_getMutableConfigurationProvider().setAll(values);
}
static Future<void> setAllAsync(Map<String, String?> values) async {
await _getMutableConfigurationProvider().setAllAsync(values);
}
static void remove(String key) {
_getMutableConfigurationProvider().remove(key);
}
static Future<void> removeAsync(String key) async {
await _getMutableConfigurationProvider().removeAsync(key);
}
static void removeAll() {
_getMutableConfigurationProvider().removeAll();
}
static Future<void> removeAllAsync() async {
await _getMutableConfigurationProvider().removeAllAsync();
}
}

51
lib/text_formatter.dart Normal file
View File

@ -0,0 +1,51 @@
class TextFormatter {
String? text;
TextFormatter(String? text) {
this.text = text;
}
String? format(List<dynamic> args) {
if (text == null) {
return null;
}
if (args.isEmpty) {
return text;
}
var msg = text;
args.asMap().forEach((index, element) {
var _replaced = '';
if (element != null) {
_replaced = element.toString();
}
msg = msg?.replaceAll('{$index}', _replaced);
});
return msg;
}
String? decorate(Map<String, dynamic> params) {
if (text == null) {
return null;
}
if (params.isEmpty) {
return text;
}
var msg = text;
params.forEach((index, element) {
var _replaced = '';
if (element != null) {
_replaced = element.toString();
}
msg = msg?.replaceAll('{$index}', _replaced);
});
return msg;
}
}

View File

@ -1,6 +1,6 @@
name: configurable
description: System Configuration and Dotenv Environment for Dart and Flutter
version: 1.0.3
description: System Configuration, Dotenv Environment and Text Formatter for Dart and Flutter
version: 1.0.8
homepage: https://github.com/CUBETIQ/system-config-dart
repository: https://github.com/CUBETIQ/system-config-dart.git

View File

@ -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)));
});
}

View File

@ -1,4 +1,5 @@
import 'package:configurable/configurable.dart' show getConfigOrNull, hasConfigkey;
import 'package:configurable/configurable.dart'
show getConfigOrNull, hasConfigkey;
import 'package:configurable/simple_configuration_provider.dart';
import 'package:configurable/system_config.dart';
import 'package:test/test.dart';
@ -7,7 +8,7 @@ void main() {
test('get system config by key', () {
var key = 'app.name';
var value = 'CUBETIQ';
// set simple provider
SystemConfig.setProvider(SimpleConfigurationProvider());

View File

@ -4,7 +4,7 @@ import 'package:test/test.dart';
void main() {
test('just call env', () {
load();
var result = env['app.title'];
expect('CUBETIQ Solution', equals(result));

View File

@ -0,0 +1,15 @@
import 'package:configurable/text_formatter.dart';
import 'package:test/test.dart';
void main() {
test('text formatter function format', () {
var text1 = 'Hello, {0}!';
var result1 = TextFormatter(text1).format(['Sambo']);
var text2 = 'Hello, {name}!';
var result2 = TextFormatter(text2).decorate({'name': 'Chea'});
expect('Hello, Sambo!', result1);
expect('Hello, Chea!', result2);
});
}