1use serde::{Deserialize, Serialize};
6
7use crate::model::EventType;
8
9macro_rules! define_hooks_config {
15 ($($field:ident => $variant:ident),* $(,)?) => {
16 #[derive(Debug, Clone, Serialize, Deserialize)]
17 #[serde(rename_all = "PascalCase")]
18 pub struct HooksConfig {
19 $(
20 #[serde(default = "default_true")]
21 pub $field: bool,
22 )*
23 }
24
25 impl Default for HooksConfig {
26 fn default() -> Self {
27 Self {
28 $($field: true,)*
29 }
30 }
31 }
32
33 impl HooksConfig {
34 pub fn enabled_hooks(&self) -> Vec<EventType> {
36 let mut hooks = Vec::new();
37 $(
38 if self.$field {
39 hooks.push(EventType::$variant);
40 }
41 )*
42 hooks
43 }
44 }
45 };
46}
47
48define_hooks_config! {
49 session_start => SessionStart,
50 session_end => SessionEnd,
51 user_prompt_submit => UserPromptSubmit,
52 stop => Stop,
53 subagent_start => SubagentStart,
54 subagent_stop => SubagentStop,
55 notification => Notification,
56 permission_request => PermissionRequest,
57 pre_compact => PreCompact,
58 pre_tool_use => PreToolUse,
59 post_tool_use => PostToolUse,
60}
61
62fn default_true() -> bool {
63 true
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_enabled_hooks_returns_all_event_types() {
72 let config = HooksConfig::default();
73 let hooks = config.enabled_hooks();
74
75 assert!(hooks.contains(&EventType::SessionStart));
77 assert!(hooks.contains(&EventType::SessionEnd));
78 assert!(hooks.contains(&EventType::UserPromptSubmit));
79 assert!(hooks.contains(&EventType::Stop));
80 assert!(hooks.contains(&EventType::SubagentStart));
81 assert!(hooks.contains(&EventType::SubagentStop));
82 assert!(hooks.contains(&EventType::Notification));
83 assert!(hooks.contains(&EventType::PermissionRequest));
84 assert!(hooks.contains(&EventType::PreCompact));
85 assert!(hooks.contains(&EventType::PreToolUse));
86 assert!(hooks.contains(&EventType::PostToolUse));
87
88 assert_eq!(hooks.len(), 11);
90 }
91
92 #[test]
93 fn test_enabled_hooks_respects_disabled_hooks() {
94 let config = HooksConfig {
95 session_start: false,
96 pre_tool_use: false,
97 ..Default::default()
98 };
99
100 let hooks = config.enabled_hooks();
101 assert_eq!(hooks.len(), 9);
103 assert!(!hooks.contains(&EventType::SessionStart));
104 assert!(!hooks.contains(&EventType::PreToolUse));
105 assert!(hooks.contains(&EventType::SessionEnd));
106 }
107}