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());