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. Upstream consumers can use `fob_bundler::oxc::*`
224 //! instead of importing oxc crates directly.
225 //!
226 //! # Example
227 //!
228 //! ```ignore
229 //! use fob_bundler::oxc::{Allocator, Parser, SourceType, Codegen};
230 //!
231 //! let allocator = Allocator::default();
232 //! let source = "const x = 1;";
233 //! let ret = Parser::new(&allocator, source, SourceType::mjs()).parse();
234 //! ```
235
236 // =========================================================================
237 // Core: Allocator & Spans
238 // =========================================================================
239
240 /// Arena allocator for AST nodes
241 pub use oxc_allocator::Allocator;
242
243 /// Span types for source location tracking
244 pub use oxc_span::{CompactStr, GetSpan, SourceType, Span};
245
246 // =========================================================================
247 // Parsing & AST
248 // =========================================================================
249
250 /// AST node types
251 pub use oxc_ast::ast;
252
253 /// AST visitor trait
254 pub use oxc_ast_visit::Visit;
255
256 /// JavaScript/TypeScript parser
257 pub use oxc_parser::{Parser, ParserReturn};
258
259 // =========================================================================
260 // Semantic Analysis
261 // =========================================================================
262
263 /// Semantic analysis (scopes, symbols, references)
264 pub use oxc_semantic::{
265 ScopeFlags, Semantic, SemanticBuilder, SemanticBuilderReturn, SymbolFlags,
266 };
267
268 // =========================================================================
269 // Code Generation
270 // =========================================================================
271
272 /// Code generator (AST to string)
273 pub use oxc_codegen::{Codegen, CodegenOptions, CodegenReturn};
274
275 // =========================================================================
276 // Minification
277 // =========================================================================
278
279 /// JavaScript minifier
280 pub use oxc_minifier::{Minifier, MinifierOptions, MinifierReturn};
281
282 // =========================================================================
283 // Transformation
284 // =========================================================================
285
286 /// AST transformer (JSX, TypeScript, etc.)
287 pub use oxc_transformer::{TransformOptions, Transformer};
288
289 /// AST traversal utilities
290 pub use oxc_traverse::{Traverse, TraverseCtx};
291
292 // =========================================================================
293 // TypeScript Declarations
294 // =========================================================================
295
296 /// Isolated declarations (.d.ts generation)
297 pub use oxc_isolated_declarations::{IsolatedDeclarations, IsolatedDeclarationsOptions};
298}
299
300/// Error types for fob operations.
301#[derive(Debug, thiserror::Error)]
302pub enum Error {
303 /// Invalid configuration provided.
304 #[error("Invalid configuration: {0}")]
305 InvalidConfig(String),
306
307 /// I/O error.
308 #[error("I/O error: {0}")]
309 Io(#[from] std::io::Error),
310
311 /// Analysis or graph operation error.
312 #[error("Operation error: {0}")]
313 Operation(String),
314}
315
316/// Result type alias for fob operations.
317pub type Result<T> = std::result::Result<T, Error>;
318
319#[cfg(test)]
320mod tests;