tauri_plugin_typegen/interface/
output.rs1use std::fmt;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum LogLevel {
5 Error,
6 Warning,
7 Info,
8 Debug,
9 Verbose,
10}
11
12impl fmt::Display for LogLevel {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 match self {
15 LogLevel::Error => write!(f, "ERROR"),
16 LogLevel::Warning => write!(f, "WARN"),
17 LogLevel::Info => write!(f, "INFO"),
18 LogLevel::Debug => write!(f, "DEBUG"),
19 LogLevel::Verbose => write!(f, "VERBOSE"),
20 }
21 }
22}
23
24#[derive(Debug, Clone)]
25pub struct Logger {
26 verbose: bool,
27 debug: bool,
28}
29
30impl Logger {
31 pub fn new(verbose: bool, debug: bool) -> Self {
32 Self { verbose, debug }
33 }
34
35 pub fn should_log(&self, level: LogLevel) -> bool {
36 match level {
37 LogLevel::Error | LogLevel::Warning | LogLevel::Info => true,
38 LogLevel::Debug => self.debug || self.verbose,
39 LogLevel::Verbose => self.verbose,
40 }
41 }
42
43 pub fn log(&self, level: LogLevel, message: &str) {
44 if self.should_log(level) {
45 let icon = match level {
46 LogLevel::Error => "❌",
47 LogLevel::Warning => "⚠️",
48 LogLevel::Info => "ℹ️",
49 LogLevel::Debug => "🔍",
50 LogLevel::Verbose => "💬",
51 };
52 println!("{} {}", icon, message);
53 }
54 }
55
56 pub fn error(&self, message: &str) {
57 self.log(LogLevel::Error, message);
58 }
59
60 pub fn warning(&self, message: &str) {
61 self.log(LogLevel::Warning, message);
62 }
63
64 pub fn info(&self, message: &str) {
65 self.log(LogLevel::Info, message);
66 }
67
68 pub fn debug(&self, message: &str) {
69 self.log(LogLevel::Debug, message);
70 }
71
72 pub fn verbose(&self, message: &str) {
73 self.log(LogLevel::Verbose, message);
74 }
75}
76
77pub struct ProgressReporter {
78 logger: Logger,
79 current_step: usize,
80 total_steps: usize,
81 step_name: String,
82}
83
84impl ProgressReporter {
85 pub fn new(logger: Logger, total_steps: usize) -> Self {
86 Self {
87 logger,
88 current_step: 0,
89 total_steps,
90 step_name: String::new(),
91 }
92 }
93
94 pub fn start_step(&mut self, step_name: &str) {
95 self.current_step += 1;
96 self.step_name = step_name.to_string();
97
98 if self.logger.should_log(LogLevel::Info) {
99 let progress = if self.total_steps > 0 {
100 format!(" ({}/{})", self.current_step, self.total_steps)
101 } else {
102 String::new()
103 };
104 self.logger.info(&format!("🚀 {}{}", step_name, progress));
105 }
106 }
107
108 pub fn complete_step(&self, message: Option<&str>) {
109 if let Some(msg) = message {
110 self.logger
111 .info(&format!("✅ {} - {}", self.step_name, msg));
112 } else {
113 self.logger.info(&format!("✅ {}", self.step_name));
114 }
115 }
116
117 pub fn fail_step(&self, error: &str) {
118 self.logger
119 .error(&format!("Failed {}: {}", self.step_name, error));
120 }
121
122 pub fn update_progress(&self, message: &str) {
123 self.logger.verbose(&format!(" → {}", message));
124 }
125
126 pub fn finish(&self, total_message: &str) {
127 self.logger.info(&format!("🎉 {}", total_message));
128 }
129}
130
131pub fn print_usage_info(output_path: &str, generated_files: &[String]) {
132 println!("\n💡 Usage in your frontend:");
133 for file in generated_files {
134 if file.ends_with("index.ts") || file.ends_with("index.js") {
135 println!(
136 " import {{ /* your commands */ }} from '{}/{}'",
137 output_path.trim_end_matches('/'),
138 file.trim_end_matches(".ts").trim_end_matches(".js")
139 );
140 break;
141 }
142 }
143
144 println!("\n📁 Generated files:");
145 for file in generated_files {
146 println!(" 📄 {}/{}", output_path, file);
147 }
148}
149
150pub fn print_dependency_visualization_info(output_path: &str) {
151 println!("\n🌐 Dependency visualization generated:");
152 println!(" 📄 {}/dependency-graph.txt", output_path);
153 println!(" 📄 {}/dependency-graph.dot", output_path);
154 println!(
155 "\n💡 To generate a visual graph: dot -Tpng {}/dependency-graph.dot -o graph.png",
156 output_path
157 );
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn test_logger_verbose_mode() {
166 let logger = Logger::new(true, false);
167 assert!(logger.should_log(LogLevel::Verbose));
168 assert!(logger.should_log(LogLevel::Info));
169 assert!(logger.should_log(LogLevel::Error));
170 assert!(logger.should_log(LogLevel::Debug)); }
172
173 #[test]
174 fn test_logger_normal_mode() {
175 let logger = Logger::new(false, false);
176 assert!(!logger.should_log(LogLevel::Verbose));
177 assert!(!logger.should_log(LogLevel::Debug));
178 assert!(logger.should_log(LogLevel::Info));
179 assert!(logger.should_log(LogLevel::Error));
180 }
181
182 #[test]
183 fn test_logger_debug_mode() {
184 let logger = Logger::new(false, true);
185 assert!(!logger.should_log(LogLevel::Verbose));
186 assert!(logger.should_log(LogLevel::Debug));
187 assert!(logger.should_log(LogLevel::Info));
188 }
189
190 #[test]
191 fn test_progress_reporter() {
192 let logger = Logger::new(false, false);
193 let mut reporter = ProgressReporter::new(logger, 3);
194
195 assert_eq!(reporter.current_step, 0);
197
198 reporter.start_step("First Step");
199 assert_eq!(reporter.current_step, 1);
200 assert_eq!(reporter.step_name, "First Step");
201
202 reporter.start_step("Second Step");
203 assert_eq!(reporter.current_step, 2);
204 assert_eq!(reporter.step_name, "Second Step");
205 }
206}