ricecoder_hooks/cli/
mod.rs

1//! CLI commands for hook management
2//!
3//! This module provides command-line interface commands for managing hooks,
4//! including listing, inspecting, enabling, disabling, and deleting hooks.
5
6pub mod commands;
7pub mod formatter;
8
9pub use commands::{delete_hook, disable_hook, enable_hook, inspect_hook, list_hooks, HookCommand};
10pub use formatter::{format_hook_json, format_hook_table, format_hooks_json, format_hooks_table};
11
12use crate::error::Result;
13use crate::registry::HookRegistry;
14
15/// Hook management CLI interface
16pub struct HookCli<R: HookRegistry> {
17    registry: R,
18}
19
20impl<R: HookRegistry> HookCli<R> {
21    /// Create a new hook CLI instance
22    pub fn new(registry: R) -> Self {
23        Self { registry }
24    }
25
26    /// Execute a hook command
27    pub fn execute(&mut self, command: HookCommand) -> Result<String> {
28        match command {
29            HookCommand::List { format } => {
30                let hooks = self.registry.list_hooks()?;
31                Ok(match format.as_deref() {
32                    Some("json") => format_hooks_json(&hooks)?,
33                    _ => format_hooks_table(&hooks),
34                })
35            }
36            HookCommand::Inspect { id, format } => {
37                let hook = self.registry.get_hook(&id)?;
38                Ok(match format.as_deref() {
39                    Some("json") => format_hook_json(&hook)?,
40                    _ => format_hook_table(&hook),
41                })
42            }
43            HookCommand::Enable { id } => {
44                self.registry.enable_hook(&id)?;
45                Ok(format!("Hook '{}' enabled", id))
46            }
47            HookCommand::Disable { id } => {
48                self.registry.disable_hook(&id)?;
49                Ok(format!("Hook '{}' disabled", id))
50            }
51            HookCommand::Delete { id } => {
52                self.registry.unregister_hook(&id)?;
53                Ok(format!("Hook '{}' deleted", id))
54            }
55        }
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62    use crate::registry::InMemoryHookRegistry;
63    use crate::types::{Action, CommandAction, Hook};
64
65    fn create_test_hook(id: &str, name: &str) -> Hook {
66        Hook {
67            id: id.to_string(),
68            name: name.to_string(),
69            description: Some("Test hook".to_string()),
70            event: "test_event".to_string(),
71            action: Action::Command(CommandAction {
72                command: "echo".to_string(),
73                args: vec!["test".to_string()],
74                timeout_ms: Some(5000),
75                capture_output: true,
76            }),
77            enabled: true,
78            tags: vec!["test".to_string()],
79            metadata: serde_json::json!({}),
80            condition: None,
81        }
82    }
83
84    #[test]
85    fn test_list_hooks() {
86        let mut registry = InMemoryHookRegistry::new();
87        let hook1 = create_test_hook("hook1", "Hook 1");
88        let hook2 = create_test_hook("hook2", "Hook 2");
89
90        registry.register_hook(hook1).unwrap();
91        registry.register_hook(hook2).unwrap();
92
93        let mut cli = HookCli::new(registry);
94        let result = cli.execute(HookCommand::List { format: None }).unwrap();
95
96        assert!(result.contains("Hook 1"));
97        assert!(result.contains("Hook 2"));
98    }
99
100    #[test]
101    fn test_inspect_hook() {
102        let mut registry = InMemoryHookRegistry::new();
103        let hook = create_test_hook("hook1", "Hook 1");
104        registry.register_hook(hook).unwrap();
105
106        let mut cli = HookCli::new(registry);
107        let result = cli
108            .execute(HookCommand::Inspect {
109                id: "hook1".to_string(),
110                format: None,
111            })
112            .unwrap();
113
114        assert!(result.contains("Hook 1"));
115    }
116
117    #[test]
118    fn test_enable_hook() {
119        let mut registry = InMemoryHookRegistry::new();
120        let mut hook = create_test_hook("hook1", "Hook 1");
121        hook.enabled = false;
122        registry.register_hook(hook).unwrap();
123
124        let mut cli = HookCli::new(registry);
125        let result = cli
126            .execute(HookCommand::Enable {
127                id: "hook1".to_string(),
128            })
129            .unwrap();
130
131        assert!(result.contains("enabled"));
132    }
133
134    #[test]
135    fn test_disable_hook() {
136        let mut registry = InMemoryHookRegistry::new();
137        let hook = create_test_hook("hook1", "Hook 1");
138        registry.register_hook(hook).unwrap();
139
140        let mut cli = HookCli::new(registry);
141        let result = cli
142            .execute(HookCommand::Disable {
143                id: "hook1".to_string(),
144            })
145            .unwrap();
146
147        assert!(result.contains("disabled"));
148    }
149
150    #[test]
151    fn test_delete_hook() {
152        let mut registry = InMemoryHookRegistry::new();
153        let hook = create_test_hook("hook1", "Hook 1");
154        registry.register_hook(hook).unwrap();
155
156        let mut cli = HookCli::new(registry);
157        let result = cli
158            .execute(HookCommand::Delete {
159                id: "hook1".to_string(),
160            })
161            .unwrap();
162
163        assert!(result.contains("deleted"));
164    }
165}