{"id":17126391,"url":"https://github.com/kellpossible/toml-env","last_synced_at":"2025-04-13T06:28:09.198Z","repository":{"id":196244752,"uuid":"695582631","full_name":"kellpossible/toml-env","owner":"kellpossible","description":"A simple configuration library using TOML","archived":false,"fork":false,"pushed_at":"2024-02-18T15:13:03.000Z","size":30,"stargazers_count":6,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-07T15:53:02.997Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kellpossible.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-09-23T15:56:35.000Z","updated_at":"2025-01-28T05:14:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"fa1f76e8-f6e5-4f84-ad0f-6f85e71057cc","html_url":"https://github.com/kellpossible/toml-env","commit_stats":null,"previous_names":["kellpossible/toml-env"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kellpossible%2Ftoml-env","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kellpossible%2Ftoml-env/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kellpossible%2Ftoml-env/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kellpossible%2Ftoml-env/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kellpossible","download_url":"https://codeload.github.com/kellpossible/toml-env/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248673780,"owners_count":21143565,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T18:47:52.018Z","updated_at":"2025-04-13T06:28:09.176Z","avatar_url":"https://github.com/kellpossible.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `toml-env`\n\n[![crates.io](https://img.shields.io/crates/v/toml-env.svg)](https://crates.io/crates/toml-env) [![docs.rs](https://img.shields.io/docsrs/toml-env.svg)](https://docs.rs/toml-env/latest/toml_env/) [![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/kellpossible/toml-env/rust.yml)](https://github.com/kellpossible/toml-env/actions/workflows/rust.yml)\n\n\nA simple configuration library using `toml`.\n\nThis library is designed to load a configuration for an application at startup using the `initialize()` function. The configuration can be loaded (in order of preference):\n\n1. From a dotenv style file `.env.toml` (a file name of your choosing)\n2. From an environment variable `CONFIG` (or a variable name of your choosing).\n3. From mapped environments (e.g. `MY_VARIABLE =\u003e my_variable.child`).\n4. From a configuration file.\n\n## Why yet another config library?\n\nHere are some possible alternatives to this library:\n\n- [`config`](https://crates.io/crates/config/) You want maximum flexibility.\n- [`figment`](https://crates.io/crates/figment) You want maximum flexibility.\n- [`just-config`](https://crates.io/crates/justconfig/) You want maximum flexibility.\n- [`dotenvy`](https://crates.io/crates/dotenvy) You just want `.env` support.\n- [`env_inventory`](https://crates.io/crates/env-inventory/) You just want environment variable configuration file support.\n\nWhy would you use this one?\n\n- Small opinionated feature set.\n- Minimal dependencies.\n- `.env` using `TOML` which is a more established file format standard.\n- Loading config from environment variables using custom mappings into the configuration (`MY_VARIABLE =\u003e child.child.config`) in a json pointer style (full syntax is not supported).\n- Loading config from environment variables using automatic mappings, which are configurable. (`MY_APP__PARENT__CHILD =\u003e parent.child`)\n- Loading config from TOML stored in a multiline environment variable.\n  - For large configurations with nested maps, this could be seen as a bit more legible than `MY_VARIABLE__SOMETHING_ELSE__SOMETHING_SOMETHING_ELSE`.\n  - You can also just copy text from a TOML file to use in the environment variable instead of translating it into complicated names of variables.\n\n## Config Struct\n\nFirstly you need to define your struct which implements `serde::de::DeserializeOwned` + `serde::Serialize` + `Default`:\n\n```rust\n#[derive(serde::Serialize, serde::Deserialize, Default)]\nstruct Config {\n    config_value_1: String,\n    config_value_2: String,\n    config_child: ConfigChild\n}\n\n#[derive(serde::Serialize, serde::Deserialize, Default)]\nstruct ConfigChild {\n    config_value_3: String,\n}\n```\n\n## `.env.toml`\n\nInitally configuration will attempted to be loaded from a file named `.env.toml` by default. You can elect to customize the name of this file. The format of this file is as follows:\n\n```toml\nSECRET_ENV_VAR_1=\"some value\"\nSECRET_ENV_VAR_2=\"some other value\"\n\n[CONFIG]\nconfig_value_1=\"some value\"\nconfig_value_2=\"some other value\"\n\n[CONFIG.config_child]\nconfig_value_3=\"some other other value\"\n```\n\nEnvironment variables for the application can be set using the top level keys in the file (e.g. `SECRET_ENV_VAR_1`).\n\nThe configuration can be loaded from a subset of this file in `CONFIG`. The `CONFIG` key will be the name from the `Args::config_variable_name` which is `CONFIG` by default.\n\n## Environment Variable `CONFIG`\n\nYou can specify the configuration by storing it in the variable name as specified using `Args::config_variable_name` (`CONFIG` by default).\n\n```bash\n# Store a multiline string into an environment variable in bash shell.\nread -r -d '' CONFIG \u003c\u003c EOM\nconfig_value_1=\"some value\"\nconfig_value_2=\"some other value\"\n\n[config_child]\nconfig_value_3=\"some other other value\"\nEOM\n```\n\n## Example\n\n### `CONFIG` Variable\n\nA simple example loading configuration from `CONFIG`, using the default settings.\n\n```rust\nuse serde::{Deserialize, Serialize};\nuse toml_env::{initialize, Args};\n\n#[derive(Serialize, Deserialize)]\nstruct Config {\n    value_1: String,\n    value_2: bool,\n}\n\n// Normally you may choose set this from a shell script or some\n// other source in your environment (docker file or server config file).\nstd::env::set_var(\n    \"CONFIG\",\n    r#\"\nvalue_1=\"Something from CONFIG environment\"\nvalue_2=true\n\"#,\n);\n\nlet config: Config = initialize(Args::default())\n    .unwrap()\n    .unwrap();\n\nassert_eq!(config.value_1, \"Something from CONFIG environment\");\nassert_eq!(config.value_2, true);\n```\n\n### Custom Variable Mappings\n\nA simple demonstration of the custom environment variable mappings:\n\n```rust\nuse serde::{Deserialize, Serialize};\nuse toml_env::{Args, initialize, TomlKeyPath};\nuse std::str::FromStr;\n\n#[derive(Serialize, Deserialize)]\nstruct Config {\n    value_1: String,\n    value_2: bool,\n}\n\n// Normally you may choose set this from a shell script or some\n// other source in your environment (docker file or server config file).\nstd::env::set_var(\"VALUE_1\", \"Hello World\");\nstd::env::set_var(\"VALUE_2\", \"true\");\n\nlet config: Config = initialize(Args {\n    map_env: [\n        (\"VALUE_1\", \"value_1\"),\n        (\"VALUE_2\", \"value_2\"),\n    ]\n    .into_iter()\n    .map(|(key, value)| {\n        (key, TomlKeyPath::from_str(value).unwrap())\n    }).collect(),\n    ..Args::default()\n})\n    .unwrap()\n    .unwrap();\n\nassert_eq!(config.value_1, \"Hello World\");\nassert_eq!(config.value_2, true);\n```\n\n### Automatic Variable Mappings\n\nA simple demonstration of the automatic environment variable mappings:\n\n```rust\nuse serde::{Deserialize, Serialize};\nuse toml_env::{Args, initialize, AutoMapEnvArgs};\n\n// NOTE: the `deny_unknown_fields` can be used to reject\n// mappings which don't conform to the current spec.\n#[derive(Serialize, Deserialize)]\n#[serde(deny_unknown_fields)]\nstruct Config {\n    value_1: String,\n    value_2: bool,\n}\n\n// Normally you may choose set this from a shell script or some\n// other source in your environment (docker file or server config file).\nstd::env::set_var(\"CONFIG__VALUE_1\", \"Hello World\");\nstd::env::set_var(\"CONFIG__VALUE_2\", \"true\");\n\nlet config: Config = initialize(Args {\n    auto_map_env: Some(AutoMapEnvArgs::default()),\n    // The default prefix is CONFIG.\n    // In practice you would usually use a custom prefix:\n    // prefix: Some(\"MY_APP\"),\n    ..Args::default()\n})\n    .unwrap()\n    .unwrap();\n\nassert_eq!(config.value_1, \"Hello World\");\nassert_eq!(config.value_2, true);\n```\n\n### `.env.toml` File\n\nA simple example loading configuration and environment variables from `.env.toml`, using the default settings.\n\n```rust\nuse serde::{Deserialize, Serialize};\nuse toml_env::{Args, initialize};\n\n#[derive(Serialize, Deserialize)]\nstruct Config {\n    value_1: String,\n    value_2: bool,\n}\n\nlet dir = tempfile::tempdir().unwrap();\nstd::env::set_current_dir(\u0026dir).unwrap();\nlet dotenv_path = dir.path().join(\".env.toml\");\n\n// Normally you would read this from .env.toml file\nstd::fs::write(\n    \u0026dotenv_path,\n    r#\"\nOTHER_VARIABLE=\"hello-world\"\n[CONFIG]\nvalue_1=\"Something from .env.toml\"\nvalue_2=true\n\"#,\n)\n.unwrap();\n\nlet config: Config = initialize(Args::default())\n    .unwrap()\n    .unwrap();\n\nassert_eq!(config.value_1, \"Something from .env.toml\");\nassert_eq!(config.value_2, true);\n\nlet secret = std::env::var(\"OTHER_VARIABLE\").unwrap();\nassert_eq!(secret, \"hello-world\");\n```\n\n### All Features\n\nA more complex example demonstrating all the features.\n\n```rust\nuse serde::{Deserialize, Serialize};\nuse tempfile::tempdir;\nuse toml_env::{Args, initialize, Logging, TomlKeyPath, AutoMapEnvArgs};\nuse std::str::FromStr;\n\n#[derive(Serialize, Deserialize)]\n#[serde(deny_unknown_fields)]\nstruct Config {\n    value_1: String,\n    value_2: bool,\n    child: Child,\n    array: Vec\u003cString\u003e,\n}\n\n#[derive(Serialize, Deserialize, Default)]\n#[serde(deny_unknown_fields)]\nstruct Child {\n    value_3: i32,\n    value_4: u8,\n    value_5: String,\n    value_6: String,\n}\n\nlet dir = tempdir().unwrap();\nlet dotenv_path = dir.path().join(\".env.toml\");\nlet config_path = dir.path().join(\"config.toml\");\n\n// Normally you would read this from .env.toml file\nstd::fs::write(\n    \u0026dotenv_path,\n    r#\"\nSECRET=\"hello-world\"\n[MY_CONFIG]\nvalue_1=\"Something from .env.toml\"\n[MY_CONFIG.child]\nvalue_3=-5\nvalue_4=16\n\"#,\n)\n.unwrap();\n\n// Normally you may choose set this from a shell script or some\n// other source in your environment (docker file or server config file).\nstd::env::set_var(\n    \"MY_CONFIG\",\n    r#\"\nvalue_1=\"Something from MY_CONFIG environment\"\nvalue_2=true\n\"#,\n);\n\nstd::env::set_var(\n    \"VALUE_1\",\n    \"Something from Environment\"\n);\nstd::env::set_var(\n    \"VALUE_5\",\n    \"Something from Environment\"\n);\nstd::env::set_var(\n    \"MY_APP__CHILD__VALUE_6\",\n    \"Something from Environment\"\n);\nstd::env::set_var(\n    \"MY_APP__ARRAY__1\",\n    \"Hello\"\n);\nstd::env::set_var(\n    \"MY_APP__ARRAY__0\",\n    \"Hello\"\n);\n\n// Normally you would read this from config.toml\n// (or whatever name you want) file.\nstd::fs::write(\n    \u0026config_path,\n    r#\"\nvalue_1=\"Something from config.toml\"\nvalue_2=false\n[child]\nvalue_4=45\n\"#,\n)\n.unwrap();\n\nlet config: Config = initialize(Args {\n    dotenv_path: \u0026dotenv_path,\n    config_path: Some(\u0026config_path),\n    config_variable_name: \"MY_CONFIG\",\n    logging: Logging::StdOut,\n    map_env: [\n        (\"VALUE_1\", \"value_1\"),\n        (\"VALUE_5\", \"child.value_5\"),\n        (\"VALUE_99\", \"does.not.exist\"),\n    ]\n    .into_iter()\n    .map(|(key, value)| {\n        (key, TomlKeyPath::from_str(value).unwrap())\n    }).collect(),\n    auto_map_env: Some(AutoMapEnvArgs {\n        divider: \"__\",\n        prefix: Some(\"MY_APP\"),\n        transform: Box::new(|name| name.to_lowercase()),\n    })\n})\n    .unwrap()\n    .unwrap();\n\nassert_eq!(config.value_1, \"Something from .env.toml\");\nassert_eq!(config.value_2, true);\nassert_eq!(config.array[0], \"Hello\");\nassert_eq!(config.child.value_3, -5);\nassert_eq!(config.child.value_4, 16);\nassert_eq!(config.child.value_5, \"Something from Environment\");\n\nlet secret = std::env::var(\"SECRET\").unwrap();\nassert_eq!(secret, \"hello-world\");\n```\n\n## Changelog\n\nSee [CHANGELOG.md](https://github.com/kellpossible/toml-env/blob/master/CHANGELOG.md) for an account of changes to this library.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkellpossible%2Ftoml-env","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkellpossible%2Ftoml-env","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkellpossible%2Ftoml-env/lists"}