Skip to content

Commit 4e3847c

Browse files
authored
docs: replace basic example with comprehensive real-world examples (#9)
- Add complete workflow example showing workspace discovery, graph building, cycle detection, and report generation - Include visualization example demonstrating Mermaid and DOT output generation - Add filtering example for production-only dependency analysis - Include targeted analysis example for finding cycles in specific workspaces - Fix import paths for ConfigBuilder to use common module - Use proper API patterns (graph_builder.graph() instead of returning graph) - Add proper error handling with miette::IntoDiagnostic - Make all examples use realistic monorepo scenarios
1 parent 6c9dafe commit 4e3847c

File tree

6 files changed

+186
-52
lines changed

6 files changed

+186
-52
lines changed

src/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub trait FromCommand: Sized {
6666
fn from_command(command: crate::cli::Commands) -> Result<Self, crate::error::FerrisWheelError>;
6767
}
6868

69-
/// Macro to implement TryFrom<Commands> using FromCommand trait
69+
/// Macro to implement `TryFrom<Commands>` using [`FromCommand`] trait
7070
#[macro_export]
7171
macro_rules! impl_try_from_command {
7272
($config:ty) => {

src/detector/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
//! ## Example
2222
//!
2323
//! ```
24-
//! use cargo_ferris_wheel::ConfigBuilder;
24+
//! use cargo_ferris_wheel::common::ConfigBuilder;
2525
//! use cargo_ferris_wheel::detector::CycleDetector;
2626
//! use cargo_ferris_wheel::graph::{DependencyEdge, DependencyType, WorkspaceNode};
2727
//! use petgraph::graph::DiGraph;

src/graph/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
//! ## Example
2020
//!
2121
//! ```
22-
//! use cargo_ferris_wheel::ConfigBuilder;
22+
//! use cargo_ferris_wheel::common::ConfigBuilder;
2323
//! use cargo_ferris_wheel::graph::{DependencyEdge, DependencyType, GraphRenderer, WorkspaceNode};
2424
//! use petgraph::graph::DiGraph;
2525
//!

src/lib.rs

Lines changed: 181 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -14,66 +14,205 @@
1414
//!
1515
//! ## Usage
1616
//!
17-
//! The library can be used programmatically:
17+
//! ### Real-World Example: Analyzing a Rust Monorepo
1818
//!
19-
//! ```
20-
//! use std::collections::HashMap;
21-
//! use std::sync::Arc;
19+
//! ```no_run
20+
//! use std::path::PathBuf;
2221
//!
23-
//! use cargo_ferris_wheel::ConfigBuilder;
2422
//! use cargo_ferris_wheel::analyzer::WorkspaceAnalyzer;
2523
//! use cargo_ferris_wheel::detector::CycleDetector;
26-
//! use cargo_ferris_wheel::graph::{
27-
//! DependencyEdge, DependencyGraphBuilder, DependencyType, WorkspaceNode,
28-
//! };
24+
//! use cargo_ferris_wheel::graph::DependencyGraphBuilder;
25+
//! use cargo_ferris_wheel::reports::{HumanReportGenerator, JsonReportGenerator, ReportGenerator};
26+
//! use miette::IntoDiagnostic;
2927
//!
30-
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
31-
//! // Create a simple test scenario
28+
//! # fn main() -> miette::Result<()> {
29+
//! // Step 1: Discover all workspaces in your monorepo
3230
//! let mut analyzer = WorkspaceAnalyzer::new();
31+
//! let repo_root = PathBuf::from("/path/to/your/monorepo");
32+
//! analyzer.discover_workspaces(&[repo_root], None)?;
33+
//!
34+
//! println!("Found {} workspaces", analyzer.workspaces().len());
3335
//!
34-
//! // For testing, we'll manually add some workspace info
35-
//! // In real usage, you'd use analyzer.discover_workspaces()
36-
//! let mut graph = petgraph::graph::DiGraph::new();
37-
//!
38-
//! // Add some test nodes
39-
//! let ws1 = graph.add_node(
40-
//! WorkspaceNode::builder()
41-
//! .with_name("workspace-a".to_string())
42-
//! .with_crates(vec!["crate-a".to_string()])
43-
//! .build()
44-
//! .unwrap(),
36+
//! // Step 2: Build the dependency graph
37+
//! let mut graph_builder = DependencyGraphBuilder::new(
38+
//! false, // include dev dependencies
39+
//! false, // include build dependencies
40+
//! false, // include target-specific dependencies
4541
//! );
46-
//! let ws2 = graph.add_node(
47-
//! WorkspaceNode::builder()
48-
//! .with_name("workspace-b".to_string())
49-
//! .with_crates(vec!["crate-b".to_string()])
50-
//! .build()
51-
//! .unwrap(),
42+
//!
43+
//! graph_builder.build_cross_workspace_graph(
44+
//! analyzer.workspaces(),
45+
//! analyzer.crate_to_workspace(),
46+
//! None, // no progress reporter
47+
//! )?;
48+
//!
49+
//! // Step 3: Detect circular dependencies
50+
//! let mut detector = CycleDetector::new();
51+
//! detector.detect_cycles(graph_builder.graph())?;
52+
//!
53+
//! // Step 4: Generate reports
54+
//! if detector.has_cycles() {
55+
//! println!(
56+
//! "⚠️ Found {} circular dependencies!",
57+
//! detector.cycle_count()
58+
//! );
59+
//!
60+
//! // Human-readable report for console output
61+
//! let human_report = HumanReportGenerator::new(Some(5)); // show max 5 cycles
62+
//! println!("{}", human_report.generate_report(&detector)?);
63+
//!
64+
//! // JSON report for programmatic processing
65+
//! let json_report = JsonReportGenerator::new();
66+
//! let json_output = json_report.generate_report(&detector)?;
67+
//! std::fs::write("cycles.json", json_output).into_diagnostic()?;
68+
//! } else {
69+
//! println!("✅ No circular dependencies found!");
70+
//! }
71+
//! # Ok(())
72+
//! # }
73+
//! ```
74+
//!
75+
//! ### Example: Visualizing the Dependency Graph
76+
//!
77+
//! ```no_run
78+
//! use std::io::Write;
79+
//!
80+
//! use cargo_ferris_wheel::graph::GraphRenderer;
81+
//! use miette::IntoDiagnostic;
82+
//! # use std::path::PathBuf;
83+
//! # use cargo_ferris_wheel::{
84+
//! # analyzer::WorkspaceAnalyzer,
85+
//! # detector::CycleDetector,
86+
//! # graph::DependencyGraphBuilder,
87+
//! # };
88+
//!
89+
//! # fn main() -> miette::Result<()> {
90+
//! # let mut analyzer = WorkspaceAnalyzer::new();
91+
//! # analyzer.discover_workspaces(&[PathBuf::from(".")], None)?;
92+
//! # let mut graph_builder = DependencyGraphBuilder::new(false, false, false);
93+
//! # graph_builder.build_cross_workspace_graph(
94+
//! # analyzer.workspaces(),
95+
//! # analyzer.crate_to_workspace(),
96+
//! # None,
97+
//! # )?;
98+
//! # let mut detector = CycleDetector::new();
99+
//! # detector.detect_cycles(graph_builder.graph())?;
100+
//! // Create a visual representation of your dependency graph
101+
//! let renderer = GraphRenderer::new(
102+
//! true, // highlight cycles
103+
//! false, // don't show individual crate details
52104
//! );
53105
//!
54-
//! // Add a dependency
55-
//! graph.add_edge(
56-
//! ws1,
57-
//! ws2,
58-
//! DependencyEdge::builder()
59-
//! .with_from_crate("crate-a")
60-
//! .with_to_crate("crate-b")
61-
//! .with_dependency_type(DependencyType::Normal)
62-
//! .build()
63-
//! .unwrap(),
106+
//! // Generate a Mermaid diagram (great for documentation)
107+
//! let mut mermaid_output = Vec::new();
108+
//! renderer.render_mermaid(
109+
//! graph_builder.graph(),
110+
//! detector.cycles(),
111+
//! &mut mermaid_output,
112+
//! )?;
113+
//!
114+
//! std::fs::write("dependencies.mmd", mermaid_output).into_diagnostic()?;
115+
//!
116+
//! // Or generate a DOT file for Graphviz
117+
//! let mut dot_output = Vec::new();
118+
//! renderer.render_dot(graph_builder.graph(), detector.cycles(), &mut dot_output)?;
119+
//!
120+
//! std::fs::write("dependencies.dot", dot_output).into_diagnostic()?;
121+
//! # Ok(())
122+
//! # }
123+
//! ```
124+
//!
125+
//! ### Example: Filtering Dependencies
126+
//!
127+
//! ```no_run
128+
//! # use std::path::PathBuf;
129+
//! # use cargo_ferris_wheel::{
130+
//! # analyzer::WorkspaceAnalyzer,
131+
//! # detector::CycleDetector,
132+
//! # graph::DependencyGraphBuilder,
133+
//! # };
134+
//! # fn main() -> miette::Result<()> {
135+
//! # let mut analyzer = WorkspaceAnalyzer::new();
136+
//! # analyzer.discover_workspaces(&[PathBuf::from(".")], None)?;
137+
//! // Check only production dependencies (exclude dev and build deps)
138+
//! let mut graph_builder = DependencyGraphBuilder::new(
139+
//! true, // exclude dev dependencies
140+
//! true, // exclude build dependencies
141+
//! false, // include target-specific dependencies
64142
//! );
65143
//!
66-
//! // Detect cycles
144+
//! graph_builder.build_cross_workspace_graph(
145+
//! analyzer.workspaces(),
146+
//! analyzer.crate_to_workspace(),
147+
//! None,
148+
//! )?;
149+
//!
67150
//! let mut detector = CycleDetector::new();
68-
//! detector.detect_cycles(&graph)?;
151+
//! detector.detect_cycles(graph_builder.graph())?;
69152
//!
70-
//! assert!(!detector.has_cycles());
153+
//! println!("Production dependency cycles: {}", detector.cycle_count());
154+
//! # Ok(())
155+
//! # }
156+
//! ```
157+
//!
158+
//! ### Example: Analyzing Specific Workspaces
159+
//!
160+
//! ```no_run
161+
//! # use std::path::PathBuf;
162+
//! # use cargo_ferris_wheel::{
163+
//! # analyzer::WorkspaceAnalyzer,
164+
//! # detector::{CycleDetector, WorkspaceCycle},
165+
//! # graph::DependencyGraphBuilder,
166+
//! # };
167+
//! # fn main() -> miette::Result<()> {
168+
//! # let mut analyzer = WorkspaceAnalyzer::new();
169+
//! # analyzer.discover_workspaces(&[PathBuf::from(".")], None)?;
170+
//! # let mut graph_builder = DependencyGraphBuilder::new(false, false, false);
171+
//! # graph_builder.build_cross_workspace_graph(
172+
//! # analyzer.workspaces(),
173+
//! # analyzer.crate_to_workspace(),
174+
//! # None,
175+
//! # )?;
176+
//! # let mut detector = CycleDetector::new();
177+
//! # detector.detect_cycles(graph_builder.graph())?;
178+
//! // Find cycles involving a specific workspace
179+
//! let target_workspace = "backend-core";
180+
//!
181+
//! let cycles_with_target: Vec<&WorkspaceCycle> = detector
182+
//! .cycles()
183+
//! .iter()
184+
//! .filter(|cycle| {
185+
//! cycle
186+
//! .workspace_names()
187+
//! .contains(&target_workspace.to_string())
188+
//! })
189+
//! .collect();
190+
//!
191+
//! println!(
192+
//! "Found {} cycles involving {}",
193+
//! cycles_with_target.len(),
194+
//! target_workspace
195+
//! );
196+
//!
197+
//! for (i, cycle) in cycles_with_target.iter().enumerate() {
198+
//! println!("\nCycle #{}", i + 1);
199+
//! println!("Workspaces: {}", cycle.workspace_names().join(" → "));
200+
//!
201+
//! // Show specific crate-level dependencies
202+
//! for edge in cycle.edges() {
203+
//! println!(
204+
//! " {} → {} ({:?} dependency)",
205+
//! edge.from_crate(),
206+
//! edge.to_crate(),
207+
//! edge.dependency_type()
208+
//! );
209+
//! }
210+
//! }
71211
//! # Ok(())
72212
//! # }
73213
//! ```
74214
75215
// Private modules
76-
mod common;
77216
mod constants;
78217
mod dependency_filter;
79218
mod progress;
@@ -85,6 +224,7 @@ mod workspace_discovery;
85224
pub mod analyzer;
86225
pub mod cli;
87226
pub mod commands;
227+
pub mod common;
88228
pub mod config;
89229
pub mod core;
90230
pub mod detector;
@@ -93,12 +233,6 @@ pub mod executors;
93233
pub mod graph;
94234
pub mod reports;
95235

96-
// Re-export commonly used types
97-
pub use crate::common::ConfigBuilder;
98-
pub use crate::detector::{CycleEdge, WorkspaceCycle};
99-
pub use crate::error::FerrisWheelError;
100-
pub use crate::graph::{DependencyEdge, DependencyType, WorkspaceNode};
101-
102236
// Main entry point for the library
103237
pub fn run() -> miette::Result<()> {
104238
use clap::Parser;

tests/graph_renderer_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::io::Cursor;
44

5-
use cargo_ferris_wheel::ConfigBuilder;
5+
use cargo_ferris_wheel::common::ConfigBuilder;
66
use cargo_ferris_wheel::detector::WorkspaceCycle;
77
use cargo_ferris_wheel::graph::{DependencyEdge, DependencyType, GraphRenderer, WorkspaceNode};
88
use petgraph::graph::DiGraph;

tests/readme_example.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::io::Cursor;
44

5-
use cargo_ferris_wheel::ConfigBuilder;
5+
use cargo_ferris_wheel::common::ConfigBuilder;
66
use cargo_ferris_wheel::detector::{CycleDetector, WorkspaceCycle};
77
use cargo_ferris_wheel::graph::{DependencyEdge, DependencyType, GraphRenderer, WorkspaceNode};
88
use petgraph::graph::DiGraph;

0 commit comments

Comments
 (0)