#![allow(clippy::pedantic)]
#![allow(clippy::nursery)]
#![warn(clippy::all, clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
use std::path::Path;
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
};
pub mod commands;
pub mod commands_graph;
pub mod commands_index;
pub mod commands_memory;
pub mod commands_query;
pub mod commands_sparse;
pub mod error;
pub mod events;
pub mod helpers;
pub mod state;
pub mod types;
pub mod types_graph;
pub use error::{CommandError, Error, Result};
pub use state::VelesDbState;
#[must_use]
pub fn init<R: Runtime>() -> TauriPlugin<R> {
init_with_path("./velesdb_data")
}
macro_rules! velesdb_invoke_handler {
(
common: [$($common:path),* $(,)?],
persistence_only: [$($persist:path),* $(,)?] $(,)?
) => {{
#[cfg(feature = "persistence")]
{
tauri::generate_handler![$($common,)* $($persist,)*]
}
#[cfg(not(feature = "persistence"))]
{
tauri::generate_handler![$($common,)*]
}
}};
}
#[must_use]
pub fn init_with_path<R: Runtime, P: AsRef<Path>>(path: P) -> TauriPlugin<R> {
let db_path = path.as_ref().to_path_buf();
let builder = Builder::new("velesdb").invoke_handler(velesdb_invoke_handler!(
common: [
commands::create_collection,
commands::create_metadata_collection,
commands::delete_collection,
commands::list_collections,
commands::get_collection,
commands::upsert,
commands::upsert_metadata,
commands::get_points,
commands::delete_points,
commands::search,
commands::batch_search,
commands::text_search,
commands::hybrid_search,
commands::multi_query_search,
commands_query::query,
commands::is_empty,
commands::flush,
commands::scroll_collection,
commands_sparse::sparse_search,
commands_sparse::hybrid_sparse_search,
commands_sparse::sparse_upsert,
commands::train_pq,
commands_memory::semantic_store,
commands_memory::semantic_query,
commands_memory::episodic_record,
commands_memory::episodic_recent,
commands_memory::procedural_learn,
commands_memory::procedural_recall,
commands_graph::create_graph_collection,
commands_graph::add_edge,
commands_graph::get_edges,
commands_graph::traverse_graph,
commands_graph::get_node_degree,
commands_graph::traverse_graph_parallel,
commands_index::create_index,
commands_index::drop_index,
commands_index::list_indexes,
],
persistence_only: [
commands::stream_insert,
],
));
builder
.setup(move |app, _api| {
let state = VelesDbState::new(db_path.clone());
app.manage(state);
tracing::info!("VelesDB plugin initialized with path: {:?}", db_path);
Ok(())
})
.build()
}
#[must_use]
pub fn init_default<R: Runtime>() -> TauriPlugin<R> {
init()
}
pub fn init_with_app_data<R: Runtime>(app_name: &str) -> Result<TauriPlugin<R>> {
let app_data_dir = get_app_data_dir(app_name)?;
Ok(init_with_path(app_data_dir))
}
pub fn get_app_data_dir(app_name: &str) -> Result<std::path::PathBuf> {
let base_dir = dirs::data_dir().or_else(dirs::config_dir).ok_or_else(|| {
Error::InvalidConfig("Could not determine app data directory for this platform".to_string())
})?;
Ok(base_dir.join(app_name).join("velesdb"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_velesdb_state_creation() {
let path = std::path::PathBuf::from("/tmp/test");
let state = VelesDbState::new(path.clone());
assert_eq!(state.path(), &path);
}
#[test]
fn test_get_app_data_dir_structure() {
let path = get_app_data_dir("test-app").unwrap();
assert!(path.ends_with("test-app/velesdb") || path.ends_with("test-app\\velesdb"));
assert!(path.to_string_lossy().contains("test-app"));
}
#[test]
fn test_get_app_data_dir_different_apps() {
let path1 = get_app_data_dir("app1").unwrap();
let path2 = get_app_data_dir("app2").unwrap();
assert_ne!(path1, path2);
}
}