Crates.io | gonfig |
lib.rs | gonfig |
version | 0.1.7 |
created_at | 2025-08-03 18:09:11.090099+00 |
updated_at | 2025-09-25 18:51:11.705373+00 |
description | A unified configuration management library for Rust that seamlessly integrates environment variables, config files, and CLI arguments |
homepage | https://github.com/itsparser/gonfig |
repository | https://github.com/itsparser/gonfig |
max_upload_size | |
id | 1779934 |
size | 150,895 |
A unified configuration management library for Rust that seamlessly integrates environment variables, configuration files, and CLI arguments with a clean, intuitive API.
#[derive(Gonfig)]
Add to your Cargo.toml
:
[dependencies]
gonfig = "0.1.6"
serde = { version = "1.0", features = ["derive"] }
use gonfig::Gonfig;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Gonfig)]
#[Gonfig(env_prefix = "APP")]
struct Config {
// Environment variable: APP_DATABASE_URL
database_url: String,
// Environment variable: APP_PORT
port: u16,
// Skip this field from configuration
#[skip]
runtime_client: Option<DatabaseClient>,
}
fn main() -> gonfig::Result<()> {
std::env::set_var("APP_DATABASE_URL", "postgres://localhost/myapp");
std::env::set_var("APP_PORT", "8080");
let config = Config::from_gonfig()?;
println!("Database: {}", config.database_url);
println!("Port: {}", config.port);
Ok(())
}
use gonfig::{Gonfig, ConfigBuilder, MergeStrategy};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Gonfig)]
#[Gonfig(allow_cli, env_prefix = "MD")]
struct Mongo {
// Environment variable: MD_MONGO_USERNAME
// CLI argument: --mongo-username
username: String,
// Environment variable: MD_MONGO_PASSWORD
// CLI argument: --mongo-password
password: String,
}
#[derive(Debug, Serialize, Deserialize, Gonfig)]
struct Application {
// Environment variable: MD_APP_USERNAME
username: String,
// Environment variable: MD_APP_PASSWORD
password: String,
#[skip]
client: Option<HttpClient>, // Excluded from configuration
}
#[derive(Debug, Serialize, Deserialize, Gonfig)]
#[Gonfig(env_prefix = "MD")]
pub struct Config {
mongo: Mongo,
app: Application,
}
fn main() -> gonfig::Result<()> {
// Option 1: Use derive macro (simple)
let config = Config::from_gonfig()?;
// Option 2: Use builder (advanced)
let config = ConfigBuilder::new()
.with_merge_strategy(MergeStrategy::Deep)
.with_env("MD")
.with_file_optional("config.toml")?
.with_cli()
.validate_with(|value| {
// Custom validation logic
if let Some(port) = value.get("port").and_then(|p| p.as_u64()) {
if port > 65535 {
return Err(gonfig::Error::Validation("Invalid port".into()));
}
}
Ok(())
})
.build::<Config>()?;
Ok(())
}
Environment variables follow a hierarchical naming pattern:
{PREFIX}_{STRUCT}_{FIELD}
#[derive(Gonfig)]
#[Gonfig(env_prefix = "MD")]
struct Config {
mongo: MongoConfig, // MD_MONGO_*
app: AppConfig, // MD_APP_*
}
struct MongoConfig {
username: String, // → MD_MONGO_USERNAME
password: String, // → MD_MONGO_PASSWORD
}
struct Config {
#[gonfig(env_name = "DATABASE_URL")]
db_url: String, // → DATABASE_URL (ignores prefix)
port: u16, // → MD_CONFIG_PORT (uses prefix)
}
Attribute | Description | Example |
---|---|---|
env_prefix = "PREFIX" |
Set environment variable prefix | #[Gonfig(env_prefix = "APP")] |
allow_cli |
Enable CLI argument support | #[Gonfig(allow_cli)] |
allow_config |
Enable config file support | #[Gonfig(allow_config)] |
Attribute | Description | Example |
---|---|---|
env_name = "NAME" |
Override environment variable name | #[gonfig(env_name = "DB_URL")] |
cli_name = "name" |
Override CLI argument name | #[gonfig(cli_name = "database-url")] |
#[skip] |
Skip field from all sources | #[skip] |
#[skip_gonfig] |
Alternative skip syntax | #[skip_gonfig] |
Use skip attributes to exclude fields from configuration:
#[derive(Gonfig)]
struct Config {
database_url: String, // ✅ Included in configuration
#[skip]
runtime_client: Option<Client>, // ❌ Excluded from configuration
#[skip_gonfig]
internal_state: Vec<String>, // ❌ Excluded from configuration
}
CLI arguments use kebab-case naming:
#[derive(Gonfig)]
#[Gonfig(allow_cli)]
struct Config {
database_url: String, // → --database-url
max_connections: u32, // → --max-connections
#[gonfig(cli_name = "db-port")]
port: u16, // → --db-port
}
Usage: cargo run -- --database-url postgres://localhost --max-connections 100
Sources are merged with the following priority (higher number wins):
use gonfig::MergeStrategy;
ConfigBuilder::new()
.with_merge_strategy(MergeStrategy::Deep) // Merge nested objects
.with_merge_strategy(MergeStrategy::Replace) // Replace entire values
.with_merge_strategy(MergeStrategy::Append) // Append arrays
Add custom validation logic:
ConfigBuilder::new()
.validate_with(|config| {
if let Some(port) = config.get("port").and_then(|p| p.as_u64()) {
if port == 0 || port > 65535 {
return Err(gonfig::Error::Validation(
"Port must be between 1 and 65535".into()
));
}
}
Ok(())
})
.build::<Config>()?;
Gonfig supports multiple config file formats:
# config.toml
database_url = "postgres://localhost/prod"
port = 8080
[mongo]
username = "admin"
password = "secret"
# config.yaml
database_url: postgres://localhost/prod
port: 8080
mongo:
username: admin
password: secret
{
"database_url": "postgres://localhost/prod",
"port": 8080,
"mongo": {
"username": "admin",
"password": "secret"
}
}
See the examples/ directory for more comprehensive examples:
your_usecase.rs
- Your exact use case implementationskip_attributes.rs
- Comprehensive skip examplesmadara_usecase.rs
- Complex hierarchical configurationsimple.rs
- Basic usage exampleRun examples:
cargo run --example your_usecase
cargo run --example skip_attributes
Gonfig provides detailed error types:
use gonfig::Error;
match config_result {
Err(Error::Environment(msg)) => eprintln!("Environment error: {}", msg),
Err(Error::Config(msg)) => eprintln!("Config file error: {}", msg),
Err(Error::Cli(msg)) => eprintln!("CLI error: {}", msg),
Err(Error::Validation(msg)) => eprintln!("Validation error: {}", msg),
Err(Error::Serialization(msg)) => eprintln!("Serialization error: {}", msg),
Ok(config) => println!("Config loaded successfully: {:?}", config),
}
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under either of
at your option.# gonfig