From 7dd054f1c9d66d11a43a92e45a70d7aec84eb817 Mon Sep 17 00:00:00 2001 From: Nishant Arora <1895906+whizzzkid@users.noreply.github.com> Date: Thu, 29 Jan 2026 22:53:14 +0000 Subject: [PATCH] docs: add example projects for library usage Add two example projects demonstrating programmatic usage: examples/simple-analyze/: - Demonstrates analyze::process_text and process_input - Shows different AnalyzeInput variants (text, lines, file) - Examples with AutoApprove and DenyAll interaction modes examples/simple-doctor/: - Demonstrates doctor::run and doctor::list - Shows DoctorRunOptions modes (ci_mode, with_fixes, for_groups) - Example of inspecting PathRunResult Both examples are standalone Cargo projects with: - Cargo.toml with dx-scope dependency - main.rs with documented examples - README.md with usage instructions Co-Authored-By: Claude (global.anthropic.claude-opus-4-5-20251101-v1:0) --- examples/simple-analyze/Cargo.toml | 14 +++++ examples/simple-analyze/README.md | 53 ++++++++++++++++++ examples/simple-analyze/main.rs | 86 ++++++++++++++++++++++++++++++ examples/simple-doctor/Cargo.toml | 14 +++++ examples/simple-doctor/README.md | 37 +++++++++++++ examples/simple-doctor/main.rs | 59 ++++++++++++++++++++ 6 files changed, 263 insertions(+) create mode 100644 examples/simple-analyze/Cargo.toml create mode 100644 examples/simple-analyze/README.md create mode 100644 examples/simple-analyze/main.rs create mode 100644 examples/simple-doctor/Cargo.toml create mode 100644 examples/simple-doctor/README.md create mode 100644 examples/simple-doctor/main.rs diff --git a/examples/simple-analyze/Cargo.toml b/examples/simple-analyze/Cargo.toml new file mode 100644 index 0000000..2c055dd --- /dev/null +++ b/examples/simple-analyze/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "simple-analyze" +version = "0.1.0" +edition = "2021" +publish = false + +[[bin]] +name = "simple-analyze" +path = "main.rs" + +[dependencies] +dx-scope = { path = "../.." } +tokio = { version = "1", features = ["full"] } +anyhow = "1.0" diff --git a/examples/simple-analyze/README.md b/examples/simple-analyze/README.md new file mode 100644 index 0000000..5cc427a --- /dev/null +++ b/examples/simple-analyze/README.md @@ -0,0 +1,53 @@ +# Simple Analyze Example + +This example demonstrates how to use dx-scope's analyze functionality programmatically. + +## Running + +```bash +cd examples/simple-analyze +cargo run +``` + +## Features Demonstrated + +- Loading scope configuration with known errors +- Analyzing text strings directly +- Analyzing lines from a vector +- Analyzing files +- Using different interaction modes (AutoApprove, DenyAll) + +## Key Concepts + +### AnalyzeInput + +Specify where input comes from: + +- `AnalyzeInput::from_lines(vec)` - Analyze in-memory lines +- `AnalyzeInput::from_file(path)` - Analyze a file +- `AnalyzeInput::Stdin` - Analyze from stdin + +### AnalyzeOptions + +Configure the analysis: + +- `known_errors`: Map of known error patterns to detect +- `working_dir`: Directory to run fix commands in + +### UserInteraction + +Control how fixes are handled: + +- `AutoApprove` - Automatically apply all fixes (good for CI) +- `DenyAll` - Never apply fixes (good for dry-run) +- `InquireInteraction` - Interactive prompts (CLI only) + +### AnalyzeStatus + +The result indicates what happened: + +- `NoKnownErrorsFound` - Clean scan +- `KnownErrorFoundNoFixFound` - Error detected but no automatic fix +- `KnownErrorFoundUserDenied` - User declined the fix +- `KnownErrorFoundFixFailed` - Fix was attempted but failed +- `KnownErrorFoundFixSucceeded` - Error detected and fix applied successfully diff --git a/examples/simple-analyze/main.rs b/examples/simple-analyze/main.rs new file mode 100644 index 0000000..f569ed2 --- /dev/null +++ b/examples/simple-analyze/main.rs @@ -0,0 +1,86 @@ +//! Simple example of using dx-scope's analyze functionality as a library. +//! +//! This example demonstrates how to programmatically analyze text for +//! known errors without using the CLI. + +use dx_scope::analyze; +use dx_scope::{AnalyzeInput, AnalyzeOptions, AnalyzeStatus, AutoApprove, DenyAll}; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + // For this example, we'll use an empty config + // In a real application, you'd load config from your project + let working_dir = std::env::current_dir()?; + let config = dx_scope::FoundConfig::empty(working_dir); + + println!("Found {} known errors", config.known_error.len()); + println!(); + + // Create options for analysis + let options = AnalyzeOptions::new(config.known_error.clone(), config.working_dir.clone()); + + // Example 1: Analyze a string directly + println!("=== Example 1: Analyzing text with known error ==="); + let log_text = r#" +Building project... +Compiling dependencies... +error: disk is full +Build failed! + "#; + + let status = analyze::process_text(&options, log_text, &AutoApprove).await?; + print_status("Direct text analysis", status); + println!(); + + // Example 2: Analyze lines from a vector (auto-approve fixes) + println!("=== Example 2: Analyzing lines with auto-approve ==="); + let lines = vec![ + "Starting deployment...".to_string(), + "Connecting to server...".to_string(), + "error: connection timeout".to_string(), + "Deployment failed".to_string(), + ]; + + let input = AnalyzeInput::from_lines(lines); + let status = analyze::process_input(&options, input, &AutoApprove).await?; + print_status("Lines with auto-approve", status); + println!(); + + // Example 3: Analyze with DenyAll (dry-run mode) + println!("=== Example 3: Analyzing with DenyAll (no fixes) ==="); + let input = AnalyzeInput::from_lines(vec!["error: disk is full".to_string()]); + + let status = analyze::process_input(&options, input, &DenyAll).await?; + print_status("With DenyAll", status); + println!(); + + // Example 4: Analyze a file + println!("=== Example 4: Analyzing a file ==="); + // Create a temporary log file + let log_content = "Building...\nerror: something went wrong\nDone.\n"; + tokio::fs::write("/tmp/test.log", log_content).await?; + + let input = AnalyzeInput::from_file("/tmp/test.log"); + let status = analyze::process_input(&options, input, &DenyAll).await?; + print_status("File analysis", status); + + // Clean up + tokio::fs::remove_file("/tmp/test.log").await?; + + Ok(()) +} + +fn print_status(label: &str, status: AnalyzeStatus) { + println!("{}: {:?}", label, status); + println!(" Exit code: {}", status.to_exit_code()); + + let message = match status { + AnalyzeStatus::NoKnownErrorsFound => "✓ No known errors detected", + AnalyzeStatus::KnownErrorFoundNoFixFound => "⚠ Error found, but no fix available", + AnalyzeStatus::KnownErrorFoundUserDenied => "⊘ Fix available but user declined", + AnalyzeStatus::KnownErrorFoundFixFailed => "✗ Fix attempted but failed", + AnalyzeStatus::KnownErrorFoundFixSucceeded => "✓ Error found and fixed!", + }; + + println!(" {}", message); +} diff --git a/examples/simple-doctor/Cargo.toml b/examples/simple-doctor/Cargo.toml new file mode 100644 index 0000000..a761a57 --- /dev/null +++ b/examples/simple-doctor/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "simple-doctor" +version = "0.1.0" +edition = "2021" +publish = false + +[[bin]] +name = "simple-doctor" +path = "main.rs" + +[dependencies] +dx-scope = { path = "../.." } +tokio = { version = "1", features = ["full"] } +anyhow = "1.0" diff --git a/examples/simple-doctor/README.md b/examples/simple-doctor/README.md new file mode 100644 index 0000000..a2ebc23 --- /dev/null +++ b/examples/simple-doctor/README.md @@ -0,0 +1,37 @@ +# Simple Doctor Example + +This example demonstrates how to use dx-scope's doctor functionality programmatically. + +## Running + +```bash +cd examples/simple-doctor +cargo run +``` + +## Features Demonstrated + +- Loading scope configuration +- Running health checks in CI mode (without fixes) +- Running specific groups with auto-fix enabled +- Listing available checks + +## Key Concepts + +### DoctorRunOptions + +Configure how doctor checks run: + +- `DoctorRunOptions::ci_mode()` - Run checks without applying fixes +- `DoctorRunOptions::with_fixes()` - Run checks and auto-apply fixes +- `DoctorRunOptions::for_groups(vec)` - Run only specific groups + +### PathRunResult + +The result contains: + +- `did_succeed`: Overall success/failure +- `succeeded_groups`: Set of group names that passed +- `failed_group`: Set of group names that failed +- `skipped_group`: Set of group names that were skipped +- `group_reports`: Detailed reports for each group diff --git a/examples/simple-doctor/main.rs b/examples/simple-doctor/main.rs new file mode 100644 index 0000000..f7de2de --- /dev/null +++ b/examples/simple-doctor/main.rs @@ -0,0 +1,59 @@ +//! Simple example of using dx-scope's doctor functionality as a library. +//! +//! This example demonstrates how to programmatically run health checks +//! without using the CLI. + +use dx_scope::DoctorRunOptions; +use dx_scope::doctor; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + // Load configuration from the current directory + println!("Loading scope configuration..."); + + // Note: For library usage, you can either: + // 1. Create an empty config and populate it programmatically + // 2. Load from disk using your own config loading logic + let working_dir = std::env::current_dir()?; + let config = dx_scope::FoundConfig::empty(working_dir); + + println!("Found {} doctor groups", config.doctor_group.len()); + println!(); + + // Option 1: Run all checks without fixes (CI mode) + println!("=== Running checks in CI mode (no fixes) ==="); + let ci_options = DoctorRunOptions::ci_mode(); + let result = doctor::run(&config, ci_options).await?; + + println!("✓ Succeeded: {}", result.succeeded_groups.len()); + println!("✗ Failed: {}", result.failed_group.len()); + println!("⊘ Skipped: {}", result.skipped_group.len()); + println!("Overall success: {}", result.did_succeed); + println!(); + + // Option 2: Run specific groups with auto-fix enabled + println!("=== Running specific groups with auto-fix ==="); + let targeted_options = DoctorRunOptions::for_groups(vec!["example-group".to_string()]); + + match doctor::run(&config, targeted_options).await { + Ok(result) => { + println!("Targeted run completed:"); + println!(" Succeeded: {:?}", result.succeeded_groups); + println!(" Failed: {:?}", result.failed_group); + } + Err(e) => { + println!("Run failed: {}", e); + } + } + + println!(); + println!("=== Listing available checks ==="); + let groups = doctor::list(&config).await?; + for group in groups { + println!("Group: {}", group.metadata.name()); + println!(" Description: {}", group.metadata.description()); + println!(" Actions: {}", group.actions.len()); + } + + Ok(()) +}