diff --git a/plugins/store/api-iife.js b/plugins/store/api-iife.js index 3582aa3b..e7b7bea2 100644 --- a/plugins/store/api-iife.js +++ b/plugins/store/api-iife.js @@ -1 +1 @@ -if("__TAURI__"in window){var __TAURI_PLUGIN_STORE__=function(e){"use strict";var t,r;function a(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}async function i(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}"function"==typeof SuppressedError&&SuppressedError;class n{get rid(){return function(e,t,r,a){if("a"===r&&!a)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!a:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?a:"a"===r?a.call(e):a?a.value:t.get(e)}(this,t,"f")}constructor(e){t.set(this,void 0),function(e,t,r,a,i){if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");t.set(e,r)}(this,t,e)}async close(){return i("plugin:resources|close",{rid:this.rid})}}async function s(e,t,r){const n={kind:"Any"};return i("plugin:event|listen",{event:e,target:n,handler:a(t)}).then((t=>async()=>async function(e,t){await i("plugin:event|unlisten",{event:e,eventId:t})}(e,t)))}t=new WeakMap,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(r||(r={}));class o extends n{constructor(e,t){super(e),this.path=t}async set(e,t){await i("plugin:store|set",{rid:this.rid,key:e,value:t})}async get(e){return await i("plugin:store|get",{rid:this.rid,key:e})}async has(e){return await i("plugin:store|has",{rid:this.rid,key:e})}async delete(e){return await i("plugin:store|delete",{rid:this.rid,key:e})}async clear(){await i("plugin:store|clear",{rid:this.rid})}async reset(){await i("plugin:store|reset",{rid:this.rid})}async keys(){return await i("plugin:store|keys",{rid:this.rid})}async values(){return await i("plugin:store|values",{rid:this.rid})}async entries(){return await i("plugin:store|entries",{rid:this.rid})}async length(){return await i("plugin:store|length",{rid:this.rid})}async load(){await i("plugin:store|load",{rid:this.rid})}async save(){await i("plugin:store|save",{rid:this.rid})}async onKeyChange(e,t){return await s("store://change",(r=>{r.payload.path===this.path&&r.payload.key===e&&t(r.payload.value)}))}async onChange(e){return await s("store://change",(t=>{t.payload.path===this.path&&e(t.payload.key,t.payload.value)}))}}return e.Store=o,e.createStore=async function(e,t){const r=await i("plugin:store|create_store",{path:e,...t});return new o(r,e)},e.getStore=async function(e){const t=await i("plugin:store|get_store");return new o(t,e)},e}({});Object.defineProperty(window.__TAURI__,"store",{value:__TAURI_PLUGIN_STORE__})} +if("__TAURI__"in window){var __TAURI_PLUGIN_STORE__=function(e){"use strict";var t,r;function a(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}async function i(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}"function"==typeof SuppressedError&&SuppressedError;class n{get rid(){return function(e,t,r,a){if("a"===r&&!a)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!a:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?a:"a"===r?a.call(e):a?a.value:t.get(e)}(this,t,"f")}constructor(e){t.set(this,void 0),function(e,t,r,a,i){if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");t.set(e,r)}(this,t,e)}async close(){return i("plugin:resources|close",{rid:this.rid})}}async function s(e,t,r){const n={kind:"Any"};return i("plugin:event|listen",{event:e,target:n,handler:a(t)}).then((t=>async()=>async function(e,t){await i("plugin:event|unlisten",{event:e,eventId:t})}(e,t)))}t=new WeakMap,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(r||(r={}));class o extends n{constructor(e,t){super(e),this.path=t}async set(e,t){await i("plugin:store|set",{rid:this.rid,key:e,value:t})}async get(e){return await i("plugin:store|get",{rid:this.rid,key:e})}async has(e){return await i("plugin:store|has",{rid:this.rid,key:e})}async delete(e){return await i("plugin:store|delete",{rid:this.rid,key:e})}async clear(){await i("plugin:store|clear",{rid:this.rid})}async reset(){await i("plugin:store|reset",{rid:this.rid})}async keys(){return await i("plugin:store|keys",{rid:this.rid})}async values(){return await i("plugin:store|values",{rid:this.rid})}async entries(){return await i("plugin:store|entries",{rid:this.rid})}async length(){return await i("plugin:store|length",{rid:this.rid})}async load(){await i("plugin:store|load",{rid:this.rid})}async save(){await i("plugin:store|save",{rid:this.rid})}async onKeyChange(e,t){return await s("store://change",(r=>{r.payload.path===this.path&&r.payload.key===e&&t(r.payload.value)}))}async onChange(e){return await s("store://change",(t=>{t.payload.path===this.path&&e(t.payload.key,t.payload.value)}))}}return e.Store=o,e.createStore=async function(e,t){const r=await i("plugin:store|create_store",{path:e,...t});return new o(r,e)},e.getStore=async function(e){const t=await i("plugin:store|get_store");return t?new o(t,e):void 0},e}({});Object.defineProperty(window.__TAURI__,"store",{value:__TAURI_PLUGIN_STORE__})} diff --git a/plugins/store/examples/AppSettingsManager/src-tauri/src/main.rs b/plugins/store/examples/AppSettingsManager/src-tauri/src/main.rs index 45ec5989..95da5bee 100644 --- a/plugins/store/examples/AppSettingsManager/src-tauri/src/main.rs +++ b/plugins/store/examples/AppSettingsManager/src-tauri/src/main.rs @@ -5,8 +5,6 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use std::time::Duration; - use serde_json::json; use tauri::Listener; use tauri_plugin_store::StoreExt; @@ -19,13 +17,7 @@ fn main() { .plugin(tauri_plugin_store::Builder::new().build()) .setup(|app| { // Init store and load it from disk - let store = app - .handle() - .store_builder("settings.json") - .auto_save(Duration::from_millis(100)) - .build() - .unwrap(); - app.share_store(store.clone()); + let store = app.handle().store_builder("settings.json").build().unwrap(); app.listen("store://change", |event| { dbg!(event); }); diff --git a/plugins/store/guest-js/index.ts b/plugins/store/guest-js/index.ts index 5f910192..598a33e9 100644 --- a/plugins/store/guest-js/index.ts +++ b/plugins/store/guest-js/index.ts @@ -25,8 +25,13 @@ export type StoreOptions = { /** * @param path: Path to save the store in `app_data_dir` * @param options: Store configuration options + * + * Throws if the store at that path already exists */ -export async function createStore(path: string, options?: StoreOptions) { +export async function createStore( + path: string, + options?: StoreOptions +): Promise { const resourceId = await invoke('plugin:store|create_store', { path, ...options @@ -37,9 +42,9 @@ export async function createStore(path: string, options?: StoreOptions) { /** * @param path: Path of the store in the rust side */ -export async function getStore(path: string) { - const resourceId = await invoke('plugin:store|get_store') - return new Store(resourceId, path) +export async function getStore(path: string): Promise { + const resourceId = await invoke('plugin:store|get_store') + return resourceId ? new Store(resourceId, path) : undefined } /** diff --git a/plugins/store/src/lib.rs b/plugins/store/src/lib.rs index 713d767d..a4fd20e9 100644 --- a/plugins/store/src/lib.rs +++ b/plugins/store/src/lib.rs @@ -12,11 +12,11 @@ )] pub use error::{Error, Result}; -use log::warn; use serde::{Deserialize, Serialize}; pub use serde_json::Value as JsonValue; use std::{ collections::HashMap, + marker::PhantomData, path::{Path, PathBuf}, sync::{Arc, Mutex}, time::Duration, @@ -188,15 +188,14 @@ impl> StoreExt for T { } } -// #[derive(Default)] pub struct Builder { - stores: HashMap>, + phantom_data: PhantomData, } impl Default for Builder { fn default() -> Self { Self { - stores: Default::default(), + phantom_data: Default::default(), } } } @@ -218,7 +217,7 @@ impl Builder { /// Ok(()) /// }); /// ``` - pub fn build(mut self) -> TauriPlugin { + pub fn build(self) -> TauriPlugin { plugin::Builder::new("store") .invoke_handler(tauri::generate_handler![ create_store, @@ -237,19 +236,9 @@ impl Builder { save ]) .setup(move |app_handle, _api| { - for (path, store) in self.stores.iter_mut() { - // ignore loading errors, just use the default - if let Err(err) = store.load() { - warn!( - "Failed to load store {path:?} from disk: {err}. Falling back to default values." - ); - } - } - app_handle.manage(StoreCollection { stores: Mutex::new(HashMap::new()), }); - Ok(()) }) .on_event(|app_handle, event| { @@ -259,7 +248,7 @@ impl Builder { for (path, rid) in stores.iter() { if let Ok(store) = app_handle.resources_table().get::>(*rid) { if let Err(err) = store.save() { - eprintln!("failed to save store {path:?} with error {err:?}"); + log::error!("failed to save store {path:?} with error {err:?}"); } } } diff --git a/plugins/store/src/store.rs b/plugins/store/src/store.rs index 1a34575e..6e363c33 100644 --- a/plugins/store/src/store.rs +++ b/plugins/store/src/store.rs @@ -385,7 +385,14 @@ pub struct Store { store: Arc>>, } -impl Resource for Store {} +impl Resource for Store { + fn close(self: Arc) { + let store = self.store.lock().unwrap(); + let collection = store.app.state::(); + let mut stores = collection.stores.lock().unwrap(); + stores.remove(&store.path); + } +} impl Store { pub fn with_store(&self, f: impl FnOnce(&mut StoreInner) -> T) -> T {