diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 54f6cf14..4215dda6 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -49,14 +49,28 @@ async fn main() { let cli = Cli::parse(); - let parent = Parent::new(OUTPUT_DIR.clone()).post_build(tailwind::execute); + let parent = Parent::new( + OUTPUT_DIR.clone(), + "cargo", + ["run", "--package", "builder", "--", OUTPUT_DIR.as_str()], + ) + .post_build(tailwind::execute); match cli.mode.unwrap_or_default() { Mode::Build => { parent.build().await.unwrap(); } Mode::Dev { open } => { - let error = parent.dev(open).await; + let error = parent + .dev( + [Utf8PathBuf::from_iter([ + env!("CARGO_MANIFEST_DIR"), + "..", + "builder", + ])], + open, + ) + .await; panic!("{error}"); } Mode::PrintOutputDir => print!("{}", OUTPUT_DIR.as_os_str().to_str().unwrap()), diff --git a/crates/reactive/src/driver/notify.rs b/crates/reactive/src/driver/notify.rs index db017864..58f6a8fd 100644 --- a/crates/reactive/src/driver/notify.rs +++ b/crates/reactive/src/driver/notify.rs @@ -16,7 +16,7 @@ pub use notify::{Error, Event, EventKind, Result}; pub struct FsChangeDriver { watcher: RecommendedWatcher, sender: mpsc::Sender>, - path: PathBuf, + paths: Vec, boo: PhantomData PathBuf>, } @@ -24,12 +24,12 @@ impl Driver for FsChangeDriver where PathBuf: From, { - type Args = T; + type Args = Vec; type ConstructionError = notify::Error; type Input = (); type Output = LocalBoxStream<'static, Result>; - fn new(path: Self::Args) -> Result<(Self, Self::Output)> { + fn new(paths: Self::Args) -> Result<(Self, Self::Output)> { let (sender, receiver) = mpsc::channel::>(1); let mut sender_clone = sender.clone(); @@ -42,7 +42,7 @@ where let fs_change_driver = Self { watcher, sender, - path: path.into(), + paths: paths.into_iter().map(Into::into).collect(), boo: PhantomData, }; @@ -50,10 +50,12 @@ where } fn init(mut self, _input: Self::Input) -> LocalBoxFuture<'static, ()> { - if let Err(error) = self.watcher.watch(&self.path, RecursiveMode::Recursive) { - block_on(self.sender.send(Err(error))).unwrap(); - return pending().boxed_local(); - }; + for path in self.paths { + if let Err(error) = self.watcher.watch(&path, RecursiveMode::Recursive) { + block_on(self.sender.send(Err(error))).unwrap(); + return pending().boxed_local(); + }; + } async move { let _watcher = self.watcher; diff --git a/crates/ssg-parent/src/lib.rs b/crates/ssg-parent/src/lib.rs index 1decf2c3..389f35a1 100644 --- a/crates/ssg-parent/src/lib.rs +++ b/crates/ssg-parent/src/lib.rs @@ -1,6 +1,10 @@ #![warn(clippy::all, clippy::pedantic)] -use camino::Utf8PathBuf; +use std::{ + ffi::{OsStr, OsString}, + path::PathBuf, +}; + use colored::Colorize; use futures::{ channel::mpsc, @@ -16,13 +20,16 @@ type PostBuildReturn = #[derive(derive_more::Debug)] #[must_use] pub struct Parent { + #[debug(skip)] + builder_command: OsString, + #[debug(skip)] + builder_args: Vec, output_dir: camino::Utf8PathBuf, builder: BuilderState, #[debug("{}", match post_build { None => "None", Some(_) => "Some(function)" })] post_build: Option PostBuildReturn>>, } -const BUILDER_CRATE_NAME: &str = "builder"; const LOCALHOST: &str = "localhost"; /// Error type returned from the reactive app @@ -74,9 +81,18 @@ pub enum BuildError { } impl Parent { - pub fn new(output_dir: impl Into) -> Self { + pub fn new( + output_dir: impl Into, + builder_command: impl AsRef + 'static, + builder_args: impl IntoIterator>, + ) -> Self { Self { output_dir: output_dir.into(), + builder_command: builder_command.as_ref().to_owned(), + builder_args: builder_args + .into_iter() + .map(|v| v.as_ref().to_owned()) + .collect::>(), builder: BuilderState::default(), post_build: None, } @@ -108,7 +124,11 @@ impl Parent { /// Sets up a development environment that watches the file system, /// recompiling the crate that when run describes the website on localhost when there are changes. - pub async fn dev(self, launch_browser: bool) -> DevError { + pub async fn dev( + self, + paths_to_watch: impl IntoIterator>, + launch_browser: bool, + ) -> DevError { let Some(port) = portpicker::pick_unused_port() else { return DevError::NoFreePort; }; @@ -129,15 +149,12 @@ impl Parent { let (open_browser_driver, browser_opened) = reactive::driver::open_that::StaticOpenThatDriver::new(url.to_string()); let (eprintln_driver, ()) = reactive::driver::println::EprintlnDriver::new(); - let (notify_driver, notify) = - match reactive::driver::notify::FsChangeDriver::new(Utf8PathBuf::from_iter([ - env!("CARGO_MANIFEST_DIR"), - "..", - BUILDER_CRATE_NAME, - ])) { - Ok(val) => val, - Err(e) => return e.into(), - }; + let (notify_driver, notify) = match reactive::driver::notify::FsChangeDriver::new( + paths_to_watch.into_iter().map(Into::into).collect(), + ) { + Ok(val) => val, + Err(e) => return e.into(), + }; let inputs = Inputs { server_task, @@ -178,17 +195,9 @@ impl Parent { } fn builder_command(&self) -> tokio::process::Command { - let mut cargo_run_builder = tokio::process::Command::new("cargo"); - - cargo_run_builder.args([ - "run", - "--package", - BUILDER_CRATE_NAME, - "--", - self.output_dir.as_str(), - ]); - - cargo_run_builder + let mut command = tokio::process::Command::new(&self.builder_command); + command.args(&self.builder_args); + command } fn input_event(&mut self, input: InputEvent) -> Option { @@ -404,12 +413,16 @@ impl Parent { #[cfg(test)] mod test { + use std::ffi::OsString; + use crate::{BuilderState, Parent}; #[test] fn parent_debug() { let parent_no_post_build = Parent { output_dir: camino::Utf8PathBuf::from("path/to/there"), + builder_command: OsString::new(), + builder_args: vec![], builder: BuilderState::default(), post_build: None, };