Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/abakay/irx-config

The library provides convenient way to represent/parse configuration from different sources. The main goals is to be very easy to use and to be extendable
https://github.com/abakay/irx-config

clap command-line config configuration environment environment-variables json json5 parsers rust seal secrets toml yaml

Last synced: 4 months ago
JSON representation

The library provides convenient way to represent/parse configuration from different sources. The main goals is to be very easy to use and to be extendable

Awesome Lists containing this project

README

        

# irx-config library

![GitHub top language](https://img.shields.io/github/languages/top/abakay/irx-config) ![Crates.io](https://img.shields.io/crates/v/irx-config) ![Crates.io](https://img.shields.io/crates/l/irx-config) ![Crates.io](https://img.shields.io/crates/d/irx-config) ![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/cargo/irx-config) ![docs.rs](https://img.shields.io/docsrs/irx-config)

The `irx-config` library provides convenient way to represent/parse configuration from different sources. The main
goals is to be very easy to use and to be extendable.

## Features

* Fully compatible with [serde](https://serde.rs/)
* Full deep merge of nested dictionaries/mappings
* Case sensitive/insensitive parameters names matching/merging
* Sealing secrets during display/debugging
* Get all configuration parameters or just cherry pick few
* Several embedded parsers available via library features:
* Command-line argument (via [clap](https://github.com/clap-rs/clap))
* Environment variables
* File based parsers: `JSON`, `JSON5`, `YAML` and `TOML`
* Could be extended with custom parsers

## Examples

### JSON with environment variables

To enable parsers used in example below, one has to add the following to `Cargo.toml`:

```toml
[dependencies]
irx-config = { version = "3.4", features = ["env", "json"] }
```

```rust
use irx_config::parsers::{env, json};
use irx_config::ConfigBuilder;
use serde::Deserialize;

#[derive(Deserialize)]
struct Conf {
id: u32,
logger: String,
tag: String,
}

// Data from two parsers will be merged. The values from parser appended first (`JSON`)
// will take precedence if values have a same names
let config = ConfigBuilder::default()
.append_parser(
json::ParserBuilder::default()
.default_path("config.json")
.build()?,
)
.append_parser(
env::ParserBuilder::default()
.default_prefix("APP_")
.build()?,
)
.load()?;

let conf_data: Conf = config.get()?;
```

### Command-line, TOML and environment variables

To enable parsers used in example below, one has to add the following to `Cargo.toml`:

```toml
[dependencies]
irx-config = { version = "3.4", features = ["cmd", "env", "toml-parser"] }
```

```rust
use clap::app_from_crate;
use irx_config::parsers::{cmd, env, toml};
use irx_config::ConfigBuilder;
use serde::Deserialize;

fn localhost() -> String {
"localhost".into()
}

#[derive(Deserialize)]
struct Logger {
level: String,
path: String,
}

#[derive(Deserialize)]
struct Connection {
#[serde(default = "localhost")]
host: String,
port: u16,
}

#[derive(Deserialize)]
struct Conf {
id: u32,
logger: Logger,
connection: Connection,
}

let app = app_from_crate!();

// Data from three parsers will be merged. The values from parser appended first (`cmd`)
// will take precedence if values have a same names
let config = ConfigBuilder::default()
.append_parser(
cmd::ParserBuilder::new(app)
.exit_on_error(true)
.build()?,
)
.append_parser(
toml::ParserBuilder::default()
.default_path("config.toml")
.path_option("config")
.build()?,
)
.append_parser(
env::ParserBuilder::default()
.default_prefix("APP_")
.prefix_option("prefix")
.build()?,
)
.load()?;

let conf_data: Conf = config.get()?;
```

### Custom parser

```rust
use irx_config::{AnyResult, Case, ConfigBuilder, Parse, Value};
use serde::Deserialize;
use std::borrow::Cow;

#[derive(Deserialize)]
struct Conf {
id: u32,
logger: String,
tag: String,
}

struct JsonStringParser<'a> {
data: Cow<'a, str>,
}

impl<'a> JsonStringParser<'a> {
pub fn new(data: impl Into>) -> Self {
JsonStringParser { data: data.into() }
}
}

impl Case for JsonStringParser<'_> {}

impl Parse for JsonStringParser<'_> {
fn parse(&mut self, _value: &Value) -> AnyResult {
Ok(serde_json::from_str(&self.data)?)
}
}

let data = r#"{ "id": 42, "logger": "file", "tag": "test" }"#;
let config = ConfigBuilder::load_one(JsonStringParser::new(data))?;
let conf_data: Conf = config.get()?;
```

### JSON parser get partial data

To enable parsers used in example below, one has to add the following to `Cargo.toml`:

```toml
[dependencies]
irx-config = { version = "3.4", features = ["json"] }
```

```rust
use irx_config::parsers::json;
use irx_config::ConfigBuilder;
use serde::Deserialize;

fn localhost() -> String {
"localhost".into()
}

#[derive(Deserialize)]
struct Logger {
level: String,
path: String,
}

#[derive(Deserialize)]
struct Connection {
#[serde(default = "localhost")]
host: String,
port: u16,
}

let config = ConfigBuilder::load_one(
json::ParserBuilder::default()
.default_path("config.json")
.build()?,
)?;

let logger: Logger = config.get_by_key_path("logger")?.unwrap();
let port: u16 = config.get_by_key_path("connection:port")?.unwrap();
```