tauri_plugin_cache/
lib.rs

1use tauri::{
2    plugin::{Builder, TauriPlugin},
3    Manager, Runtime,
4};
5
6pub use models::*;
7
8#[cfg(desktop)]
9mod desktop;
10#[cfg(mobile)]
11mod mobile;
12
13mod commands;
14mod error;
15mod models;
16
17pub use error::{Error, Result};
18
19#[cfg(desktop)]
20use desktop::Cache;
21#[cfg(mobile)]
22use mobile::Cache;
23
24/// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the cache APIs.
25pub trait CacheExt<R: Runtime> {
26    fn cache(&self) -> &Cache<R>;
27}
28
29impl<R: Runtime, T: Manager<R>> crate::CacheExt<R> for T {
30    fn cache(&self) -> &Cache<R> {
31        self.state::<Cache<R>>().inner()
32    }
33}
34
35/// Initializes the plugin.
36pub fn init<R: Runtime>() -> TauriPlugin<R> {
37    // Default config
38    let config = CacheConfig::default();
39    init_with_config(config)
40}
41
42/// Initializes the plugin with custom configuration.
43pub fn init_with_config<R: Runtime>(config: CacheConfig) -> TauriPlugin<R> {
44    // Clone config for use in the closure
45    let config_clone = config.clone();
46
47    Builder::new("cache")
48        .invoke_handler(tauri::generate_handler![
49            commands::set,
50            commands::get,
51            commands::has,
52            commands::remove,
53            commands::clear,
54            commands::stats
55        ])
56        .setup(move |app, api| {
57            // Provide the config manually to the desktop implementation
58            #[cfg(desktop)]
59            let cache = {
60                // Always start from app's cache directory
61                let base_cache_dir = app.path().app_cache_dir().map_err(|e| {
62                    crate::Error::Cache(format!("Failed to get app cache directory: {}", e))
63                })?;
64
65                // If custom subdirectory is specified, append it to the app cache directory path
66                let cache_dir = if let Some(custom_dir) = config_clone.cache_dir.as_deref() {
67                    let custom_path = std::path::PathBuf::from(custom_dir);
68                    if custom_path.is_absolute() {
69                        // Instead of absolute path, take only the last component
70                        let path_components: Vec<_> = custom_path
71                            .components()
72                            .filter(|c| !c.as_os_str().is_empty())
73                            .collect();
74
75                        if let Some(last_component) = path_components.last() {
76                            base_cache_dir.join(last_component.as_os_str())
77                        } else {
78                            base_cache_dir
79                        }
80                    } else {
81                        // Add as a relative path
82                        base_cache_dir.join(custom_dir)
83                    }
84                } else {
85                    base_cache_dir
86                };
87
88                // Create the cache directory if it doesn't exist
89                std::fs::create_dir_all(&cache_dir).map_err(|e| {
90                    crate::Error::Cache(format!("Failed to create cache directory: {}", e))
91                })?;
92
93                // Determine the cache file name
94                let cache_file_name = config_clone
95                    .cache_file_name
96                    .as_deref()
97                    .unwrap_or("tauri_cache.json");
98                let cache_file_path = cache_dir.join(cache_file_name);
99
100                // Get the default compression settings
101                let default_compression = config_clone.default_compression.unwrap_or(false);
102                let compression_level = config_clone.compression_level;
103                let compression_threshold = config_clone.compression_threshold;
104
105                // Initialize the cache with cleanup interval
106                let mut cache = desktop::init_with_config(
107                    app,
108                    api,
109                    cache_file_path,
110                    config_clone.cleanup_interval.unwrap_or(60),
111                )?;
112
113                // Initialize with compression settings
114                cache.init_with_config(
115                    default_compression,
116                    compression_level,
117                    compression_threshold,
118                );
119                cache
120            };
121
122            #[cfg(mobile)]
123            let cache = {
124                // Always start from app's cache directory
125                let base_cache_dir = app.path().app_cache_dir().map_err(|e| {
126                    crate::Error::Cache(format!("Failed to get app cache directory: {}", e))
127                })?;
128
129                // If custom subdirectory is specified, append it to the app cache directory path
130                let cache_dir = if let Some(custom_dir) = config_clone.cache_dir.as_deref() {
131                    let custom_path = std::path::PathBuf::from(custom_dir);
132                    if custom_path.is_absolute() {
133                        // Instead of absolute path, take only the last component
134                        let path_components: Vec<_> = custom_path
135                            .components()
136                            .filter(|c| !c.as_os_str().is_empty())
137                            .collect();
138
139                        if let Some(last_component) = path_components.last() {
140                            base_cache_dir.join(last_component.as_os_str())
141                        } else {
142                            base_cache_dir
143                        }
144                    } else {
145                        // Add as a relative path
146                        base_cache_dir.join(custom_dir)
147                    }
148                } else {
149                    base_cache_dir
150                };
151
152                // Create the cache directory if it doesn't exist
153                std::fs::create_dir_all(&cache_dir).map_err(|e| {
154                    crate::Error::Cache(format!("Failed to create cache directory: {}", e))
155                })?;
156
157                // Determine the cache file name
158                let cache_file_name = config_clone
159                    .cache_file_name
160                    .as_deref()
161                    .unwrap_or("tauri_cache.json");
162                let cache_file_path = cache_dir.join(cache_file_name);
163
164                mobile::init_with_config(
165                    app,
166                    api,
167                    cache_file_path,
168                    config_clone.cleanup_interval.unwrap_or(60),
169                )?
170            };
171
172            app.manage(cache);
173            Ok(())
174        })
175        .build()
176}