1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
//! High-level configuration management framework for Rust with derive macros.
//!
//! This crate provides a unified, easy-to-use API for configuration management
//! with support for:
//!
//! - File-based configuration (TOML, JSON, YAML)
//! - Environment variables with NPM-style naming (double underscore separator)
//! - Derive macros for declarative configuration
//! - Built-in validation via `validator` crate
//!
//! # Quick Start
//!
//! ```
//! use cfgmatic::{Config, ConfigLoader};
//! use serde::Deserialize;
//!
//! #[derive(Debug, Default, Deserialize, Config)]
//! #[config(prefix = "MYAPP")]
//! struct AppConfig {
//! #[config(default = "8080")]
//! port: u16,
//! #[config(default = "localhost")]
//! host: String,
//! }
//!
//! // Load from environment
//! let config = AppConfig::from_env().unwrap();
//! ```
//!
//! # NPM-style Environment Variables
//!
//! Environment variables follow NPM's naming convention using double underscore (`__`)
//! as a separator for nested fields:
//!
//! ```bash
//! # For struct with prefix "MYAPP" and field "database.url":
//! export MYAPP__DATABASE__URL="postgres://localhost/db"
//!
//! # For nested structs:
//! export MYAPP__SERVER__PORT="3000"
//! export MYAPP__SERVER__HOST="0.0.0.0"
//! ```
//!
//! # Validation
//!
//! Use the `validator` crate's derive macro for validation:
//!
//! ```
//! use cfgmatic::{Config, ConfigLoader};
//! use serde::Deserialize;
//! use validator::Validate;
//!
//! #[derive(Debug, Default, Deserialize, Config, Validate)]
//! struct DatabaseConfig {
//! #[validate(url)]
//! url: String,
//! #[validate(range(min = 1, max = 100))]
//! pool_size: u32,
//! }
//! ```
//!
//! # Reactive Configuration (Future Feature)
//!
//! ```ignore
//! use cfgmatic::reactive::{ConfigStream, FieldQuery};
//!
//! let mut stream = manager
//! .subscribe(FieldQuery::new(|c: &Config| c.server.port))
//! .await?;
//!
//! while let Some(change) = stream.next().await {
//! println!("Port: {} -> {}", change.old, change.new);
//! }
//! ```
// Re-exports from macros
pub use ;
// Re-exports from sub-crates
pub use ;
pub use ;
// Reactive module (feature-gated)
pub use ;
// Re-export validator for convenience
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// Common imports for convenience.
/// Load configuration for an application.
///
/// This is a convenience function for simple use cases.
/// Requires `Config` trait which is implemented by the `Config` derive macro.
///
/// # Example
///
/// ```ignore
/// use cfgmatic::{Config, load};
/// use serde::Deserialize;
///
/// #[derive(Debug, Default, Deserialize, Config)]
/// struct MyConfig {
/// name: String,
/// }
///
/// match load::<MyConfig>("myapp") {
/// Ok(config) => println!("Loaded: {:?}", config),
/// Err(e) => eprintln!("Failed to load: {}", e),
/// }
/// ```
///
/// # Errors
///
/// Returns an error if no configuration is found or if parsing fails.
/// Check if configuration exists for an application.
///
/// # Example
///
/// ```
/// use cfgmatic::exists;
///
/// if exists("myapp") {
/// println!("Configuration found!");
/// }
/// ```
/// Load configuration from environment variables only.
///
/// # Example
///
/// ```
/// use cfgmatic::{load_from_env, Config, ConfigLoader};
/// use serde::Deserialize;
///
/// #[derive(Debug, Deserialize, Config)]
/// #[config(prefix = "MYAPP")]
/// struct Config {
/// port: u16,
/// }
///
/// // std::env::set_var("MYAPP__PORT", "8080");
/// // let config: Config = load_from_env().unwrap();
/// ```
///
/// # Errors
///
/// Returns an error if environment variables cannot be parsed.
/// Parse a value from an environment variable string.
///
/// Supports common types like strings, numbers, bools.
///
/// # Example
///
/// ```
/// use cfgmatic::parse_env_value;
///
/// let port: u16 = parse_env_value("8080").unwrap();
/// let debug: bool = parse_env_value("true").unwrap();
/// ```
///
/// # Errors
///
/// Returns an error if the value cannot be parsed into the target type.
/// Build environment variable name from path components.
///
/// Uses double underscore (`__`) as separator, following NPM convention.
///
/// # Example
///
/// ```
/// use cfgmatic::build_env_name;
///
/// let name = build_env_name("MYAPP", &["database", "url"]);
/// assert_eq!(name, "MYAPP__DATABASE__URL");
/// ```
/// Discover configuration locations for an application.
///
/// Returns comprehensive diagnostic information about configuration
/// locations without actually loading the configuration.
///
/// # Example
///
/// ```
/// use cfgmatic::discover_config;
///
/// let discovery = discover_config("myapp");
///
/// println!("Config would be at: {}", discovery.preferred_path.display());
/// if let Some(found) = &discovery.found_path {
/// println!("Found existing config at: {}", found.display());
/// }
///
/// for candidate in discovery.candidates {
/// println!(" - {:?}: {} ({:?})",
/// candidate.tier,
/// candidate.path.display(),
/// candidate.status
/// );
/// }
/// ```
/// Get the preferred configuration path for an application.
///
/// Returns the path where configuration would be created,
/// without checking if it exists.
///
/// # Example
///
/// ```
/// use cfgmatic::config_path;
///
/// let path = config_path("myapp");
/// println!("Config location: {}", path.display());
/// ```
/// Get the preferred configuration file path for an application.
///
/// # Example
///
/// ```
/// use cfgmatic::config_file_path;
///
/// let path = config_file_path("myapp", "config.toml");
/// println!("Config file: {}", path.display());
/// ```