entertainarr-adapter-http 0.1.1

HTTP adapter for entertainarr
Documentation
use axum::routing::get;
use entertainarr_domain::tvshow::entity::{
    FindTvShowSeasonResponse, ListTvShowSeasonResponse, TvShowSeason,
};

use crate::entity::tvshow::{TvShowDocument, TvShowEntity, TvShowRelationships};
use crate::entity::tvshow_season::{
    TvShowSeasonAttributes, TvShowSeasonDocument, TvShowSeasonField, TvShowSeasonInclude,
    TvShowSeasonRelation, TvShowSeasonRelationships,
};
use crate::entity::tvshow_subscription::TvShowSubscriptionEntity;
use crate::entity::{ApiResource, Couple, Entity, Relation};
use crate::server::handler::prelude::FromDomainResponse;

mod find;
mod list_by_tvshow;

pub fn create<S>() -> axum::Router<S>
where
    S: crate::server::prelude::ServerState + Clone,
{
    axum::Router::new()
        .route("/tvshow-seasons/{season_id}", get(find::handle::<S>))
        .route(
            "/tvshows/{tvshow_id}/seasons",
            get(list_by_tvshow::handle::<S>),
        )
}

impl From<entertainarr_domain::tvshow::entity::TvShowSeasonField> for TvShowSeasonField {
    fn from(value: entertainarr_domain::tvshow::entity::TvShowSeasonField) -> Self {
        match value {
            entertainarr_domain::tvshow::entity::TvShowSeasonField::SeasonNumber => {
                Self::SeasonNumber
            }
        }
    }
}

impl From<TvShowSeasonField> for entertainarr_domain::tvshow::entity::TvShowSeasonField {
    fn from(value: TvShowSeasonField) -> Self {
        match value {
            TvShowSeasonField::SeasonNumber => Self::SeasonNumber,
        }
    }
}

impl From<TvShowSeason> for TvShowSeasonAttributes {
    fn from(value: TvShowSeason) -> Self {
        TvShowSeasonAttributes {
            source: value.source.into(),
            season_number: value.season_number,
            air_date: value.air_date,
            language: value.language.into(),
            name: value.name,
            overview: value.overview,
            poster_url: value.poster_url,
            created_at: value.created_at,
            updated_at: value.updated_at,
        }
    }
}

impl From<TvShowSeason> for TvShowSeasonDocument {
    fn from(value: TvShowSeason) -> Self {
        TvShowSeasonDocument {
            id: value.id,
            kind: Default::default(),
            relationships: TvShowSeasonRelationships {
                tvshow: Relation {
                    data: Some(TvShowEntity::new(value.tvshow_id)),
                    meta: (),
                },
            },
            attributes: value.into(),
        }
    }
}

impl FromDomainResponse<FindTvShowSeasonResponse, TvShowSeasonInclude>
    for ApiResource<TvShowSeasonDocument, TvShowSeasonRelation>
{
    fn from_response(
        response: FindTvShowSeasonResponse,
        required: std::collections::HashSet<TvShowSeasonInclude>,
    ) -> Self {
        let data = TvShowSeasonDocument {
            id: response.season.id,
            kind: Default::default(),
            relationships: TvShowSeasonRelationships {
                tvshow: Relation {
                    data: Some(TvShowEntity::new(response.tvshow.id)),
                    meta: (),
                },
            },
            attributes: response.season.into(),
        };

        let mut includes = Vec::with_capacity(1);
        if required.contains(&TvShowSeasonInclude::TvShow) {
            includes.push(TvShowSeasonRelation::TvShow(TvShowDocument {
                id: response.tvshow.id,
                kind: Default::default(),
                relationships: TvShowRelationships {
                    subscription: Relation {
                        data: response.subscription.map(|sub| {
                            TvShowSubscriptionEntity::new(Couple(sub.tvshow_id, sub.user_id))
                        }),
                        meta: (),
                    },
                },
                attributes: response.tvshow.into(),
            }));
        }

        ApiResource { data, includes }
    }
}

impl FromDomainResponse<ListTvShowSeasonResponse, TvShowSeasonInclude>
    for ApiResource<Vec<TvShowSeasonDocument>, TvShowSeasonRelation>
{
    fn from_response(
        response: ListTvShowSeasonResponse,
        required: std::collections::HashSet<TvShowSeasonInclude>,
    ) -> Self {
        let data = response
            .seasons
            .into_iter()
            .map(|season| {
                let tvshow = response.tvshows.get(&season.tvshow_id);
                TvShowSeasonDocument {
                    id: season.id,
                    kind: Default::default(),
                    relationships: TvShowSeasonRelationships {
                        tvshow: Relation {
                            data: tvshow.map(|t| TvShowEntity::new(t.id)),
                            meta: (),
                        },
                    },
                    attributes: season.into(),
                }
            })
            .collect();
        let mut includes = Vec::new();
        if required.contains(&TvShowSeasonInclude::TvShow) {
            includes.extend(response.tvshows.into_values().map(|tvshow| {
                TvShowSeasonRelation::TvShow(TvShowDocument {
                    id: tvshow.id,
                    kind: Default::default(),
                    relationships: TvShowRelationships {
                        subscription: Relation {
                            data: response
                                .subscriptions
                                .get(&tvshow.id)
                                .map(|sub| Entity::new(Couple(sub.tvshow_id, sub.user_id))),
                            meta: (),
                        },
                    },
                    attributes: tvshow.into(),
                })
            }));
        }

        ApiResource { data, includes }
    }
}