diff --git a/Cargo.lock b/Cargo.lock index 9791f9f..09b3457 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,9 +70,11 @@ dependencies = [ "askama_axum", "axum", "listenfd", + "notify", "serde", "tokio", "tower-http", + "tower-livereload", ] [[package]] @@ -868,6 +870,18 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + [[package]] name = "flate2" version = "1.0.30" @@ -920,6 +934,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "futf" version = "0.1.5" @@ -1540,6 +1563,26 @@ dependencies = [ "cfb", ] +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.13" @@ -1643,6 +1686,26 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "kuchikiki" version = "0.8.2" @@ -1857,6 +1920,18 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + [[package]] name = "mio" version = "1.0.1" @@ -1939,6 +2014,25 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.6.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio 0.8.11", + "walkdir", + "windows-sys 0.48.0", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2183,7 +2277,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.3", "smallvec", "windows-targets 0.52.6", ] @@ -2579,6 +2673,15 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.5.3" @@ -3022,7 +3125,7 @@ dependencies = [ "objc2-foundation", "objc2-quartz-core", "raw-window-handle 0.6.2", - "redox_syscall", + "redox_syscall 0.5.3", "wasm-bindgen", "web-sys", "windows-sys 0.52.0", @@ -3517,7 +3620,7 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio", + "mio 1.0.1", "pin-project-lite", "socket2", "tokio-macros", @@ -3665,6 +3768,20 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +[[package]] +name = "tower-livereload" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d7d9fecf1242d1c6a3cf8f7f3c2da94e6aac553bb7062ab6d03e16b9872fd0" +dependencies = [ + "bytes", + "http", + "http-body", + "pin-project-lite", + "tokio", + "tower", +] + [[package]] name = "tower-service" version = "0.3.2" diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml index 6a148fe..6adced3 100644 --- a/crates/app/Cargo.toml +++ b/crates/app/Cargo.toml @@ -8,7 +8,9 @@ askama = "0.12.1" askama_axum = "0.4.0" axum = "0.7.5" listenfd = "1.0.1" +notify = "6.1.1" serde = { version = "1.0.204", features = ["derive"] } tokio = { version = "1.39.1", features = ["macros", "rt-multi-thread"] } tower-http = { version = "0.5.2", features = ["fs"] } +tower-livereload = "0.9.3" diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index 507bcb9..30a3c20 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -1,14 +1,29 @@ use ::app::get_router; +use axum::http::Request; +use notify::Watcher; use std::env; use std::path::Path; use listenfd::ListenFd; use tokio::net::TcpListener; +use tower_livereload::LiveReloadLayer; + +fn not_htmx_predicate(req: &Request) -> bool { + !req.headers().contains_key("hx-request") +} #[tokio::main] async fn main() { let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let assets_path = Path::new(&manifest_dir).join("assets"); - let router = get_router(assets_path.as_path()); + let templates_path = Path::new(&manifest_dir).join("templates"); + + let livereload = LiveReloadLayer::new(); + let reloader = livereload.reloader(); + + let router = get_router(assets_path.as_path()).layer(livereload.request_predicate(not_htmx_predicate)); + + let mut watcher = notify::recommended_watcher(move |_| reloader.reload()).unwrap(); + watcher.watch(&templates_path, notify::RecursiveMode::Recursive).unwrap(); let mut listenfd = ListenFd::from_env(); let listener = match listenfd.take_tcp_listener(0).unwrap() { @@ -18,7 +33,7 @@ async fn main() { TcpListener::from_std(listener).unwrap() } // otherwise fall back to local listening - None => TcpListener::bind("127.0.0.1:3000").await.unwrap(), + None => TcpListener::bind("localhost:3000").await.unwrap(), }; println!("Listening on: http://{}", listener.local_addr().unwrap());