Skip to main content

stacksdapp_watcher/
lib.rs

1use anyhow::Result;
2use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
3use std::path::Path;
4use std::time::Duration;
5use tokio::sync::mpsc;
6use tokio::time::timeout;
7
8pub async fn watch_contracts(contracts_dir: &Path) -> Result<()> {
9    let (tx, mut rx) = mpsc::channel(32);
10    let mut watcher = RecommendedWatcher::new(
11        move |res| {
12            let _ = tx.blocking_send(res);
13        },
14        Config::default().with_poll_interval(Duration::from_millis(500)),
15    )?;
16
17    watcher.watch(contracts_dir, RecursiveMode::Recursive)?;
18
19    const DEBOUNCE_MS: u64 = 300;
20
21    while let Some(event) = rx.recv().await {
22        if let Ok(e) = event {
23            if e.paths
24                .iter()
25                .any(|p| p.extension().map(|x| x == "clar").unwrap_or(false))
26            {
27                // Debounce bursts of save/write events before regenerating.
28                while let Ok(Some(next_event)) =
29                    timeout(Duration::from_millis(DEBOUNCE_MS), rx.recv()).await
30                {
31                    if let Ok(next) = next_event {
32                        let is_clar_change = next
33                            .paths
34                            .iter()
35                            .any(|p| p.extension().map(|x| x == "clar").unwrap_or(false));
36                        if !is_clar_change {
37                            continue;
38                        }
39                    }
40                }
41
42                println!("[watcher] .clar change detected — regenerating...");
43                if let Err(e) = stacksdapp_codegen::generate_all().await {
44                    eprintln!("[watcher] codegen error: {e}");
45                }
46            }
47        }
48    }
49
50    Ok(())
51}