tauri_plugin_typegen/interface/
mod.rs

1pub mod cli;
2pub mod config;
3pub mod output;
4
5use crate::analysis::CommandAnalyzer;
6use crate::generators::generator::BindingsGenerator;
7
8pub use cli::*;
9pub use config::*;
10pub use output::*;
11
12/// Generate TypeScript bindings from configuration (backward compatibility function)
13pub fn generate_from_config(
14    config: &config::GenerateConfig,
15) -> Result<Vec<String>, Box<dyn std::error::Error>> {
16    let logger = output::Logger::new(config.is_verbose(), false);
17
18    if config.is_verbose() {
19        logger.info(&format!(
20            "🔍 Analyzing Tauri commands in: {}",
21            config.project_path
22        ));
23    }
24
25    // Validate configuration
26    config
27        .validate()
28        .map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?;
29
30    // Analyze commands with struct discovery
31    let mut analyzer = CommandAnalyzer::new();
32    let commands = analyzer.analyze_project(&config.project_path)?;
33
34    if config.is_verbose() {
35        logger.info(&format!("📋 Found {} Tauri commands:", commands.len()));
36        for cmd in &commands {
37            logger.verbose(&format!("  - {} ({})", cmd.name, cmd.file_path));
38        }
39
40        let discovered_structs = analyzer.get_discovered_structs();
41        logger.info(&format!(
42            "đŸ—ī¸  Found {} struct definitions:",
43            discovered_structs.len()
44        ));
45        for (name, struct_info) in discovered_structs {
46            let struct_type = if struct_info.is_enum {
47                "enum"
48            } else {
49                "struct"
50            };
51            logger.verbose(&format!(
52                "  - {} ({}) with {} fields",
53                name,
54                struct_type,
55                struct_info.fields.len()
56            ));
57            for field in &struct_info.fields {
58                let visibility = if field.is_public { "pub" } else { "private" };
59                let optional = if field.is_optional { "?" } else { "" };
60                logger.verbose(&format!(
61                    "    â€ĸ {}{}: {} ({})",
62                    field.name, optional, field.typescript_type, visibility
63                ));
64            }
65        }
66
67        if discovered_structs.is_empty() {
68            logger.info("  â„šī¸  No custom struct definitions found in the project");
69        }
70    }
71
72    if commands.is_empty() {
73        if config.is_verbose() {
74            logger.warning("âš ī¸  No Tauri commands found. Make sure your project contains functions with #[tauri::command] attributes.");
75        }
76        return Ok(vec![]);
77    }
78
79    // Validate validation library
80    let validation = match config.validation_library.as_str() {
81        "zod" | "none" => Some(config.validation_library.clone()),
82        _ => {
83            return Err("Invalid validation library. Use 'zod' or 'none'".into());
84        }
85    };
86
87    if config.is_verbose() {
88        logger.info(&format!(
89            "🚀 Generating TypeScript models with {} validation...",
90            validation.as_ref().unwrap()
91        ));
92    }
93
94    // Generate TypeScript models with discovered structs
95    let mut generator = BindingsGenerator::new(validation);
96    let generated_files = generator.generate_models(
97        &commands,
98        analyzer.get_discovered_structs(),
99        &config.output_path,
100        &analyzer,
101    )?;
102
103    if config.is_verbose() {
104        logger.info(&format!(
105            "✅ Successfully generated {} files for {} commands:",
106            generated_files.len(),
107            commands.len()
108        ));
109        for file in &generated_files {
110            logger.verbose(&format!("  📄 {}/{}", config.output_path, file));
111        }
112    }
113
114    Ok(generated_files)
115}