diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..9385cf38 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[Makefile] +indent_style = tab +indent_size = 2 diff --git a/.gitignore b/.gitignore index e471ea71..921fbc10 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,8 @@ dhat-heap.json # Web # ####### dist + +# Plugins # +########### +crates/http-server/inline/* +!crates/http-server/inline/.gitkeep diff --git a/Cargo.lock b/Cargo.lock index 26a8e5fd..8b1b3831 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,7 +262,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -472,6 +472,27 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "drain_filter_polyfill" version = "0.1.3" @@ -1046,6 +1067,7 @@ dependencies = [ "async-trait", "bytes", "clap", + "dirs", "http 1.1.0", "http-body-util", "http-server-plugin", @@ -1468,7 +1490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1477,6 +1499,16 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.4.0", + "libc", +] + [[package]] name = "linear-map" version = "1.2.0" @@ -1769,6 +1801,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "overload" version = "0.1.1" @@ -1801,7 +1839,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2019,6 +2057,17 @@ dependencies = [ "bitflags 2.4.0", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.9.4" @@ -3206,7 +3255,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3217,7 +3266,7 @@ checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ "windows-result", "windows-strings", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3226,7 +3275,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3236,7 +3285,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ "windows-result", - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -3245,7 +3303,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3254,7 +3312,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -3263,28 +3336,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3297,24 +3388,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 9b693233..d9fb44ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ async-trait = "0.1.83" bytes = "1.7.1" chrono = "0.4.38" clap = "4.5.20" +dirs = "5.0.1" futures = "0.3.31" gloo = "0.11.0" gloo-file = "0.3.0" diff --git a/Justfile b/Justfile deleted file mode 100644 index e5ee366c..00000000 --- a/Justfile +++ /dev/null @@ -1,26 +0,0 @@ -# Prints this help message -default: - just --list - -# Builds for release -release: - cargo build --release --locked - -# Runs Bats E2E Tests -e2e: release - BIN=./target/release/http-server bats tests/e2e - -# Runs formatting tool against Leptos source -ui-fmt: - leptosfmt ./crates/web/src/**/*.rs - -# Runs File Explorer UI for Development -ui-dev: - cd ./crates/file-explorer-ui && trunk serve --config ./Trunk.toml - -# Builds File Explorer UI for Production -ui-build: - cd ./crates/file-explorer-ui && trunk build --release --locked --config ./Trunk.toml - -dev: ui-build - cargo b --all && cargo r diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..9640dcd6 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +.PHONY: default + +default: + @echo No default target. + +dev: ui-build plugin-build + cargo b --all && cargo r + +release: plugin-build + make -C ./crates/file-explorer-plugin release + +plugin-build: ui-release + make -C ./crates/file-explorer-plugin release + +ui-build: + make -C ./crates/file-explorer-ui build + +ui-dev: + @echo Starting File Explorer UI… + make -C ./crates/file-explorer-ui dev + +ui-fmt: + make -C ./crates/file-explorer-ui fmt + +ui-release: + make -C ./crates/file-explorer-ui release diff --git a/crates/file-explorer-plugin/Makefile b/crates/file-explorer-plugin/Makefile new file mode 100644 index 00000000..c14bde65 --- /dev/null +++ b/crates/file-explorer-plugin/Makefile @@ -0,0 +1,9 @@ +.PHONY: default + +default: + @echo No default target. + +release: + @echo Building file-explorer-plugin… + cargo b --release + cp ../../target/release/libfile_explorer_plugin.dylib ../http-server/inline/file_explorer.plugin.httprs diff --git a/crates/file-explorer-ui/Makefile b/crates/file-explorer-ui/Makefile new file mode 100644 index 00000000..b743e861 --- /dev/null +++ b/crates/file-explorer-ui/Makefile @@ -0,0 +1,17 @@ +.PHONY: default + +default: + @echo No default target. + +build: + trunk build --locked --config ./Trunk.toml + +dev: + trunk serve --config ./Trunk.toml + +fmt: + @leptosfmt --version >/dev/null 2>&1 || (echo "Error: leptosfmt is required."; exit 1) + leptosfmt ./src/**/*.rs + +release: + trunk build --release --locked --config ./Trunk.toml diff --git a/crates/file-explorer-ui/src/bin/main.rs b/crates/file-explorer-ui/src/bin/main.rs index 1c5d3504..8d47897f 100644 --- a/crates/file-explorer-ui/src/bin/main.rs +++ b/crates/file-explorer-ui/src/bin/main.rs @@ -4,6 +4,6 @@ use file_explorer_ui::App; fn main() { mount_to_body(|| { - view! { } + view! { } }) } diff --git a/crates/http-server/Cargo.toml b/crates/http-server/Cargo.toml index 39c71c8a..52053db7 100644 --- a/crates/http-server/Cargo.toml +++ b/crates/http-server/Cargo.toml @@ -25,6 +25,7 @@ anyhow = { workspace = true } async-trait = { workspace = true } bytes = { workspace = true } clap = { workspace = true, features = ["env", "derive", "std"] } +dirs = { workspace = true } http = { workspace = true } http-body-util = { workspace = true } hyper = { workspace = true } diff --git a/crates/http-server/Makefile b/crates/http-server/Makefile new file mode 100644 index 00000000..ca7565eb --- /dev/null +++ b/crates/http-server/Makefile @@ -0,0 +1,7 @@ +.PHONY: default + +default: + @echo No default target. + +release: + cargo b --release -p file-explorer-plugin diff --git a/crates/http-server/inline/.gitkeep b/crates/http-server/inline/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/crates/http-server/src/bin/cli/command/mod.rs b/crates/http-server/src/bin/cli/command/mod.rs index 82aed77e..f6084334 100644 --- a/crates/http-server/src/bin/cli/command/mod.rs +++ b/crates/http-server/src/bin/cli/command/mod.rs @@ -1,11 +1,15 @@ +mod setup; mod start; use clap::Parser; +use self::setup::SetupOpt; use self::start::StartOpt; #[derive(Debug, Parser)] pub enum Command { - /// Start the HTTP server + /// Setup the HTTP Server System Files + Setup(SetupOpt), + /// Start the HTTP Server Start(StartOpt), } diff --git a/crates/http-server/src/bin/cli/command/setup.rs b/crates/http-server/src/bin/cli/command/setup.rs new file mode 100644 index 00000000..75860148 --- /dev/null +++ b/crates/http-server/src/bin/cli/command/setup.rs @@ -0,0 +1,42 @@ +use std::fs::{create_dir_all, write}; + +use anyhow::Result; +use clap::Parser; + +use http_server_rs::{install_path, plugins_path, DEFAULT_PLUGIN_NAME, FILE_EXPLORER_PLUGIN_BYTES}; + +#[derive(Debug, Parser)] +pub struct SetupOpt {} + +impl SetupOpt { + pub fn exec(&self) -> Result<()> { + let http_server_install_path = install_path()?; + + if http_server_install_path.exists() { + println!("HTTP Server System Files already installed."); + } + + let plugins_path = plugins_path()?; + + if !plugins_path.exists() { + println!( + "Creating HTTP Server System Files at: {}", + http_server_install_path.display() + ); + create_dir_all(&plugins_path)?; + } + + let file_explorer_plugin_path = plugins_path.join(DEFAULT_PLUGIN_NAME); + + if !file_explorer_plugin_path.exists() { + println!( + "Installing File Explorer Plugin at: {}", + file_explorer_plugin_path.display() + ); + write(&file_explorer_plugin_path, FILE_EXPLORER_PLUGIN_BYTES)?; + } + + println!("HTTP Server Installed"); + Ok(()) + } +} diff --git a/crates/http-server/src/bin/main.rs b/crates/http-server/src/bin/main.rs index 63c2ddf2..80cf79ed 100644 --- a/crates/http-server/src/bin/main.rs +++ b/crates/http-server/src/bin/main.rs @@ -14,6 +14,7 @@ fn main() -> Result<()> { match args.command { Command::Start(opt) => opt.exec()?, + Command::Setup(opt) => opt.exec()?, } Ok(()) diff --git a/crates/http-server/src/lib.rs b/crates/http-server/src/lib.rs index 74f47ad3..553c9eb9 100644 --- a/crates/http-server/src/lib.rs +++ b/crates/http-server/src/lib.rs @@ -1 +1,27 @@ pub mod server; + +use std::path::PathBuf; + +use anyhow::{bail, Result}; +use dirs::home_dir; + +pub const HTTP_SERVER_HOME_DIRNAME: &str = ".http-server-rs"; +pub const HTTP_SERVER_PLUGINS_DIRNAME: &str = "plugins"; +pub const DEFAULT_PLUGIN_NAME: &str = "file_explorer.plugin.httprs"; +pub const FILE_EXPLORER_PLUGIN_BYTES: &[u8] = + include_bytes!("../inline/file_explorer.plugin.httprs"); + +pub fn install_path() -> Result { + let Some(home) = home_dir() else { + bail!("Failed to resolve Home Directory. Unable to install."); + }; + + Ok(home.join(HTTP_SERVER_HOME_DIRNAME)) +} + +pub fn plugins_path() -> Result { + let install_path = install_path()?; + let plugins_path = install_path.join(HTTP_SERVER_PLUGINS_DIRNAME); + + Ok(plugins_path) +} diff --git a/crates/http-server/src/server/mod.rs b/crates/http-server/src/server/mod.rs index deb36c23..7384f6d1 100644 --- a/crates/http-server/src/server/mod.rs +++ b/crates/http-server/src/server/mod.rs @@ -20,6 +20,8 @@ use tokio::runtime::Runtime; use tower::ServiceBuilder; use tower_http::cors::{Any, CorsLayer}; +use crate::plugins_path; + use self::config::Config; use self::plugin::ExternalFunctions; @@ -38,7 +40,7 @@ impl Server { let addr = SocketAddr::from((self.config.host, self.config.port)); let listener = TcpListener::bind(addr).await?; let functions = Arc::new(ExternalFunctions::new()); - let plugin_library = PathBuf::from_str("./target/debug/libfile_explorer_plugin.dylib")?; + let plugin_library = plugins_path()?.join("file_explorer.plugin.httprs"); let config = PathBuf::from_str("./config.toml")?; let handle = Arc::new(rt.handle().to_owned());