Thanks to visit codestin.com
Credit goes to lib.rs

5 releases

Uses new Rust 2024

0.2.1 Aug 23, 2025
0.2.0 Aug 23, 2025
0.1.2 Aug 14, 2025
0.1.1 Aug 14, 2025
0.1.0 Aug 14, 2025

#938 in Configuration

Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App

173 downloads per month

Custom license

37KB
501 lines

konfik

konfik

A flexible and composable configuration parser for Rust applications that supports multiple sources and formats.

Features

  • 🔧 Multiple Sources: Load configuration from files, environment variables, and CLI arguments
  • 📁 Multiple Formats: Support for JSON, YAML, and TOML configuration files
  • 🎯 Priority System: CLI args > Environment variables > Config files
  • Validation: Custom validation functions for your configuration
  • 🚀 Zero Config: Works out of the box with sensible defaults
  • 📦 Derive Macro: Simple #[derive(Konfik)] for easy setup

Quick Start

Add to your Cargo.toml:

[dependencies]
konfik = "0.1"
serde = { version = "1.0", features = ["derive"] }
clap = { version = "4.5", features = ["derive"] } # optional! only needed for cli arguments

Basic Usage

use konfik::{ConfigLoader, LoadConfig, Konfik};
use serde::Deserialize;

#[derive(Deserialize, Konfik, Debug)]
struct AppConfig {
    database_url: String,
    port: u16,
    debug: bool,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Load with defaults (looks for config.json, config.yaml, config.toml)
    let config = AppConfig::load()?;

    println!("Config: {:#?}", config);
    Ok(())
}

Advanced Configuration

use konfik::{ConfigLoader, Error, Konfik};
use serde::Deserialize;
use clap::Parser;

#[derive(Deserialize, Konfik, Debug, Parser)]
struct AppConfig {
    database_url: String,
    port: u16,
    debug: bool,
    #[serde(skip)]
    runtime_data: Option<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ConfigLoader::default()
        .with_env_prefix("MYAPP")           // Environment variables: MYAPP_DATABASE_URL, etc.
        .with_config_file("app.toml")       // Additional config file
        .with_cli()                         // Enable CLI argument parsing
        .with_validation(|config| {         // Custom validation
            if let Some(port) = config.get("port").and_then(|v| v.as_u64()) {
                if port > 65535 {
                    return Err(Error::Validation("Port must be <= 65535".to_string()));
                }
            }
            Ok(())
        })
        .load::<AppConfig>()?;

    println!("Loaded config: {:#?}", config);
    Ok(())
}

Configuration Sources & Priority

konfik loads configuration from multiple sources in the following priority order (higher priority overrides lower):

  1. CLI Arguments (highest priority)
  2. Environment Variables
  3. Configuration Files (lowest priority)

Configuration Files

By default, konfik looks for these files in the current directory:

  • config.json
  • config.yaml
  • config.toml

You can specify custom files:

let config = ConfigLoader::default()
    .with_config_file("custom.toml")
    .with_config_files(&["/etc/myapp/config.yaml", "config.json"])
    .load::<AppConfig>()?;

Environment Variables

Environment variables are automatically mapped from your struct fields:

#[derive(Deserialize, Konfik)]
struct Config {
    database_url: String,  // DATABASE_URL
    api_key: String,       // API_KEY
    max_connections: u32,  // MAX_CONNECTIONS
}

With a prefix:

let config = ConfigLoader::default()
    .with_env_prefix("MYAPP")  // MYAPP_DATABASE_URL, MYAPP_API_KEY, etc.
    .load::<Config>()?;

CLI Arguments

The CLI is integrated with clap. It detects at runtime which fields are still missing and makes those required in the CLI:

#[derive(Deserialize, Konfik)]
struct Konfik {
    database_url: String,  // --database-url
    max_connections: u32,  // --max-connections
    debug: bool,          // --debug (flag, no value needed)
}

Supported Types

Konfik supports all types.

Validation

Add custom validation logic:

let config = ConfigLoader::default()
    .with_validation(|config| {
        // Validate port range
        if let Some(port) = config.get("port").and_then(|v| v.as_u64()) {
            if !(1024..=65535).contains(&port) {
                return Err(Error::Validation("Port must be between 1024 and 65535".into()));
            }
        }

        // Validate required combinations
        let has_ssl = config.get("ssl_enabled").and_then(|v| v.as_bool()).unwrap_or(false);
        let has_ssl_cert = config.get("ssl_cert_path").and_then(|v| v.as_str()).is_some();

        if has_ssl && !has_ssl_cert {
            return Err(Error::Validation("SSL enabled but no certificate path provided".into()));
        }

        Ok(())
    })
    .load::<AppConfig>()?;

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Radicle

To clone this repository on Radicle, simply run:

rad clone rad:z2FpyXb6X6ENg3MvQPkMfqVN7LcD8

Dependencies

~3–4.5MB
~92K SLoC