use actix_web::{
App, HttpResponse, HttpServer, Responder, get,
web::{self},
};
use db::Database;
use env_logger::Env;
use log::{info, warn};
mod assets;
mod auth;
mod config;
mod db;
mod view;
#[get("/health")]
async fn health() -> impl Responder {
HttpResponse::Ok()
}
#[get("/up")]
async fn up() -> impl Responder {
HttpResponse::Ok().finish()
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let config = config::from_env();
let log_filter = format!(
"{},libsql=warn,turso=warn,tracing::span=warn",
config.log_level()
);
env_logger::Builder::from_env(Env::default().default_filter_or(log_filter)).init();
info!("{config}");
let config = web::Data::new(config);
config.maybe_reset_database();
let db_path = config.db_path().to_string();
let db = Database::new(&db_path);
let auth_state = web::Data::new(auth::NotesContext::new(db));
{
let auth_state = auth_state.clone();
actix_web::rt::spawn(async move {
loop {
match auth_state.db().init_tables().await {
Ok(()) => {
info!("Database initialized successfully");
auth_state.set_initialized();
return;
}
Err(e) => {
warn!("Database init failed (will retry): {e}");
actix_web::rt::time::sleep(std::time::Duration::from_secs(1)).await;
}
}
}
});
}
let bind_address = config.address();
HttpServer::new(move || {
App::new()
.app_data(config.clone())
.app_data(auth_state.clone())
.service(health)
.service(up)
.service(assets::assets)
.service(view::auth::login_page)
.service(auth::handlers::login_handler)
.service(auth::handlers::logout_handler)
.service(auth::handlers::save_handler)
.service(auth::handlers::search_handler)
.service(auth::handlers::note_details_handler)
.service(auth::handlers::edit_note_handler)
.service(auth::handlers::delete_note_handler)
.service(view::dashboard::index)
.service(view::dashboard::save_page)
.service(view::dashboard::view_page)
.service(view::dashboard::search_card_handler)
})
.bind(bind_address)?
.run()
.await
}