Skip to main content

cuenv_core/config/
mod.rs

1//! Configuration types for cuenv
2//!
3//! Based on schema/config.cue
4
5use serde::{Deserialize, Serialize};
6
7/// Main configuration structure for cuenv
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
9#[serde(rename_all = "camelCase")]
10pub struct Config {
11    /// Task output format (for task execution)
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub output_format: Option<OutputFormat>,
14
15    /// Command-specific configuration
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub commands: Option<CommandsConfig>,
18
19    /// Cache configuration
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub cache_mode: Option<CacheMode>,
22
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub cache_enabled: Option<bool>,
25
26    /// Security and debugging
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub audit_mode: Option<bool>,
29
30    /// Chrome trace generation
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub trace_output: Option<bool>,
33
34    /// Default environment settings
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub default_environment: Option<String>,
37
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub default_capabilities: Option<Vec<String>>,
40
41    /// Task backend configuration
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub backend: Option<BackendConfig>,
44
45    /// CI-specific configuration
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub ci: Option<CIConfig>,
48}
49
50/// Command-specific configuration
51#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
52#[serde(rename_all = "camelCase")]
53pub struct CommandsConfig {
54    /// Task command configuration
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub task: Option<TaskCommandConfig>,
57}
58
59/// Task command configuration
60#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
61#[serde(rename_all = "camelCase")]
62pub struct TaskCommandConfig {
63    /// Task list configuration (for `cuenv task` without arguments)
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub list: Option<TaskListConfig>,
66}
67
68/// Task list display configuration
69#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
70#[serde(rename_all = "camelCase")]
71pub struct TaskListConfig {
72    /// Output format for task listing
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub format: Option<TaskListFormat>,
75}
76
77impl Config {
78    /// Get the configured task list format, if any.
79    ///
80    /// Accesses `config.commands.task.list.format` with safe navigation.
81    #[must_use]
82    pub fn task_list_format(&self) -> Option<TaskListFormat> {
83        self.commands
84            .as_ref()
85            .and_then(|c| c.task.as_ref())
86            .and_then(|t| t.list.as_ref())
87            .and_then(|l| l.format)
88    }
89}
90
91/// CI-specific configuration
92#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
93#[serde(rename_all = "camelCase")]
94pub struct CIConfig {
95    /// Cuenv installation configuration
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub cuenv: Option<CuenvConfig>,
98}
99
100/// Configuration for cuenv installation in CI
101#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
102#[serde(rename_all = "camelCase")]
103pub struct CuenvConfig {
104    /// Source for cuenv binary
105    #[serde(default)]
106    pub source: CuenvSource,
107
108    /// Version to install ("self", "latest", or specific version like "0.17.0")
109    #[serde(default = "default_cuenv_version")]
110    pub version: String,
111}
112
113fn default_cuenv_version() -> String {
114    "self".to_string()
115}
116
117impl Default for CuenvConfig {
118    fn default() -> Self {
119        Self {
120            source: CuenvSource::Release,
121            version: default_cuenv_version(),
122        }
123    }
124}
125
126/// Source for cuenv binary in CI environments
127#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
128#[serde(rename_all = "lowercase")]
129pub enum CuenvSource {
130    /// Build using native Rust/Go toolchains (no Nix)
131    Native,
132    /// Use pre-built artifact from earlier CI job
133    Artifact,
134    /// Build from git checkout (requires Nix)
135    Git,
136    /// Install via Nix flake (auto-configures Cachix)
137    Nix,
138    /// Install via Homebrew tap (no Nix required)
139    Homebrew,
140    /// Download from GitHub Releases (default)
141    #[default]
142    Release,
143}
144
145impl CuenvSource {
146    /// Get the string representation for activation condition matching
147    #[must_use]
148    pub const fn as_str(&self) -> &'static str {
149        match self {
150            Self::Native => "native",
151            Self::Artifact => "artifact",
152            Self::Git => "git",
153            Self::Nix => "nix",
154            Self::Homebrew => "homebrew",
155            Self::Release => "release",
156        }
157    }
158}
159
160/// Task output format options (for task execution)
161#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
162#[serde(rename_all = "lowercase")]
163pub enum OutputFormat {
164    Tui,
165    Spinner,
166    Simple,
167    Tree,
168    Json,
169}
170
171/// Task list format options (for `cuenv task` without arguments)
172#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
173#[serde(rename_all = "lowercase")]
174pub enum TaskListFormat {
175    /// Plain tree structure (default for non-TTY)
176    Text,
177    /// Colored tree structure (default for TTY)
178    Rich,
179    /// Category-grouped bordered tables
180    Tables,
181    /// Status dashboard with cache indicators
182    Dashboard,
183    /// Emoji-prefixed semantic categories
184    Emoji,
185}
186
187impl TaskListFormat {
188    /// Convert to the string representation used by the task command
189    #[must_use]
190    pub const fn as_str(&self) -> &'static str {
191        match self {
192            Self::Text => "text",
193            Self::Rich => "rich",
194            Self::Tables => "tables",
195            Self::Dashboard => "dashboard",
196            Self::Emoji => "emoji",
197        }
198    }
199}
200
201/// Cache mode options
202#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
203#[serde(rename_all = "kebab-case")]
204pub enum CacheMode {
205    Off,
206    Read,
207    ReadWrite,
208    Write,
209}
210
211fn default_backend_type() -> String {
212    "host".to_string()
213}
214
215/// Backend configuration
216#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
217pub struct BackendConfig {
218    /// Which backend to use for tasks
219    #[serde(default = "default_backend_type", rename = "type")]
220    pub backend_type: String,
221
222    /// Backend-specific options
223    #[serde(skip_serializing_if = "Option::is_none")]
224    pub options: Option<BackendOptions>,
225}
226
227/// Backend-specific options supported by cuenv
228#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
229pub struct BackendOptions {
230    /// Default container image for the Dagger backend
231    #[serde(skip_serializing_if = "Option::is_none")]
232    pub image: Option<String>,
233
234    /// Optional platform hint for the Dagger backend
235    #[serde(skip_serializing_if = "Option::is_none")]
236    pub platform: Option<String>,
237}