From bf2809393a50de6322987e32df951f9e9431a238 Mon Sep 17 00:00:00 2001 From: Jonas Kruckenberg Date: Tue, 15 Nov 2022 18:06:28 +0100 Subject: [PATCH 1/2] feat: add path module --- Cargo.toml | 3 +- README.md | 2 +- src/lib.rs | 2 + src/notification.rs | 2 - src/path.rs | 739 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 744 insertions(+), 4 deletions(-) create mode 100644 src/path.rs diff --git a/Cargo.toml b/Cargo.toml index f80edfe..593722e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ tauri-sys = { path = ".", features = ["all"] } all-features = true [features] -all = ["app", "clipboard", "event", "mocks", "tauri", "window", "process", "dialog", "os", "notification"] +all = ["app", "clipboard", "event", "mocks", "tauri", "window", "process", "dialog", "os", "notification", "path"] app = ["dep:semver"] clipboard = [] dialog = [] @@ -36,6 +36,7 @@ window = [] process = [] os = ["dep:semver"] notification = [] +path = [] [workspace] members = ["examples/test", "examples/test/src-tauri"] diff --git a/README.md b/README.md index 36d00e2..319604e 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ These API bindings are not completely on-par with `@tauri-apps/api` yet, but her - [x] `mocks` - [x] `notification` - [x] `os` -- [ ] `path` +- [x] `path` - [x] `process` - [ ] `shell` - [x] `tauri` diff --git a/src/lib.rs b/src/lib.rs index 465614e..1fa38d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,8 @@ pub mod window; pub mod notification; #[cfg(feature = "os")] pub mod os; +#[cfg(feature = "path")] +pub mod path; #[derive(Debug, thiserror::Error)] pub enum Error { diff --git a/src/notification.rs b/src/notification.rs index 7391b88..5cf0300 100644 --- a/src/notification.rs +++ b/src/notification.rs @@ -1,6 +1,4 @@ -use log::debug; use serde::{Deserialize, Serialize}; -use wasm_bindgen::JsValue; pub async fn is_permission_granted() -> crate::Result { let raw = inner::isPermissionGranted().await?; diff --git a/src/path.rs b/src/path.rs new file mode 100644 index 0000000..93d9428 --- /dev/null +++ b/src/path.rs @@ -0,0 +1,739 @@ +use std::path::PathBuf; +use wasm_bindgen::JsValue; + +/// Returns the path to the suggested directory for your app's config files. +/// Resolves to `${configDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::app_config_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let app_config_dir_path = app_config_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn app_config_dir() -> crate::Result { + let raw = inner::appConfigDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the suggested directory for your app's data files. +/// Resolves to `${dataDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::app_data_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let app_data_dir_path = app_data_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn app_data_dir() -> crate::Result { + let raw = inner::appDataDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the suggested directory for your app's local data files. +/// Resolves to `${localDataDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::app_local_data_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let app_local_data_dir_path = app_local_data_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn app_local_data_dir() -> crate::Result { + let raw = inner::appLocalDataDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the suggested directory for your app's cache files. +/// Resolves to `${cacheDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::app_cache_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let app_cache_dir_path = app_cache_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn app_cache_dir() -> crate::Result { + let raw = inner::appCacheDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's audio directory. +/// +/// #### Platform-specific +/// +/// -///*Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_MUSIC_DIR`. +/// -///*macOS:** Resolves to `$HOME/Music`. +/// -///*Windows:** Resolves to `{FOLDERID_Music}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::audio_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let audio_dir_path = audio_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn audio_dir() -> crate::Result { + let raw = inner::audioDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's cache directory. +/// +/// #### Platform-specific +/// +/// -///*Linux:** Resolves to `$XDG_CACHE_HOME` or `$HOME/.cache`. +/// -///*macOS:** Resolves to `$HOME/Library/Caches`. +/// -///*Windows:** Resolves to `{FOLDERID_LocalAppData}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::cache_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let cache_dir_path = cache_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn cache_dir() -> crate::Result { + let raw = inner::cacheDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's config directory. +/// +/// #### Platform-specific +/// +/// -///*Linux:** Resolves to `$XDG_CONFIG_HOME` or `$HOME/.config`. +/// -///*macOS:** Resolves to `$HOME/Library/Application Support`. +/// -///*Windows:** Resolves to `{FOLDERID_RoamingAppData}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::config_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let config_dir_path = config_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn config_dir() -> crate::Result { + let raw = inner::configDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's data directory. +/// +/// #### Platform-specific +/// +/// -///*Linux:** Resolves to `$XDG_DATA_HOME` or `$HOME/.local/share`. +/// -///*macOS:** Resolves to `$HOME/Library/Application Support`. +/// -///*Windows:** Resolves to `{FOLDERID_RoamingAppData}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::data_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let data_dir_path = data_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn data_dir() -> crate::Result { + let raw = inner::dataDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's desktop directory. +/// +/// #### Platform-specific +/// +/// -///*Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DESKTOP_DIR`. +/// -///*macOS:** Resolves to `$HOME/Desktop`. +/// -///*Windows:** Resolves to `{FOLDERID_Desktop}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::desktop_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let desktop_dir_path = desktop_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn desktop_dir() -> crate::Result { + let raw = inner::desktopDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's document directory. +/// +/// #### Platform-specific +/// +/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DOCUMENTS_DIR`. +/// - **macOS:** Resolves to `$HOME/Documents`. +/// - **Windows:** Resolves to `{FOLDERID_Documents}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::document_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let document_dir_path = document_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn document_dir() -> crate::Result { + let raw = inner::documentDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's download directory. +/// +/// #### Platform-specific +/// +/// - **Linux**: Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DOWNLOAD_DIR`. +/// - **macOS**: Resolves to `$HOME/Downloads`. +/// - **Windows**: Resolves to `{FOLDERID_Downloads}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::download_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let download_dir_path = download_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn download_dir() -> crate::Result { + let raw = inner::downloadDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's executable directory. +/// +/// #### Platform-specific +/// +/// - **Linux:** Resolves to `$XDG_BIN_HOME/../bin` or `$XDG_DATA_HOME/../bin` or `$HOME/.local/bin`. +/// - **macOS:** Not supported. +/// - **Windows:** Not supported. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::executable_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let executable_dir_path = executable_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn executable_dir() -> crate::Result { + let raw = inner::executableDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's font directory. +/// +/// #### Platform-specific +/// +/// - **Linux:** Resolves to `$XDG_DATA_HOME/fonts` or `$HOME/.local/share/fonts`. +/// - **macOS:** Resolves to `$HOME/Library/Fonts`. +/// - **Windows:** Not supported. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::font_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let font_dir_path = font_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn font_dir() -> crate::Result { + let raw = inner::fontDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's home directory. +/// +/// #### Platform-specific +/// +/// - **Linux:** Resolves to `$HOME`. +/// - **macOS:** Resolves to `$HOME`. +/// - **Windows:** Resolves to `{FOLDERID_Profile}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::home_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let home_dir_path = home_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn home_dir() -> crate::Result { + let raw = inner::homeDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's local data directory. +/// +/// #### Platform-specific +/// +/// - **Linux:** Resolves to `$XDG_DATA_HOME` or `$HOME/.local/share`. +/// - **macOS:** Resolves to `$HOME/Library/Application Support`. +/// - **Windows:** Resolves to `{FOLDERID_LocalAppData}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::local_data_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let local_data_dir_path = local_data_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn local_data_dir() -> crate::Result { + let raw = inner::localDataDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's picture directory. +/// +/// #### Platform-specific +/// +/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_PICTURES_DIR`. +/// - **macOS:** Resolves to `$HOME/Pictures`. +/// - **Windows:** Resolves to `{FOLDERID_Pictures}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::picture_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let picture_dir_path = picture_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn picture_dir() -> crate::Result { + let raw = inner::pictureDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's public directory. +/// +/// #### Platform-specific +/// +/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_PUBLICSHARE_DIR`. +/// - **macOS:** Resolves to `$HOME/Public`. +/// - **Windows:** Resolves to `{FOLDERID_Public}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::public_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let public_dir_path = public_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn public_dir() -> crate::Result { + let raw = inner::publicDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the application's resource directory. +/// To resolve a resource path, see the [[resolveResource | `resolveResource API`]]. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::resource_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let resource_dir_path = resource_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn resource_dir() -> crate::Result { + let raw = inner::resourceDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Resolve the path to a resource file. +/// +/// @param resourcePath The path to the resource. +/// Must follow the same syntax as defined in `tauri.conf.json > tauri > bundle > resources`, i.e. keeping subfolders and parent dir components (`../`). +/// @returns The full path to the resource. +/// +/// ```rust,no_run +/// use tauri_sys::path::resolve_resource; +/// +/// # async fn main() -> Result<(), Box> { +/// let resource_path = resolve_resource("script.sh").await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn resolve_resource(resource_path: &str) -> crate::Result { + let raw = inner::resolveResource(JsValue::from_str(resource_path)).await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's runtime directory. +/// +/// #### Platform-specific +/// +/// -///*Linux:** Resolves to `$XDG_RUNTIME_DIR`. +/// -///*macOS:** Not supported. +/// -///*Windows:** Not supported. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::runtime_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let runtime_dir_path = runtime_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn runtime_dir() -> crate::Result { + let raw = inner::runtimeDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's template directory. +/// +/// #### Platform-specific +/// +/// -///*Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_TEMPLATES_DIR`. +/// -///*macOS:** Not supported. +/// -///*Windows:** Resolves to `{FOLDERID_Templates}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::template_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let template_dir_path = template_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn template_dir() -> crate::Result { + let raw = inner::templateDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the user's video directory. +/// +/// #### Platform-specific +/// +/// -///*Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_VIDEOS_DIR`. +/// -///*macOS:** Resolves to `$HOME/Movies`. +/// -///*Windows:** Resolves to `{FOLDERID_Videos}`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::video_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let video_dir_path = video_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn video_dir() -> crate::Result { + let raw = inner::videoDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the path to the suggested directory for your app's log files. +/// +/// #### Platform-specific +/// +/// - **Linux:** Resolves to `${configDir}/${bundleIdentifier}/logs`. +/// - **macOS:** Resolves to `${homeDir}/Library/Logs/{bundleIdentifier}` +/// - **Windows:** Resolves to `${configDir}/${bundleIdentifier}/logs`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::app_log_dir; +/// +/// # async fn main() -> Result<(), Box> { +/// let app_log_dir_path = app_log_dir().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn app_log_dir() -> crate::Result { + let raw = inner::appLogDir().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Resolves a sequence of `paths` or `path` segments into an absolute path. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::{resolve, app_data_dir}; +/// +/// # async fn main() -> Result<(), Box> { +/// let app_data_dir_path = app_data_dir().await?; +/// +/// let path = resolve([app_data_dir_path, "..", "users", "tauri", "avatar.png"]).await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn resolve(paths: impl IntoIterator) -> crate::Result { + let paths = paths.into_iter(); + let raw = inner::resolve(serde_wasm_bindgen::to_value(&paths.collect::>())?).await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Normalizes the given `path`, resolving `'..'` and `'.'` segments and resolve symbolic links. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::{normalize, app_data_dir}; +/// +/// # async fn main() -> Result<(), Box> { +/// let app_data_dir_path = app_data_dir().await?; +/// +/// let path = normalize([app_data_dir_path, "..", "users", "tauri", "avatar.png"]).await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn normalize(path: &str) -> crate::Result { + let raw = inner::normalize(JsValue::from_str(path)).await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Joins all given `path` segments together using the platform-specific separator as a delimiter, then normalizes the resulting path. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::{join, app_data_dir}; +/// +/// # async fn main() -> Result<(), Box> { +/// let app_data_dir_path = app_data_dir().await?; +/// +/// let path = join([app_data_dir_path, "..", "users", "tauri", "avatar.png"]).await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn join(paths: impl IntoIterator) -> crate::Result { + let paths = paths.into_iter(); + let raw = inner::join(serde_wasm_bindgen::to_value(&paths.collect::>())?).await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the directory name of a `path`. Trailing directory separators are ignored. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::{dirname, app_data_dir}; +/// +/// # async fn main() -> Result<(), Box> { +/// let app_data_dir_path = app_data_dir().await?; +/// +/// let dir = dirname(app_data_dir_path).await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn dirname(path: &str) -> crate::Result { + let raw = inner::dirname(JsValue::from_str(path)).await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the extension of the `path`. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::{extname, resolve_resource}; +/// +/// # async fn main() -> Result<(), Box> { +/// let resource_path = await resolve_resource("app.conf").await?; +/// let ext = extname(resource_path).await?; +/// assert_eq!(ext, "conf"); +/// # Ok(()) +/// # } +/// ``` +pub async fn extname(path: &str) -> crate::Result { + let raw = inner::extname(JsValue::from_str(path)).await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns the last portion of a `path`. Trailing directory separators are ignored. +/// +/// @param ext An optional file extension to be removed from the returned path. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::{basename, resolve_resource}; +/// +/// # async fn main() -> Result<(), Box> { +/// let resource_path = await resolve_resource("app.conf").await?; +/// let ext = basename(resource_path).await?; +/// assert_eq!(ext, "app"); +/// # Ok(()) +/// # } +/// ``` +pub async fn basename(path: &str, ext: Option<&str>) -> crate::Result { + let raw = inner::basename( + JsValue::from_str(path), + ext.map(JsValue::from_str).unwrap_or(JsValue::null()), + ) + .await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Returns whether the path is absolute or not. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::path::is_absolute; +/// +/// # async fn main() -> Result<(), Box> { +/// assert!(is_absolute("/home/tauri").await?); +/// # Ok(()) +/// # } +/// ``` +pub async fn is_absolute(path: &str) -> crate::Result { + let raw = inner::isAbsolute(JsValue::from_str(path)).await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +mod inner { + use wasm_bindgen::prelude::*; + + #[wasm_bindgen(module = "/src/path.js")] + extern "C" { + #[wasm_bindgen(catch)] + pub async fn appCacheDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn appConfigDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn appDataDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn appLocalDataDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn appLogDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn audioDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn basename(path: JsValue, ext: JsValue) -> Result; + #[wasm_bindgen(catch)] + pub async fn cacheDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn configDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn dataDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn desktopDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn dirname(path: JsValue) -> Result; + #[wasm_bindgen(catch)] + pub async fn documentDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn downloadDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn executableDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn extname(path: JsValue) -> Result; + #[wasm_bindgen(catch)] + pub async fn fontDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn homeDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn isAbsolute(path: JsValue) -> Result; + #[wasm_bindgen(catch)] + pub async fn join(paths: JsValue) -> Result; + #[wasm_bindgen(catch)] + pub async fn localDataDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn normalize(path: JsValue) -> Result; + #[wasm_bindgen(catch)] + pub async fn pictureDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn publicDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn resolve(paths: JsValue) -> Result; + #[wasm_bindgen(catch)] + pub async fn resolveResource(path: JsValue) -> Result; + #[wasm_bindgen(catch)] + pub async fn resourceDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn runtimeDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn templateDir() -> Result; + #[wasm_bindgen(catch)] + pub async fn videoDir() -> Result; + } +} From 17df08297c781393fe95a31e4d5f70430734705b Mon Sep 17 00:00:00 2001 From: Jonas Kruckenberg Date: Wed, 16 Nov 2022 12:36:08 +0100 Subject: [PATCH 2/2] add logging to test suite --- Cargo.lock | 70 +++++++++++++++++++++++++++ examples/test/Cargo.toml | 2 +- examples/test/src-tauri/Cargo.toml | 1 + examples/test/src-tauri/src/main.rs | 17 ++++++- examples/test/src/main.rs | 15 ++++-- examples/test/src/os.rs | 2 +- examples/test/src/tauri_log.rs | 73 +++++++++++++++++++++++++++++ 7 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 examples/test/src/tauri_log.rs diff --git a/Cargo.lock b/Cargo.lock index d57e8e6..7d9d642 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,6 +95,17 @@ dependencies = [ "url", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -164,6 +175,16 @@ version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +[[package]] +name = "byte-unit" +version = "4.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581ad4b3d627b0c09a0ccb2912148f839acaca0b93cf54cbe42b6c674e86079c" +dependencies = [ + "serde", + "utf8-width", +] + [[package]] name = "bytemuck" version = "1.12.2" @@ -299,6 +320,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + [[package]] name = "combine" version = "4.6.6" @@ -607,6 +639,16 @@ dependencies = [ "instant", ] +[[package]] +name = "fern" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bdd7b0849075e79ee9a1836df22c717d1eba30451796fdc631b04565dd11e2a" +dependencies = [ + "colored", + "log", +] + [[package]] name = "field-offset" version = "0.3.4" @@ -1352,6 +1394,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", + "serde", + "value-bag", ] [[package]] @@ -2918,6 +2962,21 @@ dependencies = [ "tauri-utils", ] +[[package]] +name = "tauri-plugin-log" +version = "0.1.0" +source = "git+https://github.com/tauri-apps/tauri-plugin-log#b58475bbc410fa78eb69276c62d0b64c91c07914" +dependencies = [ + "byte-unit", + "fern", + "log", + "serde", + "serde_json", + "serde_repr", + "tauri", + "time", +] + [[package]] name = "tauri-runtime" version = "0.12.0" @@ -2983,6 +3042,7 @@ dependencies = [ "serde_json", "tauri", "tauri-build", + "tauri-plugin-log", ] [[package]] @@ -3320,6 +3380,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" +dependencies = [ + "ctor", + "version_check", +] + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/examples/test/Cargo.toml b/examples/test/Cargo.toml index 6ea130e..9595dd7 100644 --- a/examples/test/Cargo.toml +++ b/examples/test/Cargo.toml @@ -13,7 +13,7 @@ wasm-bindgen-futures = "0.4.32" futures-util = "0.3.25" serde = { version = "1.0.147", features = ["derive"] } wasm-logger = "0.2.0" -log = "0.4.17" +log = { version = "0.4.17", features = ["serde"] } [features] ci = [] diff --git a/examples/test/src-tauri/Cargo.toml b/examples/test/src-tauri/Cargo.toml index fb0e37b..4a2c62f 100644 --- a/examples/test/src-tauri/Cargo.toml +++ b/examples/test/src-tauri/Cargo.toml @@ -17,6 +17,7 @@ tauri-build = { version = "1.2", features = [] } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.2", features = ["api-all"] } +tauri-plugin-log = {git = "https://github.com/tauri-apps/tauri-plugin-log", features = ["colored"] } [features] # by default Tauri runs in production mode diff --git a/examples/test/src-tauri/src/main.rs b/examples/test/src-tauri/src/main.rs index e5eeef1..51fba36 100644 --- a/examples/test/src-tauri/src/main.rs +++ b/examples/test/src-tauri/src/main.rs @@ -4,8 +4,8 @@ )] use std::sync::atomic::{AtomicBool, Ordering}; - -use tauri::{Manager, State, api::notification::Notification}; +use tauri::{Manager, State}; +use tauri_plugin_log::{LogTarget, LoggerBuilder}; struct Received(AtomicBool); // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command @@ -21,7 +21,20 @@ fn exit_with_error(e: &str) -> bool { } fn main() { + let log_plugin = { + let targets = [ + LogTarget::LogDir, + #[cfg(debug_assertions)] + LogTarget::Stdout, + #[cfg(debug_assertions)] + LogTarget::Webview, + ]; + + LoggerBuilder::new().targets(targets).build() + }; + tauri::Builder::default() + .plugin(log_plugin) .invoke_handler(tauri::generate_handler![verify_receive, exit_with_error]) .setup(|app| { app.manage(Received(AtomicBool::new(false))); diff --git a/examples/test/src/main.rs b/examples/test/src/main.rs index 5630f5d..649afbd 100644 --- a/examples/test/src/main.rs +++ b/examples/test/src/main.rs @@ -1,16 +1,19 @@ mod app; mod clipboard; -mod event; -mod window; mod dialog; +mod event; mod notification; mod os; +mod tauri_log; +mod window; extern crate console_error_panic_hook; +use log::LevelFilter; use std::future::Future; use std::panic; use sycamore::prelude::*; use sycamore::suspense::Suspense; +use tauri_log::TauriLogger; #[cfg(feature = "ci")] async fn exit_with_error(e: String) { @@ -127,8 +130,12 @@ pub async fn Terminate<'a, G: Html>(cx: Scope<'a>) -> View { } } +static LOGGER: TauriLogger = TauriLogger; + fn main() { - wasm_logger::init(wasm_logger::Config::default()); + log::set_logger(&LOGGER) + .map(|()| log::set_max_level(LevelFilter::Trace)) + .unwrap(); panic::set_hook(Box::new(|info| { console_error_panic_hook::hook(info); @@ -163,7 +170,7 @@ fn main() { Test(name="notification::is_permission_granted",test=notification::is_permission_granted()) Test(name="notification::request_permission",test=notification::request_permission()) InteractiveTest(name="notification::show_notification",test=notification::show_notification()) - + // Test(name="window::WebviewWindow::new",test=window::create_window()) Terminate diff --git a/examples/test/src/os.rs b/examples/test/src/os.rs index f7f31a4..9e1ddf8 100644 --- a/examples/test/src/os.rs +++ b/examples/test/src/os.rs @@ -19,7 +19,7 @@ pub async fn platform() -> anyhow::Result<()> { pub async fn tempdir() -> anyhow::Result<()> { let tempdir = os::tempdir().await?; - log::debug!("{:?}", tempdir); + log::info!("{:?}", tempdir); Ok(()) } diff --git a/examples/test/src/tauri_log.rs b/examples/test/src/tauri_log.rs new file mode 100644 index 0000000..885faba --- /dev/null +++ b/examples/test/src/tauri_log.rs @@ -0,0 +1,73 @@ +use log::{Metadata, Record}; +use serde::Serialize; +use tauri_sys::tauri; + +#[derive(Debug, Serialize)] +struct LogArgs { + level: Level, + message: String, + file: Option, + line: Option, +} + +#[derive(Debug)] +enum Level { + Trace, + Debug, + Info, + Warn, + Error, +} + +impl From for Level { + fn from(l: log::Level) -> Self { + match l { + log::Level::Error => Level::Error, + log::Level::Warn => Level::Warn, + log::Level::Info => Level::Info, + log::Level::Debug => Level::Debug, + log::Level::Trace => Level::Trace, + } + } +} + +impl Serialize for Level { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u8(match self { + Level::Trace => 1, + Level::Debug => 2, + Level::Info => 3, + Level::Warn => 4, + Level::Error => 5, + }) + } +} + +pub struct TauriLogger; +impl log::Log for TauriLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + metadata.level() <= log::Level::Trace + } + + fn log(&self, record: &Record) { + if self.enabled(record.metadata()) { + let args = LogArgs { + level: record.level().into(), + message: format!("{}", record.args()), + file: record.file().map(ToString::to_string), + line: record.line(), + }; + + wasm_bindgen_futures::spawn_local(async move { + tauri::invoke::<_, ()>("plugin:log|log", &args) + .await + .unwrap(); + }); + } + } + + fn flush(&self) {} +}