diff --git a/.gitignore b/.gitignore index cd53400..b877dc5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # my gitignore todo.md .env +trash/ +.cargo/ # ---> Rust # Generated by Cargo diff --git a/Cargo.lock b/Cargo.lock index 98de303..e0841ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" +checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" dependencies = [ "axum-core", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 1a67224..c8c0b77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -axum = "0.8.6" +axum = "0.8.7" dotenvy = "0.15.7" serde = { version = "1.0.228", features = ["derive"] } sqlx = { version = "0.8.6", features = ["postgres", "runtime-tokio"] } diff --git a/compose.yaml b/compose.yaml index cf1d860..5fad67b 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,5 +1,5 @@ services: - database: + postgres: image: docker.io/postgres:17 environment: POSTGRES_DB: ${POSTGRES_DB} @@ -7,3 +7,7 @@ services: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - ${POSTGRES_PORT}:5432 + adminer: + image: docker.io/adminer + ports: + - 8080:8080 diff --git a/migrations/20251113124629_initial.down.sql b/migrations/20251113124629_initial.down.sql index b713899..e83fe11 100644 --- a/migrations/20251113124629_initial.down.sql +++ b/migrations/20251113124629_initial.down.sql @@ -1,2 +1 @@ --- Add down migration script here DROP TABLE games; diff --git a/migrations/20251113124629_initial.up.sql b/migrations/20251113124629_initial.up.sql index 0b298a7..4e9d9ec 100644 --- a/migrations/20251113124629_initial.up.sql +++ b/migrations/20251113124629_initial.up.sql @@ -1,5 +1,3 @@ --- Add up migration script here - CREATE TABLE games( id SERIAL PRIMARY KEY, name TEXT NOT NULL, diff --git a/src/database.rs b/src/database.rs index 214a520..87232c8 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,28 +1,25 @@ +use sqlx::PgPool; use std::env; -use sqlx::PgPool; - -pub async fn create_pool() -> PgPool { - PgPool::connect(&database_url()) - .await - .expect("Could not connect to database") +pub async fn create_pool() -> Result { + PgPool::connect(&database_url()?).await.map_err(Into::into) } -fn database_url() -> String { +fn database_url() -> Result { let _ = dotenvy::dotenv(); let database_url = format!( "postgres://{}:{}@{}:{}/{}", - env::var("POSTGRES_USER").unwrap(), - env::var("POSTGRES_PASSWORD").unwrap(), - env::var("POSTGRES_HOST").unwrap(), - env::var("POSTGRES_PORT").unwrap(), - env::var("POSTGRES_DB").unwrap(), + env::var("POSTGRES_USER")?, + env::var("POSTGRES_PASSWORD")?, + env::var("POSTGRES_HOST")?, + env::var("POSTGRES_PORT")?, + env::var("POSTGRES_DB")?, ); - if database_url != env::var("DATABASE_URL").unwrap() { - panic!("DATABASE_URL is not set correctly"); + if database_url != env::var("DATABASE_URL")? { + return Err("DATABASE_URL is not set correctly".into()); } - println!("DATABASE_URL={database_url}"); - database_url + println!("DATABASE_URL={}", database_url); + Ok(database_url) } diff --git a/src/main.rs b/src/main.rs index cc659dc..cc15f63 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +#![warn(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use tokio::net::TcpListener; mod app_state; @@ -8,17 +9,19 @@ mod router; use app_state::AppState; #[tokio::main] -async fn main() { +async fn main() -> Result<(), axum::BoxError> { let state = AppState { - pool: database::create_pool().await, + pool: database::create_pool().await?, }; - sqlx::migrate!().run(&state.pool).await.unwrap(); + sqlx::migrate!().run(&state.pool).await?; let addr = "127.0.0.1:8000"; - let listener = TcpListener::bind(addr).await.unwrap(); + let listener = TcpListener::bind(addr).await?; println!("Listening at {addr}"); - axum::serve(listener, router::router(state)).await.unwrap(); + axum::serve(listener, router::router(state)).await?; + + Ok(()) } diff --git a/src/router.rs b/src/router.rs index f782968..ca3b9f5 100644 --- a/src/router.rs +++ b/src/router.rs @@ -3,7 +3,7 @@ use axum::routing::{get, post}; use axum::{ Json, extract::{Path, State}, - response::IntoResponse, + http::StatusCode, }; use crate::app_state::AppState; @@ -16,19 +16,19 @@ pub fn router(state: AppState) -> axum::Router { .with_state(state) } -pub async fn games_list(State(state): State) -> impl IntoResponse { +pub async fn games_list(State(state): State) -> Result>, StatusCode> { let games: Vec = sqlx::query_file_as!(Game, "queries/get_all.sql") .fetch_all(&state.pool) .await - .unwrap(); + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - Json(games) + Ok(Json(games)) } pub async fn insert_game( State(state): State, Json(game): Json, -) -> impl IntoResponse { +) -> Result { sqlx::query_file!( "queries/insert.sql", game.name, @@ -40,16 +40,16 @@ pub async fn insert_game( ) .execute(&state.pool) .await - .unwrap(); + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - axum::http::StatusCode::CREATED + Ok(StatusCode::CREATED) } pub async fn update_game( State(state): State, Path(params): Path, Json(game): Json, -) -> impl IntoResponse { +) -> Result { sqlx::query_file!( "queries/update.sql", game.name, @@ -62,14 +62,19 @@ pub async fn update_game( ) .execute(&state.pool) .await - .unwrap(); + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + Ok(StatusCode::OK) } -pub async fn delete_game(State(state): State, Path(id): Path) -> impl IntoResponse { +pub async fn delete_game( + State(state): State, + Path(id): Path, +) -> Result { sqlx::query_file!("queries/delete.sql", id) .execute(&state.pool) .await - .unwrap(); + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - axum::http::StatusCode::OK + Ok(StatusCode::OK) }