Jesús Pérez 9cef9b8d57 refactor: consolidate configuration directories
Merge _configs/ into config/ for single configuration directory.
Update all path references.

Changes:
- Move _configs/* to config/
- Update .gitignore for new patterns
- No code references to _configs/ found

Impact: -1 root directory (layout_conventions.md compliance)
2025-12-26 18:36:23 +00:00
..

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:

[dependencies]
tools-shared = { path = "../../shared/rust" }

From a tools CLI (e.g., crates/tracking-cli):

tools-shared = { path = "../../../shared/rust" }

Usage

Configuration Discovery

Find configuration files automatically:

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:

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):

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

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

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:

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):

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/:

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:

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:

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:

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:

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:

# 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.