host: the drafts vault commands (draft_list/save/revisions/status, observation_list, data_export) are the host's (AppConfig::with_vault, commands::VAULT); the app takes the vault through vault_commands::lock
This commit is contained in:
parent
2e49577196
commit
8c2404b4cc
6 changed files with 147 additions and 11 deletions
80
crates/waybetter-host/src/vault_commands.rs
Normal file
80
crates/waybetter-host/src/vault_commands.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
//! The drafts vault, native side, for every app that sets [`crate::app::AppConfig::vault`]: opens the
|
||||
//! app's [`Vault`] in app data at launch and serves the shell-only `draft_list`, `draft_save`,
|
||||
//! `draft_revisions`, `draft_status`, `observation_list` and `data_export` ([`crate::commands::VAULT`]).
|
||||
//! A write is acknowledged only after its SQLite transaction committed. The app's own native code (its
|
||||
//! capture, a popover that reads drafts, a backup import) takes the same vault through [`lock`]; what
|
||||
//! it does with it is the app's.
|
||||
|
||||
use crate::app::config;
|
||||
use crate::host::{data_file, shell_only};
|
||||
use crate::vault::{Draft, DraftRevision, ExportData, Observation, SaveDraftInput, Vault, VaultRules};
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
use tauri::{AppHandle, Manager, Webview};
|
||||
|
||||
/// What an app declares about its vault: the database file in app data and its rules.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct VaultConfig {
|
||||
pub file: &'static str,
|
||||
pub rules: &'static VaultRules,
|
||||
}
|
||||
|
||||
struct VaultState(Mutex<Vault>);
|
||||
|
||||
/// Opens the database. Does nothing unless the app set [`crate::app::AppConfig::vault`]. A database
|
||||
/// that cannot be opened (a newer schema, a damaged file) stops the launch rather than starting empty.
|
||||
pub(crate) fn init(app: &AppHandle) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let Some(vault) = config(app).vault else { return Ok(()) };
|
||||
let path = data_file(app, vault.file).ok_or("STORAGE: no application data directory")?;
|
||||
app.manage(VaultState(Mutex::new(Vault::open(path, vault.rules).map_err(std::io::Error::other)?)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The vault, locked. Hold it only for the call that needs it; never across a webview call.
|
||||
pub fn lock(app: &AppHandle) -> Result<MutexGuard<'_, Vault>, String> {
|
||||
app.try_state::<VaultState>()
|
||||
.ok_or("DATABASE: vault unavailable; restart safely")?
|
||||
.inner()
|
||||
.0
|
||||
.lock()
|
||||
.map_err(|_| "DATABASE: workspace state unavailable; restart safely".into())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub(crate) async fn draft_list(webview: Webview, app: AppHandle) -> Result<Vec<Draft>, String> {
|
||||
shell_only(&webview)?;
|
||||
lock(&app)?.list_drafts()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub(crate) async fn draft_save(webview: Webview, app: AppHandle, input: SaveDraftInput) -> Result<Draft, String> {
|
||||
shell_only(&webview)?;
|
||||
lock(&app)?.save_draft(&input)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub(crate) async fn draft_revisions(webview: Webview, app: AppHandle, draft_id: String) -> Result<Vec<DraftRevision>, String> {
|
||||
shell_only(&webview)?;
|
||||
lock(&app)?.revisions(&draft_id)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub(crate) async fn draft_status(webview: Webview, app: AppHandle, id: String, expected_revision: i64, status: String) -> Result<Draft, String> {
|
||||
shell_only(&webview)?;
|
||||
lock(&app)?.set_status(&id, expected_revision, &status)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub(crate) async fn observation_list(webview: Webview, app: AppHandle) -> Result<Vec<Observation>, String> {
|
||||
shell_only(&webview)?;
|
||||
lock(&app)?.observations()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub(crate) async fn data_export(webview: Webview, app: AppHandle) -> Result<ExportData, String> {
|
||||
shell_only(&webview)?;
|
||||
lock(&app)?.export()
|
||||
}
|
||||
|
||||
pub(crate) fn handler() -> impl Fn(tauri::ipc::Invoke<tauri::Wry>) -> bool + Send + Sync + 'static {
|
||||
tauri::generate_handler![draft_list, draft_save, draft_revisions, draft_status, observation_list, data_export]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue