364 lines
9.7 KiB
Markdown
364 lines
9.7 KiB
Markdown
|
|
# Tools Shared Rust Library
|
||
|
|
|
||
|
|
Shared utilities for all Tools ecosystem Rust CLIs.
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This library provides common functionality used across all Tools CLIs:
|
||
|
|
|
||
|
|
- **Configuration Discovery** - Automatic search for configuration files in standard locations
|
||
|
|
- **Manifest Management** - Track installed resources and their types
|
||
|
|
- **Database Path Resolution** - Smart database file location detection
|
||
|
|
- **Project Detection** - Auto-detect projects from `.project/` or `.vapora/`
|
||
|
|
- **Project Selection** - Interactive project picker with arrow keys
|
||
|
|
- **Database Migrations** - SQL migration discovery and execution
|
||
|
|
- **XDG Directories** - Cross-platform standard directory support
|
||
|
|
- **Global Database Support** - Multi-project database management
|
||
|
|
|
||
|
|
## Installation
|
||
|
|
|
||
|
|
Add to your `Cargo.toml`:
|
||
|
|
|
||
|
|
```toml
|
||
|
|
[dependencies]
|
||
|
|
tools-shared = { path = "../../shared/rust" }
|
||
|
|
```
|
||
|
|
|
||
|
|
From a tools CLI (e.g., `crates/tracking-cli`):
|
||
|
|
|
||
|
|
```toml
|
||
|
|
tools-shared = { path = "../../../shared/rust" }
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
### Configuration Discovery
|
||
|
|
|
||
|
|
Find configuration files automatically:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::find_config_path;
|
||
|
|
use std::path::PathBuf;
|
||
|
|
|
||
|
|
// Search for a config file (returns first found)
|
||
|
|
let config_path = find_config_path("tracking.toml");
|
||
|
|
|
||
|
|
match config_path {
|
||
|
|
Some(path) => println!("Using config: {}", path.display()),
|
||
|
|
None => println!("No config found"),
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Database Path Resolution
|
||
|
|
|
||
|
|
Find or create database paths:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::find_db_path;
|
||
|
|
|
||
|
|
// Automatically searches and returns PathBuf with fallback
|
||
|
|
let db_path = find_db_path("tracking.db");
|
||
|
|
// Returns: .project/tracking.db (with fallback to .project/ if not found)
|
||
|
|
|
||
|
|
println!("Database: {}", db_path.display());
|
||
|
|
```
|
||
|
|
|
||
|
|
### Manifest Management
|
||
|
|
|
||
|
|
Track installed resources (requires `manifest` feature):
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::{Manifest, ResourceType};
|
||
|
|
use std::path::Path;
|
||
|
|
|
||
|
|
// Load manifest
|
||
|
|
let manifest = Manifest::load(Path::new(".project/manifest.toml"))?;
|
||
|
|
|
||
|
|
// Check if config is enabled
|
||
|
|
if manifest.is_enabled("tracking") {
|
||
|
|
println!("Tracking is enabled");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get all enabled configs
|
||
|
|
for config in manifest.enabled_configs() {
|
||
|
|
println!("Using: {}", config.name);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Configuration Discovery Order
|
||
|
|
|
||
|
|
All Tools CLIs automatically search for configurations in this order:
|
||
|
|
|
||
|
|
1. **`.project/{name}`** - External projects using Tools (PRIORITY)
|
||
|
|
2. **`.vapora/{name}`** - VAPORA platform projects
|
||
|
|
3. **`.coder/{name}`** - Documentation tracking projects
|
||
|
|
4. **Current directory** - Fallback
|
||
|
|
|
||
|
|
The library uses **first found** - it stops searching once it finds a match.
|
||
|
|
|
||
|
|
## Examples
|
||
|
|
|
||
|
|
### In a CLI main.rs
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::find_db_path;
|
||
|
|
use std::path::PathBuf;
|
||
|
|
|
||
|
|
#[tokio::main]
|
||
|
|
async fn main() -> Result<()> {
|
||
|
|
// Resolve database path using smart search
|
||
|
|
let db_path = find_db_path("tracking.db");
|
||
|
|
let db_url = format!("sqlite:///{}", db_path.display());
|
||
|
|
|
||
|
|
// Initialize database
|
||
|
|
let db = TrackingDb::new(&db_url).await?;
|
||
|
|
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### With explicit fallback
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::find_config_path_or;
|
||
|
|
|
||
|
|
// Find config or use explicit default
|
||
|
|
let config = find_config_path_or("app.toml", "config/app.toml");
|
||
|
|
```
|
||
|
|
|
||
|
|
### Project Detection
|
||
|
|
|
||
|
|
Automatically detect projects from configuration files in the current working directory or parents:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::detect_project_from_cwd;
|
||
|
|
|
||
|
|
// Auto-detect project from CWD searching upward
|
||
|
|
if let Some(project) = detect_project_from_cwd("config.toml") {
|
||
|
|
println!("Project: {}", project.name);
|
||
|
|
println!("Config: {}", project.config_path.display());
|
||
|
|
println!("Root: {}", project.root_path.display());
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
The detection searches in this order:
|
||
|
|
1. `.project/lifecycle.toml` (Tools projects)
|
||
|
|
2. `.vapora/lifecycle.toml` (VAPORA projects)
|
||
|
|
3. Parent directories recursively
|
||
|
|
|
||
|
|
### Project Selection
|
||
|
|
|
||
|
|
Interactively select from a list of projects with arrow keys (requires `interactive` feature):
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::{select_project, SelectableProject};
|
||
|
|
|
||
|
|
let projects = vec![
|
||
|
|
SelectableProject {
|
||
|
|
id: "proj-1".to_string(),
|
||
|
|
name: "My Project".to_string(),
|
||
|
|
path: Some("/home/user/projects/my-project".to_string()),
|
||
|
|
metadata: Some("Phase: Development".to_string()),
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
match select_project(projects, "Select a project:", None) {
|
||
|
|
Ok(selected_id) => println!("Selected: {}", selected_id),
|
||
|
|
Err(e) => println!("Cancelled: {}", e),
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Database Migrations
|
||
|
|
|
||
|
|
Find and manage SQL migration files in `data/migration/`:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::{find_migration_files, run_migration_file, has_migration_directory};
|
||
|
|
|
||
|
|
// Find all migration files
|
||
|
|
let migrations = find_migration_files(".")?;
|
||
|
|
println!("Found {} migrations", migrations.len());
|
||
|
|
|
||
|
|
// Check if migration directory exists
|
||
|
|
if has_migration_directory(".") {
|
||
|
|
// Get migration file list
|
||
|
|
let filenames = list_migration_files(".")?;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Run a single migration
|
||
|
|
run_migration_file("migrations/001_initial.sql")?;
|
||
|
|
```
|
||
|
|
|
||
|
|
### XDG Directories
|
||
|
|
|
||
|
|
Cross-platform standard directory support:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::{tool_data_dir, tool_config_dir, tool_cache_dir, ensure_dir};
|
||
|
|
|
||
|
|
// Get standard directories
|
||
|
|
let data_dir = tool_data_dir("my-tool"); // ~/.local/share/tools/my-tool
|
||
|
|
let config_dir = tool_config_dir("my-tool"); // ~/.config/tools/my-tool
|
||
|
|
let cache_dir = tool_cache_dir("my-tool"); // ~/.cache/tools/my-tool
|
||
|
|
|
||
|
|
// Ensure directory exists
|
||
|
|
ensure_dir(&data_dir)?;
|
||
|
|
```
|
||
|
|
|
||
|
|
### Global Database Support
|
||
|
|
|
||
|
|
Use a single global database for multiple projects:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tools_shared::find_global_db_path;
|
||
|
|
|
||
|
|
// Get global database path
|
||
|
|
let global_db = find_global_db_path("my-tool");
|
||
|
|
// Returns: ~/.local/share/tools/my-tool/my-tool.db
|
||
|
|
```
|
||
|
|
|
||
|
|
## Features
|
||
|
|
|
||
|
|
### `config-discovery` (default)
|
||
|
|
|
||
|
|
Provides configuration file discovery utilities:
|
||
|
|
- `find_config_path(filename)` - Returns `Option<PathBuf>`
|
||
|
|
- `find_config_path_or(filename, default)` - Returns `PathBuf` with fallback
|
||
|
|
- `find_db_path(filename)` - Returns `PathBuf` for database files
|
||
|
|
- `find_config_path_warn_conflicts(filename)` - Warns if multiple config locations exist
|
||
|
|
|
||
|
|
### `interactive` (optional)
|
||
|
|
|
||
|
|
Enables interactive project selection with arrow keys:
|
||
|
|
- `select_project()` - Interactive project picker using inquire
|
||
|
|
- Requires `inquire` crate
|
||
|
|
|
||
|
|
Enable in `Cargo.toml`:
|
||
|
|
|
||
|
|
```toml
|
||
|
|
tools-shared = { path = "../../shared/rust", features = ["interactive"] }
|
||
|
|
```
|
||
|
|
|
||
|
|
### `manifest` (optional, requires serde, toml)
|
||
|
|
|
||
|
|
Provides manifest management:
|
||
|
|
- `Manifest` struct
|
||
|
|
- `ConfigEntry` struct
|
||
|
|
- `ResourceType` enum
|
||
|
|
- TOML serialization/deserialization
|
||
|
|
|
||
|
|
Enable in `Cargo.toml`:
|
||
|
|
|
||
|
|
```toml
|
||
|
|
tools-shared = { path = "../../shared/rust", features = ["manifest"] }
|
||
|
|
```
|
||
|
|
|
||
|
|
### Always Included
|
||
|
|
|
||
|
|
**Project Detection:**
|
||
|
|
- `DetectedProject` struct
|
||
|
|
- `detect_project_from_cwd(config_filename)` - Auto-detect from CWD
|
||
|
|
- `detect_project_from_path(path, config_filename)` - Auto-detect from specific path
|
||
|
|
- `load_last_project(tool_name)` - Load cached project selection
|
||
|
|
- `save_last_project(tool_name, project_id)` - Cache project selection
|
||
|
|
|
||
|
|
**Project Selection Helpers:**
|
||
|
|
- `SelectableProject` struct
|
||
|
|
- `format_project_option()` - Format project for display
|
||
|
|
|
||
|
|
**XDG Directories:**
|
||
|
|
- `tool_data_dir(tool_name)` - Standard data directory
|
||
|
|
- `tool_config_dir(tool_name)` - Standard config directory
|
||
|
|
- `tool_cache_dir(tool_name)` - Standard cache directory
|
||
|
|
- `ensure_dir(path)` - Create directory if needed
|
||
|
|
|
||
|
|
**Global Databases:**
|
||
|
|
- `find_global_db_path(tool_name)` - Get global database path
|
||
|
|
- `find_global_db_path_custom(tool_name, filename)` - Custom global database path
|
||
|
|
- `global_db_exists(tool_name)` - Check if global database exists
|
||
|
|
|
||
|
|
**Database Migrations:**
|
||
|
|
- `run_migration_file(file_path)` - Execute SQL migration from file
|
||
|
|
- `find_migration_files(root_path)` - Find all `.sql` files in `data/migration/`
|
||
|
|
- `list_migration_files(root_path)` - Get migration filenames only
|
||
|
|
- `migration_directory(root_path)` - Get migration directory path
|
||
|
|
- `has_migration_directory(root_path)` - Check if migration directory exists
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
Run tests:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# All tests
|
||
|
|
cargo test -p tools-shared
|
||
|
|
|
||
|
|
# Specific module
|
||
|
|
cargo test -p tools-shared config_finder::tests
|
||
|
|
|
||
|
|
# With output
|
||
|
|
cargo test -p tools-shared -- --nocapture
|
||
|
|
```
|
||
|
|
|
||
|
|
## Module Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
shared/rust/
|
||
|
|
├── lib.rs # Module exports
|
||
|
|
├── config_finder.rs # Configuration discovery
|
||
|
|
├── manifest_manager.rs # Manifest management
|
||
|
|
├── xdg.rs # XDG directories
|
||
|
|
├── global_db.rs # Global database paths
|
||
|
|
├── project_detection.rs # Project auto-detection
|
||
|
|
├── project_selector.rs # Interactive selection
|
||
|
|
├── db_migration.rs # SQL migrations
|
||
|
|
└── Cargo.toml # Package definition
|
||
|
|
```
|
||
|
|
|
||
|
|
## Integration Points
|
||
|
|
|
||
|
|
This library is used by all Tools ecosystem CLIs:
|
||
|
|
|
||
|
|
### Rust CLIs
|
||
|
|
- **syntaxis-cli** - All features (detection, selection, migrations, global DB)
|
||
|
|
- **tracking-cli** - Configuration discovery & database paths
|
||
|
|
- **doc-syntaxis-cli** - Configuration discovery & project detection
|
||
|
|
- **hello-tool** (example) - All features (detection, selection, migrations)
|
||
|
|
|
||
|
|
### Can Be Used By
|
||
|
|
- **presentation-generator** - Configuration discovery
|
||
|
|
- Any new Tools ecosystem CLI
|
||
|
|
|
||
|
|
## Maintenance
|
||
|
|
|
||
|
|
When updating the library:
|
||
|
|
|
||
|
|
1. Update version in `Cargo.toml`
|
||
|
|
2. Run tests: `cargo test -p tools-shared`
|
||
|
|
3. Check all CLIs still compile: `cargo check --workspace`
|
||
|
|
4. Update documentation
|
||
|
|
|
||
|
|
## API Stability
|
||
|
|
|
||
|
|
This library follows semantic versioning:
|
||
|
|
- Major version: Breaking changes to public API
|
||
|
|
- Minor version: New features, backward compatible
|
||
|
|
- Patch version: Bug fixes
|
||
|
|
|
||
|
|
Current version: 0.1.0 (experimental)
|
||
|
|
|
||
|
|
## Contributing
|
||
|
|
|
||
|
|
When adding new functionality:
|
||
|
|
|
||
|
|
1. Add to appropriate module (config_finder.rs or manifest_manager.rs)
|
||
|
|
2. Export from lib.rs
|
||
|
|
3. Add unit tests
|
||
|
|
4. Update this README
|
||
|
|
5. Verify all CLIs still compile
|
||
|
|
|
||
|
|
## License
|
||
|
|
|
||
|
|
MIT OR Apache-2.0
|
||
|
|
|
||
|
|
Same as all Tools projects.
|