//! Typed config loading
//!
//! `#[config]` generates loaders for TOML constants and environment values.
//! Field attributes name the source:
//!
//! ```
//! # #[cfg(all(feature = "config", feature = "types"))]
//! # fn run() -> Result<(), efdn::config::ConfigError> {
//! use efdn::config::{config, Sources, TomlText};
//! use efdn::types::typed;
//!
//! #[typed(text, non_empty)]
//! pub struct ServiceName;
//!
//! #[typed(uint, inner = u16, min = 1, max = 65535)]
//! pub struct ServicePort;
//!
//! #[config(root, env(prefix = "WORKER"), file(path = "config.toml"))]
//! pub struct Config {
//!     #[file]
//!     pub service: ServiceConfig,
//! }
//!
//! #[config]
//! pub struct ServiceConfig {
//!     #[default("worker")]
//!     pub name: ServiceName,
//!     #[env("WORKER_PORT")]
//!     pub port: ServicePort,
//! }
//!
//! let config = Config::load_from(
//!     Sources::empty()
//!         .with_toml(TomlText::new("[service]\n"))
//!         .with_env(
//!             efdn::config::EnvName::from_static("WORKER_PORT"),
//!             efdn::config::EnvValue::from_static("8080"),
//!         ),
//! )?;
//! assert_eq!(config.service.name.as_str(), "worker");
//! # Ok(())
//! # }
//! # fn main() {}
//! ```
//!
//! Use `#[file]` for constants that belong in TOML and `#[env]` for values
//! that change per deployment, including URLs and secrets.
//!
//! ## Root Options
//!
//! | Option | Meaning |
//! | --- | --- |
//! | `root` | Generate `load`, `load_from`, `schema`, and `example_toml` |
//! | `dotenv` | Load `.env` before process env |
//! | `env(prefix = "APP")` | Prefix generated env vars |
//! | `file(path = "config.toml")` | Default TOML file path |
//! | `file(env = "APP_CONFIG")` | Env var that overrides the TOML path |
//!
//! Without `dotenv`, `load()` reads process env only. Without `file(...)`, it
//! reads `config.toml`. Without `env(prefix = "...")`, generated env vars use
//! the dotted field path, such as `SERVICE_PORT`.
//!
//! ## Field Attributes
//!
//! | Attribute | Meaning |
//! | --- | --- |
//! | `#[file]` | Read a section or leaf from TOML |
//! | `#[env]` | Read a section or leaf from env |
//! | `#[env("NAME")]` | Read a leaf from one exact env var |
//! | `#[env(prefix = "NATS")]` | Read section leaves as `NATS_*` |
//! | `#[env(optional)]` | Missing env is allowed for `Option<T>` |
//! | `#[default("value")]` | Parse a fallback through the field type |
//! | `#[section]` | Mark a nested non-root field as a config section |
//!
//! Root fields must use `#[file]` or `#[env]`. Non-root leaves inherit their
//! parent source. A raw `String`, `u64`, `bool`, or `Vec<T>` field fails at
//! compile time; declare a typed newtype instead.
//!
//! ## Reloading
//!
//! Configuration loads once at startup. Changed TOML or env values take
//! effect only after a restart. A service that needs hot reload must watch
//! its inputs and rebuild the config itself on top of [`source::Sources`].

pub mod context;
pub mod error;
pub mod schema;
pub mod source;
pub mod toml_example;
