cuenv_core/manifest/
mod.rs

1//! Root Cuenv configuration type
2//!
3//! Based on schema/cuenv.cue
4
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9use crate::config::Config;
10use crate::environment::Env;
11use crate::hooks::Hook;
12use crate::tasks::TaskDefinition;
13
14/// Workspace configuration
15#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
16#[serde(rename_all = "camelCase")]
17pub struct WorkspaceConfig {
18    /// Enable or disable the workspace
19    #[serde(default = "default_true")]
20    pub enabled: bool,
21
22    /// Optional: manually specify the root of the workspace relative to env.cue
23    pub root: Option<String>,
24
25    /// Optional: manually specify the package manager
26    pub package_manager: Option<String>,
27}
28
29fn default_true() -> bool {
30    true
31}
32
33/// Collection of hooks that can be executed
34#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
35pub struct Hooks {
36    /// Named hooks to execute when entering an environment (map of name -> hook)
37    #[serde(skip_serializing_if = "Option::is_none")]
38    #[serde(rename = "onEnter")]
39    pub on_enter: Option<HashMap<String, Hook>>,
40
41    /// Named hooks to execute when exiting an environment (map of name -> hook)
42    #[serde(skip_serializing_if = "Option::is_none")]
43    #[serde(rename = "onExit")]
44    pub on_exit: Option<HashMap<String, Hook>>,
45}
46
47/// Root Cuenv configuration structure
48#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
49pub struct Cuenv {
50    /// Configuration settings
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub config: Option<Config>,
53
54    /// Environment variables configuration
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub env: Option<Env>,
57
58    /// Hooks configuration
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub hooks: Option<Hooks>,
61
62    /// Workspaces configuration
63    #[serde(skip_serializing_if = "Option::is_none")]
64    pub workspaces: Option<HashMap<String, WorkspaceConfig>>,
65
66    /// Tasks configuration
67    #[serde(default)]
68    pub tasks: HashMap<String, TaskDefinition>,
69}
70
71impl Cuenv {
72    /// Create a new empty Cuenv configuration
73    pub fn new() -> Self {
74        Self::default()
75    }
76
77    /// Get hooks to execute when entering environment as a map (name -> hook)
78    pub fn on_enter_hooks_map(&self) -> HashMap<String, Hook> {
79        self.hooks
80            .as_ref()
81            .and_then(|h| h.on_enter.as_ref())
82            .cloned()
83            .unwrap_or_default()
84    }
85
86    /// Get hooks to execute when entering environment, sorted by (order, name)
87    pub fn on_enter_hooks(&self) -> Vec<Hook> {
88        let map = self.on_enter_hooks_map();
89        let mut hooks: Vec<(String, Hook)> = map.into_iter().collect();
90        hooks.sort_by(|a, b| a.1.order.cmp(&b.1.order).then(a.0.cmp(&b.0)));
91        hooks.into_iter().map(|(_, h)| h).collect()
92    }
93
94    /// Get hooks to execute when exiting environment as a map (name -> hook)
95    pub fn on_exit_hooks_map(&self) -> HashMap<String, Hook> {
96        self.hooks
97            .as_ref()
98            .and_then(|h| h.on_exit.as_ref())
99            .cloned()
100            .unwrap_or_default()
101    }
102
103    /// Get hooks to execute when exiting environment, sorted by (order, name)
104    pub fn on_exit_hooks(&self) -> Vec<Hook> {
105        let map = self.on_exit_hooks_map();
106        let mut hooks: Vec<(String, Hook)> = map.into_iter().collect();
107        hooks.sort_by(|a, b| a.1.order.cmp(&b.1.order).then(a.0.cmp(&b.0)));
108        hooks.into_iter().map(|(_, h)| h).collect()
109    }
110}