mod routes; use axum::{Router, routing::{get, post}}; use common::{SongSearchService, SongService}; use persistence::SqliteRepositoryFactory; use routes::songs::{create_song, delete_song, get_song, list_songs, update_song}; use routes::tabs::{AppState, parse_tab}; use std::sync::Arc; use tower_http::cors::{Any, CorsLayer}; use ug_parser::{UgHtmlParser, UgTabFetcher}; #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); let database_url = std::env::var("DATABASE_URL") .unwrap_or_else(|_| "sqlite://./pocket-chords.db".into()); let repo = SqliteRepositoryFactory::create(&database_url) .await .expect("failed to connect to database"); let songs = SongService::new(Box::new(repo.clone())); let search = SongSearchService::new(Box::new(repo)); let state = Arc::new(AppState { fetcher: Box::new(UgTabFetcher::new()), parser: Box::new(UgHtmlParser), songs, search, }); let cors = CorsLayer::new() .allow_origin(Any) .allow_methods(Any) .allow_headers(Any); let app = Router::new() .route("/tabs/parse", post(parse_tab)) .route("/songs", post(create_song).get(list_songs)) .route("/songs/{id}", get(get_song).delete(delete_song).patch(update_song)) .layer(cors) .with_state(state); let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap(); tracing::info!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app).await.unwrap(); }