Reviewed-on: #26
This commit was merged in pull request #26.
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
[package]
|
||||
name = "api-types"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
uuid = { workspace = true }
|
||||
utoipa = { version = "5.5.0", features = ["axum_extras", "uuid"] }
|
||||
domain = { path = "../domain" }
|
||||
utoipa = { workspace = true, features = ["axum_extras", "uuid"] }
|
||||
domain = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -21,3 +21,9 @@ pub type ActivityFeedResponse = PaginatedResponse<crate::diary::FeedEntryDto>;
|
||||
pub type WatchlistResponse = PaginatedResponse<crate::watchlist::WatchlistEntryDto>;
|
||||
pub type PaginatedMovieHits = PaginatedResponse<crate::search::MovieSearchHitDto>;
|
||||
pub type PaginatedPersonHits = PaginatedResponse<crate::search::PersonSearchHitDto>;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct ErrorResponse {
|
||||
pub error: String,
|
||||
pub code: String,
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ pub mod diary;
|
||||
pub mod goals;
|
||||
pub mod import;
|
||||
pub mod insights;
|
||||
pub mod mappers;
|
||||
pub mod movies;
|
||||
pub mod rendering;
|
||||
pub mod search;
|
||||
|
||||
20
crates/api-types/src/mappers/diary.rs
Normal file
20
crates/api-types/src/mappers/diary.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use crate::FeedEntryDto;
|
||||
use domain::models::FeedEntry;
|
||||
|
||||
use super::movies::{movie_to_dto, review_to_dto};
|
||||
|
||||
pub fn feed_entry_to_dto(e: &FeedEntry) -> FeedEntryDto {
|
||||
use domain::models::ReviewSource;
|
||||
let actor_url = match e.review().source() {
|
||||
ReviewSource::Remote { actor_url } => Some(actor_url.clone()),
|
||||
ReviewSource::Local => None,
|
||||
};
|
||||
FeedEntryDto {
|
||||
movie: movie_to_dto(e.movie()),
|
||||
review: review_to_dto(e.review()),
|
||||
user_id: e.review().user_id().value(),
|
||||
user_display_name: e.user_display_name().to_string(),
|
||||
is_federated: e.review().is_remote(),
|
||||
actor_url,
|
||||
}
|
||||
}
|
||||
12
crates/api-types/src/mappers/goals.rs
Normal file
12
crates/api-types/src/mappers/goals.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use crate::GoalDto;
|
||||
|
||||
pub fn goal_with_progress_to_dto(g: &domain::models::GoalWithProgress) -> GoalDto {
|
||||
GoalDto {
|
||||
year: g.goal.year(),
|
||||
target_count: g.goal.target_count(),
|
||||
current_count: g.current_count,
|
||||
percentage: g.percentage(),
|
||||
is_complete: g.is_complete(),
|
||||
goal_type: g.goal.goal_type().clone(),
|
||||
}
|
||||
}
|
||||
9
crates/api-types/src/mappers/mod.rs
Normal file
9
crates/api-types/src/mappers/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
mod diary;
|
||||
mod goals;
|
||||
mod movies;
|
||||
mod search;
|
||||
|
||||
pub use diary::*;
|
||||
pub use goals::*;
|
||||
pub use movies::*;
|
||||
pub use search::*;
|
||||
50
crates/api-types/src/mappers/movies.rs
Normal file
50
crates/api-types/src/mappers/movies.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use crate::{DiaryEntryDto, MovieDto, ReviewDto};
|
||||
use domain::models::{DiaryEntry, Movie, MovieSummary, Review};
|
||||
|
||||
pub fn movie_to_dto(movie: &Movie) -> MovieDto {
|
||||
MovieDto {
|
||||
id: movie.id().value(),
|
||||
title: movie.title().value().to_string(),
|
||||
release_year: movie.release_year().value(),
|
||||
director: movie.director().map(|d| d.to_string()),
|
||||
poster_path: movie.poster_path().map(|p| p.value().to_string()),
|
||||
genres: vec![],
|
||||
runtime_minutes: None,
|
||||
original_language: None,
|
||||
overview: None,
|
||||
collection_name: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn summary_to_dto(summary: &MovieSummary) -> MovieDto {
|
||||
MovieDto {
|
||||
id: summary.movie.id().value(),
|
||||
title: summary.movie.title().value().to_string(),
|
||||
release_year: summary.movie.release_year().value(),
|
||||
director: summary.movie.director().map(|d| d.to_string()),
|
||||
poster_path: summary.movie.poster_path().map(|p| p.value().to_string()),
|
||||
genres: summary.genres.clone(),
|
||||
runtime_minutes: summary.runtime_minutes,
|
||||
original_language: summary.original_language.clone(),
|
||||
overview: summary.overview.clone(),
|
||||
collection_name: summary.collection_name.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn review_to_dto(review: &Review) -> ReviewDto {
|
||||
ReviewDto {
|
||||
id: review.id().value(),
|
||||
rating: review.rating().value(),
|
||||
comment: review.comment().map(|c| c.value().to_string()),
|
||||
watched_at: domain::value_objects::format_watched_at(review.watched_at()),
|
||||
watch_medium: review.watch_medium().copied(),
|
||||
spoilers: review.spoilers(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn entry_to_dto(entry: &DiaryEntry) -> DiaryEntryDto {
|
||||
DiaryEntryDto {
|
||||
movie: movie_to_dto(entry.movie()),
|
||||
review: review_to_dto(entry.review()),
|
||||
}
|
||||
}
|
||||
22
crates/api-types/src/mappers/search.rs
Normal file
22
crates/api-types/src/mappers/search.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use crate::search::PersonDto;
|
||||
use domain::models::person::Person;
|
||||
|
||||
pub fn person_to_dto(p: &Person) -> PersonDto {
|
||||
PersonDto {
|
||||
id: p.id().value(),
|
||||
external_id: p.external_id().value().to_string(),
|
||||
name: p.name().to_string(),
|
||||
known_for_department: p.known_for_department().map(str::to_string),
|
||||
profile_path: p.profile_path().map(str::to_string),
|
||||
biography: p.biography().map(str::to_string),
|
||||
birthday: p.birthday().map(|d| d.to_string()),
|
||||
deathday: p.deathday().map(|d| d.to_string()),
|
||||
place_of_birth: p.place_of_birth().map(str::to_string),
|
||||
also_known_as: p.also_known_as().to_vec(),
|
||||
homepage: p.homepage().map(str::to_string),
|
||||
imdb_url: p
|
||||
.imdb_id()
|
||||
.map(|id| format!("https://www.imdb.com/name/{id}")),
|
||||
enriched: p.enriched_at().is_some(),
|
||||
}
|
||||
}
|
||||
@@ -77,29 +77,3 @@ pub struct FollowRelationResponse {
|
||||
pub struct PendingCountResponse {
|
||||
pub count: usize,
|
||||
}
|
||||
|
||||
//todo: move out to separate file
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn follow_state_dto_serializes_to_lowercase_strings() {
|
||||
assert_eq!(
|
||||
serde_json::to_string(&FollowStateDto::None).unwrap(),
|
||||
"\"none\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&FollowStateDto::Pending).unwrap(),
|
||||
"\"pending\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&FollowStateDto::Accepted).unwrap(),
|
||||
"\"accepted\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&FollowStateDto::Rejected).unwrap(),
|
||||
"\"rejected\""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,8 @@ pub struct UserProfileResponse {
|
||||
pub goals: Option<Vec<GoalDto>>,
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub is_federated: bool,
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub is_service_account: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub handle: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -153,6 +155,11 @@ pub struct UpdateProfileFieldsRequest {
|
||||
pub fields: Vec<ProfileFieldDto>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, utoipa::ToSchema)]
|
||||
pub struct DeleteAccountRequest {
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct UserSettingsDto {
|
||||
pub federate_goals: bool,
|
||||
|
||||
21
crates/api-types/tests/social_dto_test.rs
Normal file
21
crates/api-types/tests/social_dto_test.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use api_types::social::FollowStateDto;
|
||||
|
||||
#[test]
|
||||
fn follow_state_dto_serializes_to_lowercase_strings() {
|
||||
assert_eq!(
|
||||
serde_json::to_string(&FollowStateDto::None).unwrap(),
|
||||
"\"none\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&FollowStateDto::Pending).unwrap(),
|
||||
"\"pending\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&FollowStateDto::Accepted).unwrap(),
|
||||
"\"accepted\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&FollowStateDto::Rejected).unwrap(),
|
||||
"\"rejected\""
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user