tauri_plugin_vue/
lib.rs

1// THIS FILE WAS AUTOGENERATED AND SHOULD NOT BE EDITED MANUALLY.
2//
3// Check the `codegen` command in the `tauri-store-cli` crate.
4// https://github.com/ferreira-tb/tauri-store/tree/main/crates/tauri-store-cli
5//
6// To modify the behavior of the plugin, you must either change the
7// upstream `tauri-store` crate or update the code generation itself.
8// This ensures that all plugins maintain consistent behavior.
9
10#![forbid(unsafe_code)]
11#![cfg_attr(docsrs, feature(doc_auto_cfg))]
12#![doc = include_str!("../README.md")]
13#![doc(html_favicon_url = "https://tb.dev.br/tauri-store/favicon.ico")]
14
15mod command;
16mod manager;
17mod vue;
18
19use serde::de::DeserializeOwned;
20use std::collections::{HashMap, HashSet};
21use std::path::{Path, PathBuf};
22use std::time::Duration;
23use tauri::plugin::{PluginApi, TauriPlugin};
24use tauri::{AppHandle, RunEvent, Runtime};
25use tauri_store::Migrator;
26
27pub use manager::ManagerExt;
28pub use tauri_store::prelude::*;
29pub use tauri_store::{Migration, MigrationContext};
30pub use vue::{Vue, VueMarker};
31
32#[cfg(target_os = "ios")]
33tauri::ios_plugin_binding!(init_plugin_vue);
34
35/// Builder for the Vue plugin.
36pub struct Builder<R: Runtime> {
37  default_path: Option<PathBuf>,
38  path_table: HashMap<StoreId, Box<Path>>,
39  default_marshaler: Option<Box<dyn Marshaler>>,
40  marshaler_table: HashMap<StoreId, Box<dyn Marshaler>>,
41  default_save_strategy: SaveStrategy,
42  autosave: Option<Duration>,
43  on_load: Option<Box<OnLoadFn<R, VueMarker>>>,
44  save_denylist: HashSet<StoreId>,
45  sync_denylist: HashSet<StoreId>,
46  migrator: Migrator,
47  debug_stores: bool,
48}
49
50impl<R: Runtime> Builder<R> {
51  /// Creates a new builder instance with default values.
52  pub fn new() -> Self {
53    Self::default()
54  }
55
56  /// Sets the autosave interval for all stores.
57  #[must_use]
58  pub fn autosave(mut self, interval: Duration) -> Self {
59    self.autosave = Some(interval);
60    self
61  }
62
63  /// Sets the default save strategy to be used by the stores.
64  #[must_use]
65  pub fn default_save_strategy(mut self, strategy: SaveStrategy) -> Self {
66    self.default_save_strategy = strategy;
67    self
68  }
69
70  /// Registers a closure to be called when a store is loaded.
71  #[must_use]
72  pub fn on_load<F>(mut self, f: F) -> Self
73  where
74    F: Fn(&Store<R, VueMarker>) -> Result<()> + Send + Sync + 'static,
75  {
76    self.on_load = Some(Box::new(f));
77    self
78  }
79
80  /// Default directory where the stores are saved.
81  #[must_use]
82  pub fn path(mut self, path: impl AsRef<Path>) -> Self {
83    let path = path.as_ref().to_path_buf();
84    self.default_path = Some(path);
85    self
86  }
87
88  /// Directory where a specific store should be saved.
89  #[must_use]
90  pub fn path_of(mut self, id: impl AsRef<str>, path: impl AsRef<Path>) -> Self {
91    let id = StoreId::from(id.as_ref());
92    let path = Box::from(path.as_ref());
93    self.path_table.insert(id, path);
94    self
95  }
96
97  /// Sets a list of stores that should not be saved to disk.
98  #[must_use]
99  pub fn save_denylist<I, T>(mut self, denylist: I) -> Self
100  where
101    I: IntoIterator<Item = T>,
102    T: AsRef<str>,
103  {
104    self.save_denylist.extend(
105      denylist
106        .into_iter()
107        .map(|it| StoreId::from(it.as_ref())),
108    );
109
110    self
111  }
112
113  /// Sets a list of stores that should not be synchronized across windows.
114  #[must_use]
115  pub fn sync_denylist<I, T>(mut self, denylist: I) -> Self
116  where
117    I: IntoIterator<Item = T>,
118    T: AsRef<str>,
119  {
120    self.sync_denylist.extend(
121      denylist
122        .into_iter()
123        .map(|it| StoreId::from(it.as_ref())),
124    );
125
126    self
127  }
128
129  /// Defines how the stores should be serialized and deserialized.
130  #[must_use]
131  pub fn marshaler(mut self, marshaler: Box<dyn Marshaler>) -> Self {
132    self.default_marshaler = Some(marshaler);
133    self
134  }
135
136  /// Defines how a store should be serialized and deserialized.
137  #[must_use]
138  pub fn marshaler_of(mut self, id: impl AsRef<str>, marshaler: Box<dyn Marshaler>) -> Self {
139    let id = StoreId::from(id.as_ref());
140    self.marshaler_table.insert(id, marshaler);
141    self
142  }
143
144  /// Adds a `.dev` suffix to the store files when in development mode.
145  ///
146  /// This is enabled by default.
147  #[must_use]
148  pub fn enable_debug_stores(mut self, yes: bool) -> Self {
149    self.debug_stores = yes;
150    self
151  }
152
153  /// Defines a migration for a store.
154  #[must_use]
155  pub fn migration(mut self, id: impl Into<StoreId>, migration: Migration) -> Self {
156    self.migrator.add_migration(id.into(), migration);
157    self
158  }
159
160  /// Defines multiple migrations for a store.
161  #[must_use]
162  pub fn migrations<I>(mut self, id: impl Into<StoreId>, migrations: I) -> Self
163  where
164    I: IntoIterator<Item = Migration>,
165  {
166    self
167      .migrator
168      .add_migrations(id.into(), migrations);
169
170    self
171  }
172
173  /// Sets a closure to be called before each migration step.
174  #[must_use]
175  pub fn on_before_each_migration<F>(mut self, f: F) -> Self
176  where
177    F: Fn(MigrationContext) + Send + Sync + 'static,
178  {
179    self.migrator.on_before_each(f);
180    self
181  }
182
183  fn build_collection(self, handle: Handle<R>) -> Result<()> {
184    let mut builder = StoreCollection::<R, VueMarker>::builder()
185      .default_save_strategy(self.default_save_strategy)
186      .save_denylist(&self.save_denylist)
187      .sync_denylist(&self.sync_denylist)
188      .migrator(self.migrator)
189      .enable_debug_stores(self.debug_stores);
190
191    if let Some(path) = self.default_path {
192      builder = builder.path(path);
193    }
194
195    if let Some(on_load) = self.on_load {
196      builder = builder.on_load(on_load);
197    }
198
199    if let Some(duration) = self.autosave {
200      builder = builder.autosave(duration);
201    }
202
203    if let Some(marshaler) = self.default_marshaler {
204      builder = builder.marshaler(marshaler);
205    }
206
207    for (id, path) in self.path_table {
208      builder = builder.path_of(id, path);
209    }
210
211    for (id, marshaler) in self.marshaler_table {
212      builder = builder.marshaler_of(id, marshaler);
213    }
214
215    builder.build(handle, env!("CARGO_PKG_NAME"))
216  }
217
218  /// Builds the Vue plugin.
219  pub fn build(self) -> TauriPlugin<R> {
220    tauri::plugin::Builder::new("vue")
221      .setup(|app, api| setup(app, api, self))
222      .on_event(on_event)
223      .invoke_handler(tauri::generate_handler![
224        command::allow_save,
225        command::allow_sync,
226        command::clear_autosave,
227        command::deny_save,
228        command::deny_sync,
229        command::destroy,
230        command::get_default_save_strategy,
231        command::get_store_collection_path,
232        command::get_save_strategy,
233        command::get_store_ids,
234        command::get_store_path,
235        command::get_store_state,
236        command::load,
237        command::patch,
238        command::save,
239        command::save_all,
240        command::save_all_now,
241        command::save_now,
242        command::save_some,
243        command::save_some_now,
244        command::set_autosave,
245        command::set_save_strategy,
246        command::set_store_options,
247        command::unload
248      ])
249      .build()
250  }
251}
252
253impl<R: Runtime> Default for Builder<R> {
254  fn default() -> Self {
255    Self {
256      default_path: None,
257      path_table: HashMap::new(),
258      default_marshaler: None,
259      marshaler_table: HashMap::new(),
260      default_save_strategy: SaveStrategy::default(),
261      autosave: None,
262      on_load: None,
263      save_denylist: HashSet::default(),
264      sync_denylist: HashSet::default(),
265      migrator: Migrator::default(),
266      debug_stores: true,
267    }
268  }
269}
270
271#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
272fn setup<R, D>(app: &AppHandle<R>, _api: PluginApi<R, D>, builder: Builder<R>) -> BoxResult<()>
273where
274  R: Runtime,
275  D: DeserializeOwned,
276{
277  let handle = Handle::new(app.clone());
278  builder.build_collection(handle)?;
279  Ok(())
280}
281
282#[cfg(any(target_os = "android", target_os = "ios"))]
283fn setup<R, D>(_app: &AppHandle<R>, api: PluginApi<R, D>, builder: Builder<R>) -> BoxResult<()>
284where
285  R: Runtime,
286  D: DeserializeOwned,
287{
288  #[cfg(target_os = "android")]
289  let handle = api.register_android_plugin("com.plugin.vue", "VuePlugin")?;
290
291  #[cfg(target_os = "ios")]
292  let handle = api.register_ios_plugin(init_plugin_vue)?;
293
294  builder.build_collection(Handle::new(handle))?;
295  Ok(())
296}
297
298fn on_event<R>(app: &AppHandle<R>, event: &RunEvent)
299where
300  R: Runtime,
301{
302  if let RunEvent::Exit = event {
303    let _ = app.vue().0.on_exit();
304  }
305}
306
307/// Initializes the plugin with the default settings.
308pub fn init<R: Runtime>() -> TauriPlugin<R> {
309  Builder::default().build()
310}