use serde::Deserialize;
use topcoat_core::context::Cx;
use topcoat_router::{
Body, Method, Methods, Path, PathBuf, Route, RouteFuture, RouteId,
content::Json,
error::rewrite,
request::{FromRequest, uri},
};
use crate::SignalValues;
pub(crate) const PAGE_ROUTE_PREFIX: &str = "/_topcoat/runtime/pages";
#[derive(Debug, Deserialize)]
struct PageRerunRequest {
#[serde(default)]
signals: SignalValues,
}
pub struct PageRerunRoute {
id: RouteId,
path: PathBuf,
}
impl PageRerunRoute {
#[must_use]
pub fn root() -> Self {
Self {
id: RouteId::new(),
path: Path::new(PAGE_ROUTE_PREFIX).to_owned(),
}
}
#[must_use]
pub fn nested() -> Self {
Self {
id: RouteId::new(),
path: Path::new(&format!("{PAGE_ROUTE_PREFIX}/{{*page}}")).to_owned(),
}
}
}
impl Route for PageRerunRoute {
fn id(&self) -> RouteId {
self.id
}
fn methods(&self) -> Methods<'_> {
Methods::Only(&[Method::POST])
}
fn path(&self) -> &Path {
&self.path
}
fn handle<'cx>(&'cx self, cx: &'cx Cx, body: Body) -> RouteFuture<'cx> {
Box::pin(async move {
let Json(request) = Json::<PageRerunRequest>::from_request(cx, body).await?;
let uri = uri(cx);
let mut target = match uri.path().strip_prefix(PAGE_ROUTE_PREFIX) {
Some(path) if !path.is_empty() => path.to_owned(),
_ => String::from("/"),
};
if let Some(query) = uri.query() {
target.push('?');
target.push_str(query);
}
Err(rewrite(target, Body::empty())
.method(Method::GET)
.cx(cx.with(request.signals))
.into())
})
}
}