| Crates.io | turbovault-core |
| lib.rs | turbovault-core |
| version | 1.2.6 |
| created_at | 2025-10-24 15:53:40.761424+00 |
| updated_at | 2025-12-16 18:24:06.814692+00 |
| description | Core data models and types for TurboVault Server |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1898628 |
| size | 154,859 |
Core data models, error types, and configuration for the Obsidian vault management system.
This crate provides the foundational types and utilities that all other TurboVault crates depend on. It defines the canonical data structures, error handling, configuration management, and cross-cutting concerns like metrics and validation.
turbovault-core is the foundation layer that:
models.rs)Rich, serializable types representing Obsidian vault elements:
use TurboVault_core::prelude::*;
// Core vault file with parsed content
let file = VaultFile::new(path, content, metadata);
// Structured link types
let link = Link::new(LinkType::WikiLink, source_file, target, position);
// Parse results include headings, tags, callouts, tasks, etc.
assert_eq!(file.headings.len(), 3);
assert!(file.has_tag("rust"));
Types:
VaultFile - Complete parsed markdown file with all elementsLink - Links with type classification (see LinkType below)Heading - Hierarchical headings with anchorsTag - Inline and frontmatter tagsTaskItem - Checkboxes with completion statusCallout - Obsidian callout blocks (note, warning, tip, etc.)Block - Generic content blocks with IDsFrontmatter - YAML metadataFileMetadata - File system metadata (size, timestamps, checksum)ContentBlock - Block-level AST (Heading, Paragraph, Code, List, Table, etc.)InlineElement - Inline formatting (Strong, Emphasis, Code, Link, Image)LinkType variants:
WikiLink - Basic wikilink: [[Note]]Embed - Embedded content: ![[Note]]BlockRef - Block reference: [[Note#^blockid]] or #^blockidHeadingRef - Cross-file heading: [[Note#Heading]] or file.md#sectionAnchor - Same-document anchor: [[#Heading]] or #sectionMarkdownLink - Markdown link to file: [text](./file.md)ExternalLink - External URL: [text](https://...)error.rs)Unified error type for the entire system:
use TurboVault_core::{Error, Result};
fn read_file(path: &Path) -> Result<String> {
if !path.exists() {
return Err(Error::file_not_found(path));
}
let content = std::fs::read_to_string(path)?;
if content.len() > max_size {
return Err(Error::file_too_large(path, content.len() as u64, max_size));
}
Ok(content)
}
Error Categories:
Io - File system errors (auto-converted from std::io::Error)FileNotFound - Missing files with path contextInvalidPath - Path validation failuresPathTraversalAttempt - Security violationsFileTooLarge - Size limit violationsParseError - Content parsing failuresConfigError - Configuration validation issuesValidationError - Content validation failuresConcurrencyError - Race condition detectionNotFound - Missing graph entriesconfig.rs)Builder-based configuration with validation:
use TurboVault_core::config::*;
// Single vault configuration
let vault = VaultConfig::builder("main", "/path/to/vault")
.as_default()
.watch_for_changes(true)
.build()?;
// Server-wide configuration
let mut server_config = ServerConfig::new();
server_config.vaults.push(vault);
server_config.max_file_size = 20 * 1024 * 1024; // 20MB
server_config.validate()?;
Features:
VaultConfig - Per-vault settings with optional overridesServerConfig - Global server settings with defaultsmulti_vault.rs)Coordinate multiple Obsidian vaults simultaneously:
use TurboVault_core::MultiVaultManager;
let manager = MultiVaultManager::new(server_config)?;
// Add new vault
manager.add_vault(new_vault_config).await?;
// Switch active vault
manager.set_active_vault("work").await?;
// List all vaults
let vaults = manager.list_vaults().await?;
for vault_info in vaults {
println!("{} - {}", vault_info.name, vault_info.path.display());
}
Features:
metrics.rs)Lock-free metrics infrastructure for high-performance observability:
use TurboVault_core::metrics::*;
// Lock-free counter (atomic operations)
let counter = Counter::new("requests");
counter.increment();
counter.add(5);
assert_eq!(counter.value(), 6);
// Histogram for distributions
let histogram = Histogram::new("latency_ms");
histogram.record(42.5);
// RAII timer for automatic duration recording
{
let _timer = histogram.timer();
// ... operation ...
} // Duration automatically recorded on drop
Features:
Counter - Monotonically increasing atomic valuesHistogram - Distribution tracking with statisticsHistogramTimer - RAII timer for automatic recordingMetricsContext - Global registry (rarely used)validation.rs)Extensible content validation framework:
use TurboVault_core::validation::*;
// Create validators
let validator = CompositeValidator::new()
.add_validator(Box::new(
FrontmatterValidator::new().require_field("title")
))
.add_validator(Box::new(LinkValidator::new()))
.add_validator(Box::new(
ContentValidator::new()
.min_length(100)
.require_heading()
));
// Validate a file
let report = validator.validate(&file);
if !report.passed {
for issue in report.issues {
println!("[{}] {}: {}",
issue.severity,
issue.category,
issue.message
);
if let Some(suggestion) = issue.suggestion {
println!(" Suggestion: {}", suggestion);
}
}
}
Validators:
FrontmatterValidator - Required fields, tag format validationLinkValidator - Empty targets, suspicious URLs, fragment-only linksContentValidator - Length checks, required headingsCompositeValidator - Run multiple validatorsSeverity Levels:
Info - Informational messagesWarning - Should be addressed but not criticalError - Should be fixed (fails validation)Critical - Must be fixed (fails validation)profiles.rs)Pre-configured deployments for common use cases:
use TurboVault_core::profiles::ConfigProfile;
// Create profile-based configuration
let config = ConfigProfile::Production.create_config();
// Or get recommendation based on vault size
let profile = ConfigProfile::recommend(vault_size);
let config = profile.create_config();
Available Profiles:
Development - Verbose logging, all features enabled, metrics onProduction - Optimized for reliability and securityReadOnly - Search/analysis only, no write operationsHighPerformance - Tuned for large vaults (5000+ files)Minimal - Bare essentials onlyMultiVault - Multiple vault support with isolationCollaboration - Team features, webhooks, exportsresilience.rs)Patterns for graceful error handling:
use TurboVault_core::resilience::*;
// Retry with exponential backoff
let config = RetryConfig::conservative();
let result = retry_with_backoff(&config, || {
Box::pin(async {
vault_operation().await
})
}).await?;
// Circuit breaker for preventing cascading failures
let circuit_breaker = CircuitBreaker::new(
3, // failure threshold
2, // success threshold
Duration::from_secs(30) // timeout
);
if circuit_breaker.is_request_allowed() {
match operation().await {
Ok(result) => {
circuit_breaker.record_success();
Ok(result)
}
Err(e) => {
circuit_breaker.record_failure();
Err(e)
}
}
} else {
Err(Error::other("Circuit breaker open"))
}
Features:
use TurboVault_core::prelude::*;
// Configure a vault
let vault_config = VaultConfig::builder("my-vault", "/path/to/vault")
.as_default()
.build()?;
// Create server configuration
let mut server_config = ServerConfig::new();
server_config.vaults.push(vault_config);
server_config.validate()?;
// Create multi-vault manager
let manager = MultiVaultManager::new(server_config)?;
use TurboVault_core::models::*;
// Create a vault file
let metadata = FileMetadata {
path: PathBuf::from("notes/readme.md"),
size: 1024,
created_at: 1234567890.0,
modified_at: 1234567890.0,
checksum: "abc123".to_string(),
is_attachment: false,
};
let mut file = VaultFile::new(
PathBuf::from("notes/readme.md"),
content,
metadata
);
// Add parsed elements
file.headings.push(Heading {
text: "Introduction".to_string(),
level: 1,
position: SourcePosition::new(0, 0, 0, 14),
anchor: Some("introduction".to_string()),
});
file.links.push(Link::new(
LinkType::WikiLink,
PathBuf::from("notes/readme.md"),
"Other Note".to_string(),
SourcePosition::new(5, 10, 100, 20)
));
// Query parsed content
let outgoing = file.outgoing_links();
let has_rust_tag = file.has_tag("rust");
let blocks = file.blocks_with_ids();
All other TurboVault crates depend on turbovault-core:
cargo build -p turbovault-core
# Run all tests
cargo test -p turbovault-core
# Run with output
cargo test -p turbovault-core -- --nocapture
# Run specific test
cargo test -p turbovault-core test_vault_config_builder
# Generate and open docs
cargo doc -p turbovault-core --open
Configuration objects have many optional fields. Builders provide:
Traditional metrics use Mutex/RwLock which:
Lock-free atomics provide:
Using anyhow::Error loses type information. Custom Error enum provides:
Licensed under the same terms as the TurboVault project.