Skip to main content

rust_config_tree/
config.rs

1//! High-level `confique` integration and generate-template rendering.
2//!
3//! This module loads `.env` values, builds a Figment runtime source graph,
4//! extracts it into a `confique` schema for defaults and validation, renders
5//! example templates that mirror the same include tree, and writes JSON Schema
6//! files that editors can use for completion and validation. YAML templates can
7//! also be split across nested schema sections.
8
9use std::path::PathBuf;
10
11use confique::Config;
12
13pub use crate::config_env::ConfiqueEnvProvider;
14pub use crate::config_format::ConfigFormat;
15pub use crate::config_load::{
16    build_config_figment, load_config, load_config_from_figment, load_config_with_figment,
17};
18pub(crate) use crate::config_output::default_config_schema_output;
19pub use crate::config_schema::target::ConfigSchemaTarget;
20pub use crate::config_schema::write::{
21    config_schema_targets_for_path, write_config_schema, write_config_schemas,
22};
23pub use crate::config_templates::{
24    ConfigTemplateTarget, template_for_path, template_targets_for_paths,
25    template_targets_for_paths_with_schema, write_config_templates,
26    write_config_templates_with_schema,
27};
28pub use crate::config_trace::trace_config_sources;
29pub use crate::config_load_adapt::TransparentSectionContext;
30pub use crate::transparent_section::ArraySection;
31
32/// Result type used by the high-level configuration API.
33///
34/// The error type is [`ConfigError`](crate::error::ConfigError).
35pub type ConfigResult<T> = std::result::Result<T, crate::error::ConfigError>;
36
37/// A `confique` schema that can expose recursive include paths and template
38/// section layout.
39///
40/// Implement this trait for the same type that derives `confique::Config`.
41/// `include_paths` receives a partially loaded layer so the crate can discover
42/// child config files before the final schema is merged.
43pub trait ConfigSchema: Config + Sized {
44    /// Returns include paths declared by a loaded config layer.
45    ///
46    /// Relative paths are resolved from the file that declared them. Empty paths
47    /// are rejected before traversal continues.
48    ///
49    /// # Arguments
50    ///
51    /// - `layer`: Partially loaded `confique` layer for one config file.
52    ///
53    /// # Returns
54    ///
55    /// Returns include paths declared by `layer`.
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// use confique::Config;
61    /// use rust_config_tree::config::ConfigSchema;
62    ///
63    /// #[derive(Config)]
64    /// struct AppConfig {
65    ///     #[config(default = [])]
66    ///     include: Vec<std::path::PathBuf>,
67    /// }
68    ///
69    /// impl ConfigSchema for AppConfig {
70    ///     fn include_paths(layer: &<Self as Config>::Layer) -> Vec<std::path::PathBuf> {
71    ///         layer.include.clone().unwrap_or_default()
72    ///     }
73    /// }
74    /// ```
75    fn include_paths(layer: &<Self as Config>::Layer) -> Vec<PathBuf>;
76
77    /// Overrides the generated template file path for a split nested section.
78    ///
79    /// A nested section is split only when its field schema has
80    /// `x-tree-split = true`, for example
81    /// `#[schemars(extend("x-tree-split" = true))]`. By default, top-level
82    /// split sections are generated as `<field>.yaml` relative to the root
83    /// template directory and nested split sections as children of their
84    /// parent section file stem, e.g. `trading/risk.yaml`.
85    ///
86    /// # Arguments
87    ///
88    /// - `section_path`: Path of nested schema field names from the root schema
89    ///   to the section being rendered.
90    ///
91    /// # Returns
92    ///
93    /// Returns `Some(path)` to override the generated file path, or `None` to
94    /// use the default section path.
95    ///
96    /// # Examples
97    ///
98    /// ```
99    /// use confique::Config;
100    /// use rust_config_tree::config::ConfigSchema;
101    ///
102    /// #[derive(Config)]
103    /// struct AppConfig {
104    ///     #[config(default = [])]
105    ///     include: Vec<std::path::PathBuf>,
106    /// }
107    ///
108    /// impl ConfigSchema for AppConfig {
109    ///     fn include_paths(layer: &<Self as Config>::Layer) -> Vec<std::path::PathBuf> {
110    ///         layer.include.clone().unwrap_or_default()
111    ///     }
112    ///
113    ///     fn template_path_for_section(section_path: &[&str]) -> Option<std::path::PathBuf> {
114    ///         match section_path {
115    ///             ["server"] => Some(std::path::PathBuf::from("config/server.yaml")),
116    ///             _ => None,
117    ///         }
118    ///     }
119    /// }
120    /// ```
121    fn template_path_for_section(section_path: &[&str]) -> Option<PathBuf> {
122        let _ = section_path;
123        None
124    }
125}
126
127#[cfg(test)]
128#[path = "unit_tests/config.rs"]
129mod unit_tests;