fob_graph/analysis/walker/
mod.rs1mod parser;
7mod traversal;
8mod validation;
9
10pub use validation::{PathTraversalError, normalize_and_validate_path, validate_path_within_cwd};
11
12use std::sync::Arc;
13
14use crate::collection::CollectionState;
15use crate::runtime::Runtime;
16
17use crate::analysis::config::AnalyzerConfig;
18use crate::analysis::resolver::ModuleResolver;
19
20#[derive(Debug, thiserror::Error)]
22pub enum WalkerError {
23 #[error("Failed to read file '{path}': {source}")]
24 ReadFile {
25 path: std::path::PathBuf,
26 #[source]
27 source: crate::runtime::RuntimeError,
28 },
29
30 #[error("Maximum depth exceeded: {depth}")]
31 MaxDepthExceeded { depth: usize },
32
33 #[error("Circular dependency detected: {path}")]
34 CircularDependency { path: std::path::PathBuf },
35
36 #[error("Failed to resolve module '{specifier}' from '{from}': {reason}")]
37 ResolutionFailed {
38 specifier: String,
39 from: std::path::PathBuf,
40 reason: String,
41 },
42
43 #[error("Failed to extract scripts from '{path}': {source}")]
44 ExtractionFailed {
45 path: std::path::PathBuf,
46 #[source]
47 source: crate::analysis::extractors::ExtractorError,
48 },
49
50 #[error("Path traversal detected: path '{path}' escapes from cwd '{cwd}'")]
51 PathTraversal {
52 path: std::path::PathBuf,
53 cwd: std::path::PathBuf,
54 },
55
56 #[error("Too many modules processed: {count} modules (max: {max} allowed)")]
57 TooManyModules { count: usize, max: usize },
58
59 #[error("File too large: {path} is {size} bytes (max: {max} bytes)")]
60 FileTooLarge {
61 path: std::path::PathBuf,
62 size: usize,
63 max: usize,
64 },
65}
66
67pub struct GraphWalker {
69 resolver: ModuleResolver,
70 config: AnalyzerConfig,
71}
72
73impl GraphWalker {
74 pub fn new(config: AnalyzerConfig) -> Self {
76 let resolver = ModuleResolver::new(config.clone());
77 Self { resolver, config }
78 }
79
80 pub async fn walk(&self, runtime: Arc<dyn Runtime>) -> Result<CollectionState, WalkerError> {
84 let traversal = traversal::Traversal::new(&self.resolver, &self.config);
85 traversal.traverse(runtime).await
86 }
87}