Skip to content
//! Router assembly. Exactly one route is unauthenticated: `GET /health`.

pub(crate) mod apps;
pub(crate) mod jobs;

use axum::routing::{get, post};
use axum::{Json, Router, middleware};
use twice_core::{API_PREFIX, HealthResponse};

use crate::auth;
use crate::state::AppState;

/// Builds the full application router, mounted under [`API_PREFIX`].
pub(crate) fn router(state: AppState) -> Router {
    let protected = Router::new()
        .route("/apps", get(apps::list))
        .route("/apps/{host}/start", post(apps::start))
        .route("/apps/{host}/stop", post(apps::stop))
        .route("/apps/{host}/update", post(apps::update_image))
        .route("/infrastructure/apply", post(apps::apply_infrastructure))
        .route("/jobs", get(jobs::list))
        .route("/jobs/{id}", get(jobs::get_one))
        .route("/jobs/{id}/stream", get(jobs::stream))
        .route_layer(middleware::from_fn_with_state(
            std::sync::Arc::clone(&state.config),
            auth::require_api_key,
        ));

    let api = Router::new()
        .route("/health", get(health))
        .merge(protected)
        .with_state(state);

    Router::new().nest(API_PREFIX, api)
}

async fn health() -> Json<HealthResponse> {
    Json(HealthResponse {
        service: "twice".to_owned(),
        version: env!("CARGO_PKG_VERSION").to_owned(),
    })
}