Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/knut

crates/knut-wasm-host/src/lib.rs

//! A wasm-bundle host: a directory of bytes and a stream of frames, handed to a
//! browser — and **nothing about what is in either**.
//!
//! ## What this crate is
//!
//! Something has to hand a browser (a) the bytes of a wasm bundle and (b) a live
//! stream of data for it to render. That job has no opinions in it, so this crate
//! has none: it does not know what a *component* is, what a *frame* contains, what
//! tool built the bundle, or what the files in it are called. Every one of those is
//! a string the caller passes in, and this crate's tests assert each comes back out
//! verbatim.
//!
//! It owns exactly four things:
//!
//! * **[`bundle`]** — open a directory at run time, validate it, refuse LOUDLY when
//!   it is missing or incomplete: every bad file by name, the directory looked in,
//!   and the caller's own recipe for producing them. Never a blank page.
//! * **[`media`]** — extension → content type, off a small honest table, with an
//!   unknown extension REFUSED rather than guessed.
//! * **[`entry`]** — `/` → the loader page, carrying the caller's component name
//!   and data URL.
//! * **[`sse`]** — a stream of already-encoded frame strings → `text/event-stream`,
//!   terminated by whatever terminal frame the caller sends.
//!
//! ## What it is not
//!
//! * It is **not a web framework**, and it does not bring one. The core's whole
//!   dependency set is hyper + http-body-util + tokio + bytes; [`WasmHost`] is a
//!   `hyper::service::Service` a hyper-based server mounts directly (korp's server
//!   is hyper under tonic and must not grow an axum). An [`axum::Router`] wrapper
//!   sits behind the optional `axum` feature for callers who already run one.
//! * It is **not a component library's server.** A GUI crate that grew an HTTP
//!   server would put every one of its consumers one feature flag away from a
//!   listening socket. The bytes get served from here instead, by something whose
//!   only job is serving bytes.
//!
//! ## Shape of a caller
//!
//! ```no_run
//! use knut_wasm_host::{BundleSpec, EntryPoint, WasmHost};
//!
//! let spec = BundleSpec::new(
//!     "myapp: the viewer bundle is not available.",
//!     ["index.html", "glue.js", "viewer_bg.wasm"],
//!     "build it with `cargo xtask wrap-wasm` and point --dist at the output",
//! )
//! .with_env_var("MYAPP_DIST");
//!
//! let host = WasmHost::new(
//!     spec.load_from_env(),
//!     EntryPoint::new("/index.html", "pipeline", "/events"),
//! );
//! // `host` is a `hyper::service::Service`; the caller's own data routes
//! // (`/events`, …) sit beside it.
//! ```
//!
//! [`axum::Router`]: https://docs.rs/axum/latest/axum/struct.Router.html

pub mod bundle;
pub mod entry;
pub mod media;
pub mod response;
pub mod service;
pub mod sse;

#[cfg(feature = "axum")]
pub mod axum_host;

pub use bundle::{Bundle, BundleError, BundleSpec, WASM_MAGIC};
pub use entry::{COMPONENT_PARAM, EVENTS_PARAM, EntryPoint};
pub use media::{MEDIA_TYPES, content_type, known_extensions};
pub use response::{HostBody, bytes_response, redirect_response, text_response};
pub use service::{WasmHost, relative_file};
pub use sse::{FrameSender, SSE_CONTENT_TYPE, SseBody, event_bytes, sse_channel};

#[cfg(feature = "axum")]
pub use axum_host::{router, sse_response};

#[cfg(test)]
mod tests;