1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use super::*;
use anyhow::anyhow;
use anyhow::Error;
use anyhow::Result;
use forky_fs::terminal;
use forky_fs::FsWatcher;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread::JoinHandle;
use std::time::Duration;
use tower_livereload::LiveReloadLayer;

pub type AnyhowJoinHandle = JoinHandle<Result<(), Error>>;

impl SweetCli {
	#[tokio::main]
	pub async fn run(&self) -> Result<()> {		
		if self.run_tests_mode.is_some() && !self.watch {
			self.run_once().await
		} else {
			// run in watch mode OR interactive
			self.run_forever().await
		}
	}
	
	async fn run_once(&self) -> Result<()> {
		terminal::print_forky();
		let server = self.server.clone();
		let _server = std::thread::spawn(move || -> Result<()> {
			server.serve_with_options(None)
		});
		let should_kill = || false;
		self.build_wasm(should_kill)?;
		let result = self.run_tests(should_kill).await?.unwrap();
		if result.did_fail() {
			Err(anyhow!("Tests failed"))
		} else {
			Ok(())
		}
	}
	
	async fn run_forever(&self) -> Result<()> {
		terminal::clear();
		terminal::print_forky();
		let server = self.server.clone();
		let livereload = LiveReloadLayer::new();
		let reload = livereload.reloader();
		let _server_handle = std::thread::spawn(move || -> Result<()> {
			println!(
				"Starting server at {}\n",
				server.address.to_string_pretty()
			);
			server.serve_with_reload(livereload)
		});

		let kill = Arc::new(Mutex::new(()));
		let kill2 = kill.clone();
		let should_kill = move || -> bool { kill2.try_lock().is_ok() };

		loop {
			let change_listener = self.get_change_listener(kill.clone());

			if let Err(err) = self.build_wasm(should_kill.clone()) {
				eprintln!("sweet cli - build failed: {:?}", err);
			} else {
				reload.reload();
				if self.run_tests_mode.is_some() {
					let _ = self.run_tests(should_kill.clone()).await?;
				}
			}
			//only joins in watch mode, otherwise block forever
			change_listener.join().unwrap()?;
		}
	}

	fn get_change_listener(&self, kill: Arc<Mutex<()>>) -> AnyhowJoinHandle {
		let kill2 = kill.clone();
		let listener = if self.watch {
			std::thread::spawn(move || -> Result<()> {
				let kill_lock = kill2.lock().unwrap();
				FsWatcher::default()
					.with_watch("**/*.rs")
					.with_ignore("**/target/**")
					.block()?;
				drop(kill_lock);
				Ok(())
			})
		} else {
			// otherwise lock mutex and loop forever
			std::thread::spawn(move || -> Result<()> {
				let _kill_lock = kill2.lock().unwrap();
				loop {
					std::thread::sleep(Duration::from_secs(1))
				}
			})
		};
		//wait for lock
		while kill.try_lock().is_ok() {
			std::thread::sleep(Duration::from_millis(1))
		}
		listener
	}
}