diff --git a/Cargo.lock b/Cargo.lock index 1b3326b..f368e81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -970,6 +970,7 @@ dependencies = [ "maestro-protocol", "rand 0.8.6", "reqwest", + "rust-embed", "serde", "serde_json", "tempfile", @@ -1362,6 +1363,40 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rust-embed" +version = "8.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04113cb9355a377d83f06ef1f0a45b8ab8cd7d8b1288160717d66df5c7988d27" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0902e4c7c8e997159ab384e6d0fc91c221375f6894346ae107f47dd0f3ccaa" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bcdef0be6fe7f6fa333b1073c949729274b05f123a0ad7efcb8efd878e5c3b1" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc-hash" version = "2.1.2" @@ -1453,6 +1488,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "semver" version = "1.0.28" @@ -1545,6 +1589,17 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2107,6 +2162,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2267,6 +2332,15 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "windows-core" version = "0.62.2" diff --git a/Cargo.toml b/Cargo.toml index eb924b3..9d2b344 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ maestro-protocol = { path = "crates/maestro-protocol" } nix = { version = "0.29", default-features = false, features = ["term", "signal"] } rand = "0.8" reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "cookies"] } +rust-embed = "8" serde = { version = "1", features = ["derive"] } serde_json = "1" tempfile = "3" diff --git a/crates/maestro-registry/Cargo.toml b/crates/maestro-registry/Cargo.toml index d1edd6b..c73b628 100644 --- a/crates/maestro-registry/Cargo.toml +++ b/crates/maestro-registry/Cargo.toml @@ -22,6 +22,7 @@ futures-util.workspace = true jsonwebtoken.workspace = true maestro-protocol.workspace = true rand.workspace = true +rust-embed.workspace = true serde.workspace = true serde_json.workspace = true thiserror.workspace = true diff --git a/crates/maestro-registry/src/client_api.rs b/crates/maestro-registry/src/client_api.rs index fa1e946..23f8e1f 100644 --- a/crates/maestro-registry/src/client_api.rs +++ b/crates/maestro-registry/src/client_api.rs @@ -18,6 +18,7 @@ use uuid::Uuid; use crate::events::events_ws; use crate::jwt::issue_attach_jwt; use crate::state::{Registry, RegistryError, RPC_TIMEOUT}; +use crate::web_assets; /// Shared state plumbed into client-facing handlers. #[derive(Debug, Clone)] @@ -32,6 +33,7 @@ pub struct ClientApiState { pub fn routes(state: ClientApiState) -> Router { Router::new() .route("/", get(index)) + .route("/assets/*file", get(asset)) .route("/api/daemons", get(list_daemons)) .route("/api/sessions", get(list_sessions).post(create_session)) .route("/api/sessions/:id", axum::routing::delete(delete_session)) @@ -40,13 +42,12 @@ pub fn routes(state: ClientApiState) -> Router { .with_state(state) } -async fn index() -> impl IntoResponse { - // Placeholder until the real web bundle lands in NAP-218. - ( - [("content-type", "text/html; charset=utf-8")], - "
The web client is not bundled yet — see NAP-218.
", - ) +async fn index() -> Response { + web_assets::serve_index() +} + +async fn asset(Path(file): PathWeb bundle not built. Run pnpm --dir web install \
+ then pnpm --dir web build, then rebuild the registry.