feat: add nested namespaces
This commit is contained in:
parent
f4ee1fe9e6
commit
1a5154d261
5 changed files with 178 additions and 62 deletions
36
README.md
36
README.md
|
@ -26,7 +26,9 @@ use std::env;
|
||||||
//use dotenv::dotenv;
|
//use dotenv::dotenv;
|
||||||
|
|
||||||
config! {
|
config! {
|
||||||
DEBUG: bool => true,
|
DEBUG: bool => false,
|
||||||
|
|
||||||
|
#[env_name = "APP_HOST"]
|
||||||
HOST: String => "127.0.0.1",
|
HOST: String => "127.0.0.1",
|
||||||
|
|
||||||
DATABASE_URL < (
|
DATABASE_URL < (
|
||||||
|
@ -40,26 +42,36 @@ config! {
|
||||||
POSTGRES_DB => "test",
|
POSTGRES_DB => "test",
|
||||||
),
|
),
|
||||||
|
|
||||||
NAMESPACE {
|
APP {
|
||||||
#[env_name = "MY_CUSTOM_NAME"]
|
ARTICLE {
|
||||||
FOO: bool,
|
PER_PAGE: u32 => 15,
|
||||||
|
}
|
||||||
|
|
||||||
BAR: i32 => 10,
|
#[cfg(feature = "companies")]
|
||||||
|
COMPANY {
|
||||||
|
#[env_name = "INSTITUTIONS_PER_PAGE"]
|
||||||
|
PER_PAGE: u32 => 15,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "feature")]
|
FEATURE {
|
||||||
#[env_name = "POSTGRES_CONNECTION_STRING"]
|
NEW_MENU: bool => false,
|
||||||
DATABASE_URL: String
|
|
||||||
|
COMPANY {
|
||||||
|
PROFILE: bool => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main () {
|
fn main () {
|
||||||
// dotenv().ok();
|
// dotenv().ok();
|
||||||
env::set_var("MY_CUSTOM_NAME", "t");
|
env::set_var("FEATURE_NEW_MENU", "t");
|
||||||
|
|
||||||
cfg::init();
|
cfg::init();
|
||||||
assert_eq!(cfg::HOST(), String::from("127.0.0.1"));
|
assert_eq!(cfg::HOST(), String::from("127.0.0.1"));
|
||||||
assert_eq!(cfg::DATABASE_URL(), String::from("postgres://user:pass@localhost:5432/test"));
|
assert_eq!(cfg::DATABASE_URL(), String::from("postgres://user:pass@localhost:5432/test"));
|
||||||
assert_eq!(cfg::NAMESPACE::FOO(), true);
|
assert_eq!(cfg::APP:ARTICLE:PER_PAGE(), 15);
|
||||||
|
assert_eq!(cfg::FEATURE::NEW_MENU(), true);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -77,10 +89,12 @@ cargo test
|
||||||
* [x] Support feature config and other meta directives
|
* [x] Support feature config and other meta directives
|
||||||
* [x] Add default value to env if env is not found
|
* [x] Add default value to env if env is not found
|
||||||
* [x] Concat env variables to one variable
|
* [x] Concat env variables to one variable
|
||||||
* [ ] Add nested namespaces
|
* [x] Add nested namespaces
|
||||||
|
* [x] Support meta for namespaces
|
||||||
* [ ] Support array type
|
* [ ] Support array type
|
||||||
* [ ] Support hashmap type
|
* [ ] Support hashmap type
|
||||||
* [ ] Support custom env type
|
* [ ] Support custom env type
|
||||||
|
* [ ] Common configuration for namespace variables
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
|
@ -13,7 +13,9 @@ use std::env;
|
||||||
//use dotenv::dotenv;
|
//use dotenv::dotenv;
|
||||||
|
|
||||||
config! {
|
config! {
|
||||||
DEBUG: bool => true,
|
DEBUG: bool => false,
|
||||||
|
|
||||||
|
#[env_name = "APP_HOST"]
|
||||||
HOST: String => "127.0.0.1",
|
HOST: String => "127.0.0.1",
|
||||||
|
|
||||||
DATABASE_URL < (
|
DATABASE_URL < (
|
||||||
|
@ -27,26 +29,36 @@ config! {
|
||||||
POSTGRES_DB => "test",
|
POSTGRES_DB => "test",
|
||||||
),
|
),
|
||||||
|
|
||||||
NAMESPACE {
|
APP {
|
||||||
#[env_name = "MY_CUSTOM_NAME"]
|
ARTICLE {
|
||||||
FOO: bool,
|
PER_PAGE: u32 => 15,
|
||||||
|
}
|
||||||
|
|
||||||
BAR: i32 => 10,
|
#[cfg(feature = "companies")]
|
||||||
|
COMPANY {
|
||||||
|
#[env_name = "INSTITUTIONS_PER_PAGE"]
|
||||||
|
PER_PAGE: u32 => 15,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "feature")]
|
FEATURE {
|
||||||
#[env_name = "POSTGRES_CONNECTION_STRING"]
|
NEW_MENU: bool => false,
|
||||||
DATABASE_URL: String
|
|
||||||
|
COMPANY {
|
||||||
|
PROFILE: bool => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main () {
|
fn main () {
|
||||||
// dotenv().ok();
|
// dotenv().ok();
|
||||||
env::set_var("MY_CUSTOM_NAME", "t");
|
env::set_var("FEATURE_NEW_MENU", "t");
|
||||||
|
|
||||||
cfg::init();
|
cfg::init();
|
||||||
assert_eq!(cfg::HOST(), String::from("127.0.0.1"));
|
assert_eq!(cfg::HOST(), String::from("127.0.0.1"));
|
||||||
assert_eq!(cfg::DATABASE_URL(), String::from("postgres://user:pass@localhost:5432/test"));
|
assert_eq!(cfg::DATABASE_URL(), String::from("postgres://user:pass@localhost:5432/test"));
|
||||||
assert_eq!(cfg::NAMESPACE::FOO(), true);
|
assert_eq!(cfg::APP:ARTICLE:PER_PAGE(), 15);
|
||||||
|
assert_eq!(cfg::FEATURE::NEW_MENU(), true);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -58,10 +70,12 @@ fn main () {
|
||||||
* [x] Support feature config and other meta directives
|
* [x] Support feature config and other meta directives
|
||||||
* [x] Add default value to env if env is not found
|
* [x] Add default value to env if env is not found
|
||||||
* [x] Concat env variables to one variable
|
* [x] Concat env variables to one variable
|
||||||
* [ ] Add nested namespaces
|
* [x] Add nested namespaces
|
||||||
|
* [x] Support meta for namespaces
|
||||||
* [ ] Support array type
|
* [ ] Support array type
|
||||||
* [ ] Support hashmap type
|
* [ ] Support hashmap type
|
||||||
* [ ] Support custom env type
|
* [ ] Support custom env type
|
||||||
|
* [ ] Common configuration for namespace variables
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
|
@ -25,22 +25,36 @@
|
||||||
//! POSTGRES_DB => "test",
|
//! POSTGRES_DB => "test",
|
||||||
//! ),
|
//! ),
|
||||||
//!
|
//!
|
||||||
//! NAMESPACE {
|
//! APP {
|
||||||
//! #[env_name = "MY_CUSTOM_NAME"]
|
//! ARTICLE {
|
||||||
//! FOO: bool,
|
//! PER_PAGE: u32 => 15,
|
||||||
|
//! }
|
||||||
//!
|
//!
|
||||||
//! BAR: i32 => 10,
|
//! #[cfg(feature = "companies")]
|
||||||
|
//! COMPANY {
|
||||||
|
//! #[env_name = "INSTITUTIONS_PER_PAGE"]
|
||||||
|
//! PER_PAGE: u32 => 15,
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! FEATURE {
|
||||||
|
//! NEW_MENU: bool => false,
|
||||||
|
//!
|
||||||
|
//! COMPANY {
|
||||||
|
//! PROFILE: bool => false,
|
||||||
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn main () {
|
//! fn main () {
|
||||||
//! // dotenv().ok();
|
//! // dotenv().ok();
|
||||||
//! env::set_var("MY_CUSTOM_NAME", "t");
|
//! env::set_var("FEATURE_NEW_MENU", "t");
|
||||||
//!
|
//!
|
||||||
//! cfg::init();
|
//! cfg::init();
|
||||||
//! assert_eq!(cfg::HOST(), String::from("127.0.0.1"));
|
//! assert_eq!(cfg::HOST(), String::from("127.0.0.1"));
|
||||||
//! assert_eq!(cfg::DATABASE_URL(), String::from("postgres://user:pass@localhost:5432/test"));
|
//! assert_eq!(cfg::DATABASE_URL(), String::from("postgres://user:pass@localhost:5432/test"));
|
||||||
//! assert_eq!(cfg::NAMESPACE::FOO(), true);
|
//! assert_eq!(cfg::APP::ARTICLE::PER_PAGE(), 15);
|
||||||
|
//! assert_eq!(cfg::FEATURE::NEW_MENU(), true);
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
@ -165,6 +179,41 @@ impl From<EnvValue> for String {
|
||||||
/// # cfg::init()
|
/// # cfg::init()
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// Now you can use nested structure in namespaces without limits :)
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// config! {
|
||||||
|
/// FIRST {
|
||||||
|
/// SECOND {
|
||||||
|
/// THIRD {
|
||||||
|
/// FOO: bool => true,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// # cfg::init();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Namespaces supports custom meta
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// config! {
|
||||||
|
/// #[cfg(feature = "first")]
|
||||||
|
/// FIRST {
|
||||||
|
/// #[cfg(feature = "second")]
|
||||||
|
/// SECOND {
|
||||||
|
/// #[cfg(feature = "third")]
|
||||||
|
/// THIRD {
|
||||||
|
/// FOO: bool => true,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// # cfg::init();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// Meta
|
/// Meta
|
||||||
/// ----
|
/// ----
|
||||||
///
|
///
|
||||||
|
@ -343,6 +392,7 @@ macro_rules! __itconfig_parse_module {
|
||||||
module = {
|
module = {
|
||||||
env_prefix = "",
|
env_prefix = "",
|
||||||
name = $name,
|
name = $name,
|
||||||
|
meta = [],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -360,6 +410,7 @@ macro_rules! __itconfig_parse_variables {
|
||||||
// Find namespace
|
// Find namespace
|
||||||
(
|
(
|
||||||
tokens = [
|
tokens = [
|
||||||
|
$(#$meta:tt)*
|
||||||
$ns_name:ident { $($ns_tokens:tt)* }
|
$ns_name:ident { $($ns_tokens:tt)* }
|
||||||
$($rest:tt)*
|
$($rest:tt)*
|
||||||
],
|
],
|
||||||
|
@ -368,9 +419,11 @@ macro_rules! __itconfig_parse_variables {
|
||||||
__itconfig_parse_variables! {
|
__itconfig_parse_variables! {
|
||||||
tokens = [$($ns_tokens)*],
|
tokens = [$($ns_tokens)*],
|
||||||
variables = [],
|
variables = [],
|
||||||
|
namespaces = [],
|
||||||
module = {
|
module = {
|
||||||
env_prefix = concat!(stringify!($ns_name), "_"),
|
env_prefix = concat!(stringify!($ns_name), "_"),
|
||||||
name = $ns_name,
|
name = $ns_name,
|
||||||
|
meta = [$(#$meta)*],
|
||||||
},
|
},
|
||||||
callback = {
|
callback = {
|
||||||
tokens = [$($rest)*],
|
tokens = [$($rest)*],
|
||||||
|
@ -526,9 +579,8 @@ macro_rules! __itconfig_parse_variables {
|
||||||
(
|
(
|
||||||
tokens = [],
|
tokens = [],
|
||||||
variables = $ns_variables:tt,
|
variables = $ns_variables:tt,
|
||||||
module = {
|
namespaces = $ns_namespaces:tt,
|
||||||
$($current_namespace:tt)*
|
module = $ns_module:tt,
|
||||||
},
|
|
||||||
callback = {
|
callback = {
|
||||||
tokens = $tokens:tt,
|
tokens = $tokens:tt,
|
||||||
variables = $variables:tt,
|
variables = $variables:tt,
|
||||||
|
@ -543,7 +595,8 @@ macro_rules! __itconfig_parse_variables {
|
||||||
$($namespaces,)*
|
$($namespaces,)*
|
||||||
{
|
{
|
||||||
variables = $ns_variables,
|
variables = $ns_variables,
|
||||||
$($current_namespace)*
|
namespaces = $ns_namespaces,
|
||||||
|
module = $ns_module,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
$($args)*
|
$($args)*
|
||||||
|
@ -555,7 +608,7 @@ macro_rules! __itconfig_parse_variables {
|
||||||
tokens = [],
|
tokens = [],
|
||||||
$($args:tt)*
|
$($args:tt)*
|
||||||
) => {
|
) => {
|
||||||
__itconfig_impl!($($args)*);
|
__itconfig_impl_namespace!($($args)*);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Invalid syntax
|
// Invalid syntax
|
||||||
|
@ -567,7 +620,7 @@ macro_rules! __itconfig_parse_variables {
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! __itconfig_impl {
|
macro_rules! __itconfig_impl_namespace {
|
||||||
(
|
(
|
||||||
variables = [$({
|
variables = [$({
|
||||||
meta = $var_meta:tt,
|
meta = $var_meta:tt,
|
||||||
|
@ -576,44 +629,42 @@ macro_rules! __itconfig_impl {
|
||||||
$($variable:tt)*
|
$($variable:tt)*
|
||||||
},)*],
|
},)*],
|
||||||
namespaces = [$({
|
namespaces = [$({
|
||||||
variables = [$({
|
variables = $ns_variable:tt,
|
||||||
meta = $ns_var_meta:tt,
|
namespaces = $ns_namespaces:tt,
|
||||||
concat = $ns_var_concat:tt,
|
module = {
|
||||||
name = $ns_var_name:ident,
|
env_prefix = $ns_env_prefix:expr,
|
||||||
$($ns_variables:tt)*
|
name = $ns_mod_name:ident,
|
||||||
},)*],
|
meta = [$(#$ns_meta:tt)*],
|
||||||
env_prefix = $ns_env_prefix:expr,
|
},
|
||||||
name = $ns_name:ident,
|
|
||||||
},)*],
|
},)*],
|
||||||
module = {
|
module = {
|
||||||
env_prefix = $env_prefix:expr,
|
env_prefix = $env_prefix:expr,
|
||||||
name = $mod_name:ident,
|
name = $mod_name:ident,
|
||||||
|
meta = [$(#$meta:tt)*],
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
|
$(#$meta)*
|
||||||
pub mod $mod_name {
|
pub mod $mod_name {
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
use std::env;
|
use std::env;
|
||||||
use itconfig::EnvValue;
|
use itconfig::EnvValue;
|
||||||
|
|
||||||
$(
|
$(__itconfig_impl_namespace! {
|
||||||
pub mod $ns_name {
|
variables = $ns_variable,
|
||||||
use std::env;
|
namespaces = $ns_namespaces,
|
||||||
use itconfig::EnvValue;
|
module = {
|
||||||
|
env_prefix = $ns_env_prefix,
|
||||||
$(__itconfig_variable! {
|
name = $ns_mod_name,
|
||||||
meta = $ns_var_meta,
|
meta = [$(#$ns_meta)*],
|
||||||
concat = $ns_var_concat,
|
},
|
||||||
name = $ns_var_name,
|
})*
|
||||||
env_prefix = $ns_env_prefix,
|
|
||||||
$($ns_variables)*
|
|
||||||
})*
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
$($var_name();)*
|
$($var_name();)*
|
||||||
|
$(
|
||||||
$($($ns_name::$ns_var_name();)*)*
|
$(#$ns_meta)*
|
||||||
|
$ns_mod_name::init();
|
||||||
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
$(__itconfig_variable! {
|
$(__itconfig_variable! {
|
||||||
|
|
|
@ -10,3 +10,7 @@ publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
itconfig = { path = '../itconfig' }
|
itconfig = { path = '../itconfig' }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["meta_namespace"]
|
||||||
|
meta_namespace = []
|
||||||
|
|
|
@ -179,6 +179,39 @@ fn configuration_with_namespace() {
|
||||||
assert_eq!(cfg::DB::HOST(), true);
|
assert_eq!(cfg::DB::HOST(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn configuration_with_nested_namespaces() {
|
||||||
|
config! {
|
||||||
|
FIRST {
|
||||||
|
SECOND {
|
||||||
|
THIRD {
|
||||||
|
FOO: u32 => 50,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg::init();
|
||||||
|
assert_eq!(cfg::FIRST::SECOND::THIRD::FOO(), 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "meta_namespace")]
|
||||||
|
#[test]
|
||||||
|
fn configuration_namespaces_with_custom_meta() {
|
||||||
|
config! {
|
||||||
|
FIRST {
|
||||||
|
#[cfg(feature = "meta_namespace")]
|
||||||
|
SECOND {
|
||||||
|
THIRD {
|
||||||
|
FOO: u32 => 50,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg::init();
|
||||||
|
assert_eq!(cfg::FIRST::SECOND::THIRD::FOO(), 50);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn configuration_variables_and_namespace_in_lowercase() {
|
fn configuration_variables_and_namespace_in_lowercase() {
|
||||||
|
|
Reference in a new issue