Skip to main content

tokenburn_web/
api.rs

1//! JSON and static routes.
2
3use topcoat::{
4    Result,
5    context::Cx,
6    router::{
7        content::{Css, Json},
8        query_params, route,
9    },
10};
11
12use crate::{data::load, params::UsageParams, style::CSS};
13
14/// The same report as JSON: `/api/report?tool=pi&bucket=daily`.
15#[route(GET "/api/report")]
16async fn report(cx: &Cx) -> Result<Json<Vec<tokenburn_core::ReportRow>>> {
17    let query = query_params::<UsageParams>(cx)?.to_query();
18    Ok(Json(
19        load(query, &Default::default(), tokenburn_core::Currency::USD)
20            .await
21            .report,
22    ))
23}
24
25/// Liveness probe.
26#[route(GET "/api/health")]
27async fn health() -> Result<Json<&'static str>> {
28    Ok(Json("ok"))
29}
30
31/// Every colour theme with its palette (the same ones the TUI and GUI offer).
32#[route(GET "/api/themes")]
33async fn themes() -> Result<Json<serde_json::Value>> {
34    Ok(Json(crate::theme::catalogue()))
35}
36
37#[route(GET "/style.css")]
38async fn style() -> Result<Css<&'static str>> {
39    Ok(Css(CSS))
40}
41
42/// Extra styling for the Cyberpunk theme, imported by the inline theme `<style>`.
43#[route(GET "/cyberpunk.css")]
44async fn cyberpunk_style() -> Result<Css<&'static str>> {
45    Ok(Css(crate::theme::CYBERPUNK_CSS))
46}