feat: add Tauri state persistence and BvCli trait

- Add Tauri storage adapter for Zustand (tauri-storage.ts)
- Add read_state, write_state, clear_state Tauri commands
- Wire focus-store and nav-store to use Tauri persistence
- Add BvCli trait for bv CLI mocking with response types
- Add BvError and McError conversion for bv errors
- Add cleanup_tmp_files tests for bridge
- Fix linter-introduced tauri_specta::command issues

Closes bd-2x6, bd-gil, bd-3px

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
teernisse
2026-02-26 10:05:53 -05:00
parent 443db24fb3
commit 087b588d71
14 changed files with 877 additions and 20 deletions

View File

@@ -7,6 +7,7 @@
//! - Single-instance locking via flock(2)
use serde::{Deserialize, Serialize};
use specta::Type;
use std::collections::HashMap;
use std::fs::{self, File};
use std::io::{self, Write};
@@ -109,7 +110,7 @@ impl MappingKey {
}
/// Result of a sync operation
#[derive(Debug, Default, Serialize)]
#[derive(Debug, Default, Serialize, Type)]
pub struct SyncResult {
/// Number of new beads created
pub created: usize,
@@ -1323,4 +1324,48 @@ mod tests {
assert_eq!(r4.closed, 1);
assert!(!map.mappings.contains_key("issue:g/p:42"));
}
// -- cleanup_tmp_files tests --
#[test]
fn test_cleanup_tmp_files_removes_orphaned_tmp() {
let dir = TempDir::new().unwrap();
let bridge = test_bridge(MockLoreCli::new(), MockBeadsCli::new(), &dir);
// Create an orphaned .tmp file (simulating a crash during save_map)
let tmp_file = dir.path().join("gitlab_bead_map.json.tmp");
std::fs::write(&tmp_file, "orphaned data").unwrap();
assert!(tmp_file.exists());
// Cleanup should remove it
let cleaned = bridge.cleanup_tmp_files().unwrap();
assert_eq!(cleaned, 1);
assert!(!tmp_file.exists());
}
#[test]
fn test_cleanup_tmp_files_ignores_non_tmp_files() {
let dir = TempDir::new().unwrap();
let bridge = test_bridge(MockLoreCli::new(), MockBeadsCli::new(), &dir);
// Create a regular file (should not be removed)
let json_file = dir.path().join("gitlab_bead_map.json");
std::fs::write(&json_file, "{}").unwrap();
let cleaned = bridge.cleanup_tmp_files().unwrap();
assert_eq!(cleaned, 0);
assert!(json_file.exists());
}
#[test]
fn test_cleanup_tmp_files_handles_missing_dir() {
let dir = TempDir::new().unwrap();
let nonexistent = dir.path().join("nonexistent");
let bridge: Bridge<MockLoreCli, MockBeadsCli> =
Bridge::with_data_dir(MockLoreCli::new(), MockBeadsCli::new(), nonexistent);
// Should return 0, not error, when dir doesn't exist
let cleaned = bridge.cleanup_tmp_files().unwrap();
assert_eq!(cleaned, 0);
}
}