User Guide
Welcome to the Eidetica User Guide. This guide will help you understand and use Eidetica effectively in your applications.
What is Eidetica?
Eidetica is a Rust library for managing structured data with built-in history tracking. It combines concepts from distributed systems, Merkle-CRDTs, and traditional databases to provide a unique approach to data management:
- Efficient data storage with customizable Databases
- History tracking for all changes via immutable Entries forming a DAG
- Structured data types via named, typed Stores within logical Databases
- Atomic changes across multiple data structures using Transactions
- Designed for distribution (future capability)
How to Use This Guide
This user guide is structured to guide you from basic setup to advanced concepts:
- Getting Started: Installation, basic setup, and your first steps.
- Basic Usage Pattern: A quick look at the typical workflow.
- Core Concepts: Understand the fundamental building blocks:
- Entries & Databases: The core DAG structure.
- Databases: How data is stored.
- Stores: Where structured data lives (
DocStore,Table,YDoc). - Transactions: How atomic changes are made.
- Tutorial: Todo App: A step-by-step walkthrough using a simple application.
- Code Examples: Focused code snippets for common tasks.
Quick Overview: The Core Flow
Eidetica revolves around a few key components working together:
Database: You start by choosing or creating a storageDatabase(e.g.,InMemoryDatabase).Instance: You create aInstanceinstance, providing it theDatabase. This is your main database handle.Database: Using theInstance, you create or load aDatabase, which acts as a logical container for related data and tracks its history.Transaction: To read or write data, you start aTransactionfrom theDatabase. This ensures atomicity and consistent views.Store: Within aTransaction, you get handles to namedStores (likeDocStoreorTable<YourData>). These provide methods (set,get,insert,remove, etc.) to interact with your structured data.Commit: Changes made viaStorehandles within theTransactionare staged. Callingcommit()on theTransactionfinalizes these changes atomically, creating a new historicalEntryin theDatabase.
Basic Usage Pattern
Here's a quick example showing creating a user, database, and writing new data.
extern crate eidetica; extern crate serde; use eidetica::{backend::database::InMemory, Instance, crdt::Doc, store::{DocStore, Table}}; use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize, Clone, Debug)] struct MyData { name: String, } fn main() -> eidetica::Result<()> { let backend = InMemory::new(); let instance = Instance::open(Box::new(backend))?; // Create and login a passwordless user instance.create_user("alice", None)?; let mut user = instance.login_user("alice", None)?; // Create a database let mut settings = Doc::new(); settings.set_string("name", "my_database"); let default_key = user.get_default_key()?; let database = user.create_database(settings, &default_key)?; // --- Writing Data --- // Start a Transaction let txn = database.new_transaction()?; let inserted_id = { // Scope for store handles // Get Store handles let config = txn.get_store::<DocStore>("config")?; let items = txn.get_store::<Table<MyData>>("items")?; // Use Store methods config.set("version", "1.0")?; items.insert(MyData { name: "example".to_string() })? }; // Handles drop, changes are staged in txn // Commit changes let new_entry_id = txn.commit()?; println!("Committed changes, new entry ID: {}", new_entry_id); // --- Reading Data --- // Use Database::get_store_viewer for a read-only view let items_viewer = database.get_store_viewer::<Table<MyData>>("items")?; if let Ok(item) = items_viewer.get(&inserted_id) { println!("Read item: {:?}", item); } Ok(()) }
See Transactions and Code Examples for more details.
Project Status
Eidetica is currently under active development. The core functionality is working, but APIs are considered experimental and may change in future releases. It is suitable for evaluation and prototyping, but not yet recommended for production systems requiring long-term API stability.