mod assets;
#[doc(hidden)]
pub use assets::{CSS_BUNDLER, SVG_SPRITE_BUNDLER};
pub(crate) use assets::{css_bundle_url, js_bundle_url, js_url, svg_sprite_url};
mod compression;
#[cfg(debug_assertions)]
mod hot_reload;
mod redirect_trailing_slash;
use std::fmt::Display;
use axum::Router;
use crate::{router::assets::assets_router, track::TrackConfig};
#[derive(Debug)]
pub enum Error {
Bundling(String),
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::Bundling(e) => write!(f, "bundling: {}", e),
}
}
}
impl std::error::Error for Error {}
#[derive(Debug, Clone, Default)]
pub struct Config {
pub track: Option<TrackConfig>,
}
impl Config {
pub fn track(mut self, track: TrackConfig) -> Self {
self.track = Some(track);
self
}
}
pub fn new<S: Clone + Send + Sync + 'static>(
actions_and_pages: Router<S>,
config: Config,
) -> Result<Router<S>, Error> {
let router = assets_router(config.track.as_ref())?;
#[cfg(debug_assertions)]
let router = router.merge(hot_reload::router());
let router = Router::new()
.nest("/cheers", router)
.merge(actions_and_pages);
let router = router.layer(axum::middleware::from_fn(
redirect_trailing_slash::redirect_trailing_slash,
));
let router = router.layer(axum::middleware::from_fn(
compression::compression_middleware,
));
Ok(router)
}
pub trait ActionDef {
const PATH: &'static str;
const METHOD: axum::http::Method;
}
pub trait Action<S, C = S>: ActionDef {
fn register(router: Router<S>) -> Router<S>;
}
pub trait ActionRouterExt<S, C = S>: Sized {
fn action<A>(self) -> Self
where
A: Action<S, C>;
}
impl<S, C> ActionRouterExt<S, C> for Router<S> {
fn action<A>(self) -> Self
where
A: Action<S, C>,
{
A::register(self)
}
}