use tokio::net::TcpListener;
use crate::handlers;
use crate::{error::BuildError, state::AppState};
use axum::{
Router,
http::StatusCode,
routing::{get, post},
};
use molten_config::settings_parser::Settings;
use sea_orm::{Database, DatabaseConnection, DbErr};
pub struct Application {
listener: TcpListener,
state: AppState,
port: u16,
}
impl Application {
pub async fn build(config: Settings) -> Result<Self, BuildError> {
let db: DatabaseConnection = Self::get_db_connection(&config).await?;
tracing::info!("Connected to database: {}", &config.database.database_name);
let state = AppState::new(db);
let addr = format!("{}:{}", config.application.host, config.application.port);
tracing::info!("Listening on {}", addr);
let listener = TcpListener::bind(addr).await?;
let port = listener.local_addr().unwrap().port();
Ok(Self {
listener,
state,
port,
})
}
pub fn port(&self) -> u16 {
self.port
}
async fn get_db_connection(config: &Settings) -> Result<DatabaseConnection, DbErr> {
Database::connect(config.database.get_connect_options()).await
}
fn define_router(db: DatabaseConnection) -> Router {
let state = AppState::new(db);
Router::new()
.route("/health", get(|| async { StatusCode::OK }))
.route("/documents", post(handlers::create_document))
.route("/documents/{id}", get(handlers::get_document))
.route("/forms", post(handlers::create_form))
.route("/forms/{id}", get(handlers::get_form))
.route("/workflows", post(handlers::create_workflow))
.route("/workflows/{id}", get(handlers::get_workflow))
.with_state(state)
}
pub async fn run(self) -> Result<(), std::io::Error> {
let Application {
listener,
state,
port: _,
} = self;
let router = Self::define_router(state.db);
axum::serve(listener, router.into_make_service()).await
}
}