12 个版本 (3 个稳定版)
1.2.0 | 2024 年 2 月 18 日 |
---|---|
1.1.1 | 2023 年 9 月 25 日 |
0.3.5 | 2023 年 9 月 23 日 |
0.2.0 | 2023 年 9 月 23 日 |
0.1.1 | 2023 年 9 月 23 日 |
#56 in 配置
每月下载量 92 次
48KB
832 行
toml-env
一个使用 toml
的简单配置库。
此库旨在使用 initialize()
函数在启动时加载应用程序的配置。配置可以按以下顺序加载
- 从 dotenv 风格的文件
.env.toml
(您选择的文件名) - 从环境变量
CONFIG
(或您选择的变量名)。 - 从映射的环境(例如
MY_VARIABLE => my_variable.child
)。 - 从配置文件。
为什么还需要另一个配置库?
以下是这个库的一些可能替代品
config
您需要最大限度的灵活性。figment
您需要最大限度的灵活性。just-config
您需要最大限度的灵活性。dotenvy
您只需要.env
支持。env_inventory
您只需要环境变量配置文件支持。
为什么选择这个?
- 小型且具有意见的功能集。
- 最小依赖。
.env
使用TOML
,这是一个更成熟的文件格式标准。- 使用自定义映射将环境变量加载到配置中(
MY_VARIABLE => child.child.config
),采用 json pointer 风格(不支持完整语法)。 - 使用可配置的自动映射将环境变量加载到配置中(
MY_APP__PARENT__CHILD => parent.child
) - 从存储在多行环境变量中的 TOML 加载配置。
- 对于具有嵌套映射的大配置,这可能与以下代码相比更容易阅读:
MY_VARIABLE__SOMETHING_ELSE__SOMETHING_SOMETHING_ELSE
。 - 您也可以直接复制TOML文件中的文本以用作环境变量,而不是将其翻译成复杂的变量名称。
- 对于具有嵌套映射的大配置,这可能与以下代码相比更容易阅读:
配置结构
首先,您需要定义一个实现 serde::de::DeserializeOwned
+ serde::Serialize
+ Default
#[derive(serde::Serialize, serde::Deserialize, Default)]
struct Config {
config_value_1: String,
config_value_2: String,
config_child: ConfigChild
}
#[derive(serde::Serialize, serde::Deserialize, Default)]
struct ConfigChild {
config_value_3: String,
}
.env.toml
默认情况下,配置将尝试从名为 .env.toml
的文件中加载。您可以自定义此文件的名称。该文件的格式如下:
SECRET_ENV_VAR_1="some value"
SECRET_ENV_VAR_2="some other value"
[CONFIG]
config_value_1="some value"
config_value_2="some other value"
[CONFIG.config_child]
config_value_3="some other other value"
您可以使用文件中的顶层键来设置应用程序的环境变量(例如,SECRET_ENV_VAR_1
)。
配置可以从文件的一部分加载到 CONFIG
中。CONFIG
键将是 Args::config_variable_name
的名称,默认为 CONFIG
。
环境变量 CONFIG
您可以通过使用 Args::config_variable_name
(默认为 CONFIG
)指定的变量名称来指定配置。
# Store a multiline string into an environment variable in bash shell.
read -r -d '' CONFIG << EOM
config_value_1="some value"
config_value_2="some other value"
[config_child]
config_value_3="some other other value"
EOM
示例
CONFIG
变量
一个简单示例,使用默认设置从 CONFIG
加载配置。
use serde::{Deserialize, Serialize};
use toml_env::{initialize, Args};
#[derive(Serialize, Deserialize)]
struct Config {
value_1: String,
value_2: bool,
}
// Normally you may choose set this from a shell script or some
// other source in your environment (docker file or server config file).
std::env::set_var(
"CONFIG",
r#"
value_1="Something from CONFIG environment"
value_2=true
"#,
);
let config: Config = initialize(Args::default())
.unwrap()
.unwrap();
assert_eq!(config.value_1, "Something from CONFIG environment");
assert_eq!(config.value_2, true);
自定义变量映射
自定义环境变量映射的简单演示
use serde::{Deserialize, Serialize};
use toml_env::{Args, initialize, TomlKeyPath};
use std::str::FromStr;
#[derive(Serialize, Deserialize)]
struct Config {
value_1: String,
value_2: bool,
}
// Normally you may choose set this from a shell script or some
// other source in your environment (docker file or server config file).
std::env::set_var("VALUE_1", "Hello World");
std::env::set_var("VALUE_2", "true");
let config: Config = initialize(Args {
map_env: [
("VALUE_1", "value_1"),
("VALUE_2", "value_2"),
]
.into_iter()
.map(|(key, value)| {
(key, TomlKeyPath::from_str(value).unwrap())
}).collect(),
..Args::default()
})
.unwrap()
.unwrap();
assert_eq!(config.value_1, "Hello World");
assert_eq!(config.value_2, true);
自动变量映射
自动环境变量映射的简单演示
use serde::{Deserialize, Serialize};
use toml_env::{Args, initialize, AutoMapEnvArgs};
// NOTE: the `deny_unknown_fields` can be used to reject
// mappings which don't conform to the current spec.
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct Config {
value_1: String,
value_2: bool,
}
// Normally you may choose set this from a shell script or some
// other source in your environment (docker file or server config file).
std::env::set_var("CONFIG__VALUE_1", "Hello World");
std::env::set_var("CONFIG__VALUE_2", "true");
let config: Config = initialize(Args {
auto_map_env: Some(AutoMapEnvArgs::default()),
// The default prefix is CONFIG.
// In practice you would usually use a custom prefix:
// prefix: Some("MY_APP"),
..Args::default()
})
.unwrap()
.unwrap();
assert_eq!(config.value_1, "Hello World");
assert_eq!(config.value_2, true);
.env.toml
文件
一个简单示例,使用默认设置从 .env.toml
加载配置和环境变量。
use serde::{Deserialize, Serialize};
use toml_env::{Args, initialize};
#[derive(Serialize, Deserialize)]
struct Config {
value_1: String,
value_2: bool,
}
let dir = tempfile::tempdir().unwrap();
std::env::set_current_dir(&dir).unwrap();
let dotenv_path = dir.path().join(".env.toml");
// Normally you would read this from .env.toml file
std::fs::write(
&dotenv_path,
r#"
OTHER_VARIABLE="hello-world"
[CONFIG]
value_1="Something from .env.toml"
value_2=true
"#,
)
.unwrap();
let config: Config = initialize(Args::default())
.unwrap()
.unwrap();
assert_eq!(config.value_1, "Something from .env.toml");
assert_eq!(config.value_2, true);
let secret = std::env::var("OTHER_VARIABLE").unwrap();
assert_eq!(secret, "hello-world");
所有功能
一个更复杂的示例,演示了所有功能。
use serde::{Deserialize, Serialize};
use tempfile::tempdir;
use toml_env::{Args, initialize, Logging, TomlKeyPath, AutoMapEnvArgs};
use std::str::FromStr;
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct Config {
value_1: String,
value_2: bool,
child: Child,
array: Vec<String>,
}
#[derive(Serialize, Deserialize, Default)]
#[serde(deny_unknown_fields)]
struct Child {
value_3: i32,
value_4: u8,
value_5: String,
value_6: String,
}
let dir = tempdir().unwrap();
let dotenv_path = dir.path().join(".env.toml");
let config_path = dir.path().join("config.toml");
// Normally you would read this from .env.toml file
std::fs::write(
&dotenv_path,
r#"
SECRET="hello-world"
[MY_CONFIG]
value_1="Something from .env.toml"
[MY_CONFIG.child]
value_3=-5
value_4=16
"#,
)
.unwrap();
// Normally you may choose set this from a shell script or some
// other source in your environment (docker file or server config file).
std::env::set_var(
"MY_CONFIG",
r#"
value_1="Something from MY_CONFIG environment"
value_2=true
"#,
);
std::env::set_var(
"VALUE_1",
"Something from Environment"
);
std::env::set_var(
"VALUE_5",
"Something from Environment"
);
std::env::set_var(
"MY_APP__CHILD__VALUE_6",
"Something from Environment"
);
std::env::set_var(
"MY_APP__ARRAY__1",
"Hello"
);
std::env::set_var(
"MY_APP__ARRAY__0",
"Hello"
);
// Normally you would read this from config.toml
// (or whatever name you want) file.
std::fs::write(
&config_path,
r#"
value_1="Something from config.toml"
value_2=false
[child]
value_4=45
"#,
)
.unwrap();
let config: Config = initialize(Args {
dotenv_path: &dotenv_path,
config_path: Some(&config_path),
config_variable_name: "MY_CONFIG",
logging: Logging::StdOut,
map_env: [
("VALUE_1", "value_1"),
("VALUE_5", "child.value_5"),
("VALUE_99", "does.not.exist"),
]
.into_iter()
.map(|(key, value)| {
(key, TomlKeyPath::from_str(value).unwrap())
}).collect(),
auto_map_env: Some(AutoMapEnvArgs {
divider: "__",
prefix: Some("MY_APP"),
transform: Box::new(|name| name.to_lowercase()),
})
})
.unwrap()
.unwrap();
assert_eq!(config.value_1, "Something from .env.toml");
assert_eq!(config.value_2, true);
assert_eq!(config.array[0], "Hello");
assert_eq!(config.child.value_3, -5);
assert_eq!(config.child.value_4, 16);
assert_eq!(config.child.value_5, "Something from Environment");
let secret = std::env::var("SECRET").unwrap();
assert_eq!(secret, "hello-world");
变更日志
有关此库的更改,请参阅 CHANGELOG.md。
依赖项
~0.6–1.2MB
~27K SLoC