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;
29
30/// Result type used by the high-level configuration API.
31///
32/// The error type is [`ConfigError`](crate::error::ConfigError).
33pub type ConfigResult<T> = std::result::Result<T, crate::error::ConfigError>;
34
35/// A `confique` schema that can expose recursive include paths and template
36/// section layout.
37///
38/// Implement this trait for the same type that derives `confique::Config`.
39/// `include_paths` receives a partially loaded layer so the crate can discover
40/// child config files before the final schema is merged.
41pub trait ConfigSchema: Config + Sized {
42 /// Returns include paths declared by a loaded config layer.
43 ///
44 /// Relative paths are resolved from the file that declared them. Empty paths
45 /// are rejected before traversal continues.
46 ///
47 /// # Arguments
48 ///
49 /// - `layer`: Partially loaded `confique` layer for one config file.
50 ///
51 /// # Returns
52 ///
53 /// Returns include paths declared by `layer`.
54 ///
55 /// # Examples
56 ///
57 /// ```
58 /// use confique::Config;
59 /// use rust_config_tree::config::ConfigSchema;
60 ///
61 /// #[derive(Config)]
62 /// struct AppConfig {
63 /// #[config(default = [])]
64 /// include: Vec<std::path::PathBuf>,
65 /// }
66 ///
67 /// impl ConfigSchema for AppConfig {
68 /// fn include_paths(layer: &<Self as Config>::Layer) -> Vec<std::path::PathBuf> {
69 /// layer.include.clone().unwrap_or_default()
70 /// }
71 /// }
72 /// ```
73 fn include_paths(layer: &<Self as Config>::Layer) -> Vec<PathBuf>;
74
75 /// Overrides the generated template file path for a split nested section.
76 ///
77 /// A nested section is split only when its field schema has
78 /// `x-tree-split = true`, for example
79 /// `#[schemars(extend("x-tree-split" = true))]`. By default, top-level
80 /// split sections are generated as `<field>.yaml` relative to the root
81 /// template directory and nested split sections as children of their
82 /// parent section file stem, e.g. `trading/risk.yaml`.
83 ///
84 /// # Arguments
85 ///
86 /// - `section_path`: Path of nested schema field names from the root schema
87 /// to the section being rendered.
88 ///
89 /// # Returns
90 ///
91 /// Returns `Some(path)` to override the generated file path, or `None` to
92 /// use the default section path.
93 ///
94 /// # Examples
95 ///
96 /// ```
97 /// use confique::Config;
98 /// use rust_config_tree::config::ConfigSchema;
99 ///
100 /// #[derive(Config)]
101 /// struct AppConfig {
102 /// #[config(default = [])]
103 /// include: Vec<std::path::PathBuf>,
104 /// }
105 ///
106 /// impl ConfigSchema for AppConfig {
107 /// fn include_paths(layer: &<Self as Config>::Layer) -> Vec<std::path::PathBuf> {
108 /// layer.include.clone().unwrap_or_default()
109 /// }
110 ///
111 /// fn template_path_for_section(section_path: &[&str]) -> Option<std::path::PathBuf> {
112 /// match section_path {
113 /// ["server"] => Some(std::path::PathBuf::from("config/server.yaml")),
114 /// _ => None,
115 /// }
116 /// }
117 /// }
118 /// ```
119 fn template_path_for_section(section_path: &[&str]) -> Option<PathBuf> {
120 let _ = section_path;
121 None
122 }
123}
124
125#[cfg(test)]
126#[path = "unit_tests/config.rs"]
127mod unit_tests;