diff --git a/Cargo.toml b/Cargo.toml index cdd0740..a2754f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,9 @@ members = [ 'libarchive', 'libarchive3-sys' ] + +[profile.release] +lto = "fat" +codegen-units = 1 +panic = "abort" +strip = true diff --git a/server/Cargo.toml b/server/Cargo.toml index 68a7c6b..aeb0f48 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -22,9 +22,3 @@ tower-http = { version = "0.4.1", features = ["fs", "trace"] } tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } uuid = { version = "1.4.0", features = ["v4"] } - -[profile.release] -lto = "fat" -codegen-units = 1 -panic = "abort" -strip = true diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs index 982dc02..91a1023 100644 --- a/server/src/api/mod.rs +++ b/server/src/api/mod.rs @@ -1,33 +1,44 @@ -use axum::extract::{Query, State}; +mod pagination; + +use axum::extract::{Path, Query, State}; use axum::routing::get; use axum::Json; use axum::Router; use sea_orm::entity::EntityTrait; use sea_orm::query::QueryOrder; use sea_orm::PaginatorTrait; -use serde::Deserialize; + +use pagination::PaginatedResponse; use crate::db::entities::repo; -#[derive(Deserialize)] -pub struct Pagination { - page: Option, - per_page: Option, -} - pub fn router() -> Router { - Router::new().route("/repos", get(get_repos)) + Router::new() + .route("/repos", get(get_repos)) + .route("/repos/:id", get(get_single_repo)) } async fn get_repos( State(global): State, - Query(params): Query, -) -> crate::Result>> { + Query(pagination): Query, +) -> crate::Result>> { let repos = repo::Entity::find() .order_by_asc(repo::Column::Id) - .paginate(&global.db, params.per_page.unwrap_or(25)) - .fetch_page(params.page.unwrap_or(0)) + .paginate(&global.db, pagination.per_page.unwrap_or(25)) + .fetch_page(pagination.page.unwrap_or(1) - 1) .await?; - Ok(Json(repos)) + Ok(Json(pagination.res(repos))) +} + +async fn get_single_repo( + State(global): State, + Path(id): Path, +) -> crate::Result> { + let repo = repo::Entity::find_by_id(id) + .one(&global.db) + .await? + .ok_or(axum::http::StatusCode::NOT_FOUND)?; + + Ok(Json(repo)) } diff --git a/server/src/api/pagination.rs b/server/src/api/pagination.rs new file mode 100644 index 0000000..ae3812d --- /dev/null +++ b/server/src/api/pagination.rs @@ -0,0 +1,34 @@ +use axum::response::{IntoResponse, Response}; +use axum::Json; +use serde::{Deserialize, Serialize}; + +pub const DEFAULT_PAGE: u64 = 0; +pub const DEFAULT_PER_PAGE: u64 = 25; + +#[derive(Deserialize)] +pub struct Query { + pub page: Option, + pub per_page: Option, +} + +#[derive(Serialize)] +pub struct PaginatedResponse +where + T: for<'de> Serialize, +{ + pub page: u64, + pub per_page: u64, + pub count: usize, + pub items: Vec, +} + +impl Query { + pub fn res Serialize>(self, items: Vec) -> PaginatedResponse { + PaginatedResponse { + page: self.page.unwrap_or(DEFAULT_PAGE), + per_page: self.page.unwrap_or(DEFAULT_PER_PAGE), + count: items.len(), + items, + } + } +} diff --git a/server/src/error.rs b/server/src/error.rs index 8ff467a..a359572 100644 --- a/server/src/error.rs +++ b/server/src/error.rs @@ -12,6 +12,7 @@ pub enum ServerError { Axum(axum::Error), Status(StatusCode), Db(sea_orm::DbErr), + Status(StatusCode), } impl fmt::Display for ServerError { @@ -21,6 +22,7 @@ impl fmt::Display for ServerError { ServerError::Axum(err) => write!(fmt, "{}", err), ServerError::Status(status) => write!(fmt, "{}", status), ServerError::Db(err) => write!(fmt, "{}", err), + ServerError::Status(status) => write!(fmt, "{}", status), } } } @@ -39,6 +41,7 @@ impl IntoResponse for ServerError { StatusCode::NOT_FOUND.into_response() } ServerError::Db(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(), + ServerError::Status(status) => status.into_response(), } } } @@ -72,3 +75,9 @@ impl From for ServerError { ServerError::Db(err) } } + +impl From for ServerError { + fn from(status: StatusCode) -> Self { + ServerError::Status(status) + } +}