// Copyright 2019-2023 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! [![](https://github.com/tauri-apps/plugins-workspace/raw/v2/plugins/updater/banner.png)](https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/updater) //! //! In-app updates for Tauri applications. //! //! - Supported platforms: Windows, Linux and macOS.crypted database and secure runtime. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png" )] use std::ffi::OsString; use tauri::{ plugin::{Builder as PluginBuilder, TauriPlugin}, Manager, Runtime, }; mod commands; mod config; mod error; mod updater; pub use config::Config; pub use error::{Error, Result}; pub use updater::*; /// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the updater APIs. pub trait UpdaterExt { /// Gets the updater builder to build and updater /// that can manually check if an update is available. /// /// # Examples /// /// ```no_run /// use tauri_plugin_updater::UpdaterExt; /// tauri::Builder::default() /// .setup(|app| { /// let handle = app.handle().clone(); /// tauri::async_runtime::spawn(async move { /// let response = handle.updater_builder().build().unwrap().check().await; /// }); /// Ok(()) /// }); /// ``` fn updater_builder(&self) -> UpdaterBuilder; /// Gets the updater to manually check if an update is available. /// /// # Examples /// /// ```no_run /// use tauri_plugin_updater::UpdaterExt; /// tauri::Builder::default() /// .setup(|app| { /// let handle = app.handle().clone(); /// tauri::async_runtime::spawn(async move { /// let response = handle.updater().unwrap().check().await; /// }); /// Ok(()) /// }); /// ``` fn updater(&self) -> Result; } impl> UpdaterExt for T { fn updater_builder(&self) -> UpdaterBuilder { let app = self.app_handle(); let version = app.package_info().version.clone(); let UpdaterState { config, target } = self.state::().inner(); let mut builder = UpdaterBuilder::new(version, config.clone()); if let Some(target) = target { builder = builder.target(target); } let args = self.env().args_os; if !args.is_empty() { builder = builder.installer_arg("/ARGS").installer_args(args); } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] { let env = app.env(); if let Some(appimage) = env.appimage { builder = builder.executable_path(appimage); } } let app_handle = app.app_handle().clone(); builder = builder.on_before_exit(move || { app_handle.cleanup_before_exit(); }); builder } fn updater(&self) -> Result { self.updater_builder().build() } } struct UpdaterState { target: Option, config: Config, } #[derive(Default)] pub struct Builder { target: Option, pubkey: Option, installer_args: Vec, } impl Builder { pub fn new() -> Self { Self::default() } pub fn target(mut self, target: impl Into) -> Self { self.target.replace(target.into()); self } pub fn pubkey>(mut self, pubkey: S) -> Self { self.pubkey.replace(pubkey.into()); self } pub fn installer_args(mut self, args: I) -> Self where I: IntoIterator, S: Into, { let args = args.into_iter().map(|a| a.into()).collect::>(); self.installer_args.extend_from_slice(&args); self } pub fn installer_arg(mut self, arg: S) -> Self where S: Into, { self.installer_args.push(arg.into()); self } pub fn clear_installer_args(mut self) -> Self { self.installer_args.clear(); self } pub fn build(self) -> TauriPlugin { let pubkey = self.pubkey; let target = self.target; let installer_args = self.installer_args; PluginBuilder::::new("updater") .setup(move |app, api| { let mut config = api.config().clone(); if let Some(pubkey) = pubkey { config.pubkey = pubkey; } if let Some(windows) = &mut config.windows { windows.installer_args.extend_from_slice(&installer_args); } app.manage(UpdaterState { target, config }); Ok(()) }) .invoke_handler(tauri::generate_handler![ commands::check, commands::download_and_install ]) .build() } }