fob_graph/
lib.rs

1//! # fob-graph
2//!
3//! Pure graph data structures for module dependency graphs.
4//!
5//! This crate provides the core graph primitives and `ModuleGraph` implementation
6//! without any I/O or analysis logic. It's designed to be lightweight and
7//! WASM-compatible.
8//!
9//! ## Overview
10//!
11//! `fob-graph` is the foundation for building module dependency graphs from
12//! JavaScript/TypeScript codebases. It provides:
13//!
14//! - **Pure Data Structures**: No I/O, no file system dependencies
15//! - **WASM-Compatible**: Can run in browser environments
16//! - **Thread-Safe**: Uses `Arc` for efficient shared ownership
17//! - **Memory Efficient**: Arena-based allocation where possible
18//! - **Type-Safe**: Strong typing for modules, imports, exports, and dependencies
19//!
20//! ## Architecture
21//!
22//! ```text
23//! ┌─────────────────────────────────────────────────────────────┐
24//! │                    ModuleGraph                              │
25//! │  (Arc-based, thread-safe, WASM-compatible)                  │
26//! └────────────────────┬────────────────────────────────────────┘
27//!                      │
28//!          ┌───────────┼───────────┐
29//!          │           │           │
30//!          ▼           ▼           ▼
31//!    ┌─────────┐ ┌─────────┐ ┌─────────┐
32//!    │ Module  │ │ Import  │ │ Export  │
33//!    │ (Node)  │ │ (Edge)  │ │ (Edge)  │
34//!    └─────────┘ └─────────┘ └─────────┘
35//!          │           │           │
36//!          └───────────┼───────────┘
37//!                      │
38//!                      ▼
39//!          ┌──────────────────────┐
40//!          │   SymbolTable        │
41//!          │   (Intra-file        │
42//!          │    analysis)         │
43//!          └──────────────────────┘
44//! ```
45//!
46//! ## Quick Start
47//!
48//! ### Building a Module Graph
49//!
50//! ```rust,no_run
51//! use fob_graph::{ModuleGraph, Module, ModuleId, SourceType};
52//! use std::path::PathBuf;
53//!
54//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
55//! // Create a new graph
56//! let graph = ModuleGraph::new()?;
57//!
58//! // Add a module
59//! let module_id = ModuleId::new("src/index.ts")?;
60//! let module = Module::builder(module_id.clone(), PathBuf::from("src/index.ts"), SourceType::TypeScript)
61//!     .entry(true)
62//!     .build();
63//!
64//! graph.add_module(module)?;
65//!
66//! // Query the graph
67//! let dependencies = graph.dependencies(&module_id)?;
68//! println!("Dependencies: {:?}", dependencies);
69//! # Ok(())
70//! # }
71//! ```
72//!
73//! ### Symbol Analysis
74//!
75//! ```rust,no_run
76//! use fob_graph::semantic::analyze_symbols;
77//! use fob_graph::{SourceType, SymbolTable};
78//!
79//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
80//! let source = r#"
81//!     const used = 42;
82//!     const unused = 100;
83//!     console.log(used);
84//! "#;
85//!
86//! let table: SymbolTable = analyze_symbols(source, "example.js", SourceType::JavaScript)?;
87//!
88//! // Find unused symbols
89//! let unused = table.unused_symbols();
90//! println!("Unused symbols: {:?}", unused);
91//! # Ok(())
92//! # }
93//! ```
94//!
95//! ## Extension Trait Pattern
96//!
97//! The crate uses extension traits to add functionality without modifying core types.
98//! Methods are organized into logical groups:
99//!
100//! - [`memory::queries`] - Query operations (dependencies, dependents, etc.)
101//! - [`memory::mutations`] - Modification operations (add module, add dependency)
102//! - [`memory::exports`] - Export analysis (unused exports, usage counts)
103//! - [`memory::symbols`] - Symbol-level analysis (unused symbols, statistics)
104//! - [`memory::chains`] - Dependency chain analysis (circular detection)
105//!
106//! ## Thread Safety
107//!
108//! `ModuleGraph` uses `Arc` internally for efficient shared ownership. Multiple threads
109//! can safely read from the graph concurrently. For modifications, use appropriate
110//! synchronization (e.g., `Mutex` or `RwLock`).
111//!
112//! ## WASM Compatibility
113//!
114//! The crate is designed to work in WASM environments:
115//! - No file system dependencies
116//! - No network dependencies
117//! - Pure Rust data structures
118//! - Compatible with `wasm-bindgen` and `wasm-pack`
119
120// Runtime abstraction (merged from fob-core)
121pub mod runtime;
122
123// Analysis functionality (merged from fob-analysis)
124#[path = "analysis/lib.rs"]
125pub mod analysis;
126
127// Core graph types and primitives
128mod class_enum_extraction;
129pub mod collection;
130pub mod dependency_chain;
131pub mod export;
132pub mod external_dep;
133pub mod framework_rules;
134pub mod from_collection;
135pub mod import;
136pub mod module;
137pub mod module_id;
138pub mod package_json;
139mod quality;
140pub mod semantic;
141pub mod span;
142pub mod statistics;
143pub mod symbol;
144
145// ModuleGraph implementation
146// In-memory implementation (WASM-compatible)
147mod memory;
148
149// Re-export ModuleGraph implementation
150pub use memory::{
151    ClassMemberInfo, EnumMemberInfo, ModuleGraph, NamespaceImportInfo, SideEffectImport,
152    TypeOnlyImport,
153};
154
155/// Output entry for unused exports.
156#[derive(Debug, Clone, PartialEq, Eq)]
157pub struct UnusedExport {
158    pub module_id: module_id::ModuleId,
159    pub export: export::Export,
160}
161
162pub use collection::{
163    CollectedExport, CollectedImport, CollectedImportSpecifier, CollectedModule, CollectionState,
164    parse_module_structure,
165};
166pub use dependency_chain::{ChainAnalysis, DependencyChain};
167pub use export::{Export, ExportKind};
168pub use external_dep::ExternalDependency;
169pub use framework_rules::FrameworkRule;
170pub use from_collection::CollectionGraphError;
171pub use import::{Import, ImportKind, ImportSpecifier};
172pub use module::{Module, SourceType};
173pub use module_id::{ModuleId, ModuleIdError};
174pub use package_json::{
175    DependencyCoverage, DependencyType, PackageJson, TypeCoverage, UnusedDependency,
176    extract_package_name,
177};
178pub use span::SourceSpan;
179pub use statistics::GraphStatistics;
180pub use symbol::{
181    ClassMemberMetadata, EnumMemberMetadata, EnumMemberValue, Symbol, SymbolKind, SymbolMetadata,
182    SymbolSpan, SymbolStatistics, SymbolTable, UnreachableCode, UnusedSymbol, Visibility,
183};
184
185// Re-export runtime types
186pub use runtime::{FileMetadata, Runtime, RuntimeError, RuntimeResult};
187
188// Platform-specific runtime implementations
189#[cfg(not(target_family = "wasm"))]
190pub use runtime::native::NativeRuntime;
191
192#[cfg(target_family = "wasm")]
193pub use runtime::wasm::WasmRuntime;
194
195// Test utilities (available in test builds)
196#[cfg(any(
197    all(any(test, doctest), not(target_family = "wasm")),
198    all(feature = "test-utils", not(target_family = "wasm"))
199))]
200pub use runtime::test_utils::TestRuntime;
201
202#[cfg(any(
203    all(any(test, doctest), not(target_family = "wasm")),
204    all(feature = "test-utils", not(target_family = "wasm"))
205))]
206pub mod test_utils {
207    pub use super::runtime::test_utils::*;
208}
209
210// Re-export analysis types (merged from fob-analysis)
211pub use analysis::{
212    AnalysisResult, AnalyzeError, AnalyzeOptions, Analyzer, CacheAnalysis, CacheEffectiveness,
213    Configured, ImportOutcome, ImportResolution, RenameEvent, RenamePhase, TransformationTrace,
214    Unconfigured, analyze, analyze_with_options,
215};
216
217// Re-export OXC foundation types for consistent version usage across workspace
218// These are commonly used types that appear in public APIs and cross crate boundaries
219pub mod oxc {
220    //! OXC (Oxidation Compiler) foundation types re-exported for workspace consistency.
221    //!
222    //! This ensures all workspace crates use the same OXC version for types that
223    //! cross crate boundaries. Specialized OXC crates (like `oxc_isolated_declarations`)
224    //! should still be imported directly by crates that need them.
225
226    /// Re-export allocator - required for all OXC AST operations
227    pub use oxc_allocator::Allocator;
228
229    /// Re-export AST types
230    pub use oxc_ast::ast;
231
232    /// Re-export AST visitor trait
233    pub use oxc_ast_visit::Visit;
234
235    /// Re-export span types for source location tracking
236    pub use oxc_span::{GetSpan, SourceType, Span};
237
238    /// Re-export parser for code analysis
239    pub use oxc_parser::{Parser, ParserReturn};
240
241    /// Re-export semantic analysis
242    pub use oxc_semantic::{ScopeFlags, SemanticBuilder};
243}
244
245/// Error types for fob operations.
246#[derive(Debug, thiserror::Error)]
247pub enum Error {
248    /// Invalid configuration provided.
249    #[error("Invalid configuration: {0}")]
250    InvalidConfig(String),
251
252    /// I/O error.
253    #[error("I/O error: {0}")]
254    Io(#[from] std::io::Error),
255
256    /// Analysis or graph operation error.
257    #[error("Operation error: {0}")]
258    Operation(String),
259}
260
261/// Result type alias for fob operations.
262pub type Result<T> = std::result::Result<T, Error>;
263
264#[cfg(test)]
265mod tests;