use std::sync::LazyLock; use anyhow::Context; use clap::CommandFactory; use tauri::Emitter; mod introspect; mod modifiers; static INSTALLER_COMMAND: LazyLock = LazyLock::new(installer::Args::command); async fn run_installer(app_handle: tauri::AppHandle, args: String) -> anyhow::Result<()> { let args_vec = shlex::split(&args).context("Failed to parse arguments: unclosed quote")?; tauri::async_runtime::spawn_blocking(move || { installer::run_with_callback( args_vec.iter().map(|s| s.as_str()), Some(Box::new(move |output| { app_handle .emit("installer-output", output) .expect("Error sending Rayhunter CLI installer output to GUI frontend"); })), ) }) .await? } #[tauri::command] async fn install_rayhunter(app_handle: tauri::AppHandle, args: String) -> Result<(), String> { // the return value of tauri commands needs to be serializable by serde which we accomplish // here by converting anyhow::Error to a string run_installer(app_handle, args) .await .map_err(|error| format!("{error:?}")) } #[tauri::command] fn rayhunter_options() -> introspect::Command<'static> { introspect::Command::new(&INSTALLER_COMMAND) } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .invoke_handler(tauri::generate_handler![install_rayhunter]) .invoke_handler(tauri::generate_handler![rayhunter_options]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }