fob_graph/framework_rules/
trait_def.rs

1//! Framework rule trait definition for marking framework-convention exports.
2
3use crate::ModuleGraph;
4use crate::Result;
5use async_trait::async_trait;
6
7/// Framework-specific rule for marking exports as used by framework conventions.
8///
9/// Framework rules identify exports that appear unused but are actually consumed
10/// by framework magic (React hooks, Next.js data fetching, Vue composables, etc.).
11///
12/// # Example
13///
14/// ```rust,ignore
15/// use fob_graph::graph::{ModuleGraph, FrameworkRule};
16/// use async_trait::async_trait;
17///
18/// struct MyFrameworkRule;
19///
20/// #[async_trait]
21/// impl FrameworkRule for MyFrameworkRule {
22///     async fn apply(&self, graph: &ModuleGraph) -> Result<()> {
23///         let modules = graph.modules().await?;
24///         
25///         for module in modules {
26///             let mut updated = module.clone();
27///             let mut changed = false;
28///             
29///             for export in updated.exports.iter_mut() {
30///                 if export.name.starts_with("action_") {
31///                     export.mark_framework_used();
32///                     changed = true;
33///                 }
34///             }
35///             
36///             if changed {
37///                 graph.add_module(updated).await?;
38///             }
39///         }
40///         
41///         Ok(())
42///     }
43///
44///     fn name(&self) -> &'static str {
45///         "MyFrameworkRule"
46///     }
47///
48///     fn description(&self) -> &'static str {
49///         "Marks exports prefixed with 'action_' as framework-used"
50///     }
51/// }
52/// ```
53#[async_trait]
54pub trait FrameworkRule: Send + Sync {
55    /// Apply the rule to the module graph, marking exports as framework-used.
56    ///
57    /// This method receives immutable access to the graph and should:
58    /// 1. Load modules via `graph.modules().await?`
59    /// 2. Clone and modify modules that need changes
60    /// 3. Save modified modules back via `graph.add_module(module).await?`
61    ///
62    /// The async nature allows the database backend to handle concurrent updates safely.
63    async fn apply(&self, graph: &ModuleGraph) -> Result<()>;
64
65    /// Human-readable name for the rule (used in diagnostics).
66    fn name(&self) -> &'static str;
67
68    /// Description of what patterns this rule matches.
69    fn description(&self) -> &'static str;
70
71    /// Whether this rule should be enabled by default.
72    ///
73    /// Built-in rules return `true`, custom rules typically return `false`.
74    fn is_default(&self) -> bool {
75        false
76    }
77
78    /// Clone the rule into a boxed trait object.
79    ///
80    /// Required for storing rules in collections.
81    fn clone_box(&self) -> Box<dyn FrameworkRule>;
82}
83
84impl Clone for Box<dyn FrameworkRule> {
85    fn clone(&self) -> Self {
86        self.clone_box()
87    }
88}