diff --git a/src/http.rs b/src/http.rs index 6593168..385cba0 100644 --- a/src/http.rs +++ b/src/http.rs @@ -1,6 +1,7 @@ //! HTTP networking: router wiring, server runtime, and the outbound HTTP client. pub mod error; +pub mod hal; pub mod handler; pub mod router; pub(crate) mod server; diff --git a/src/http/hal.rs b/src/http/hal.rs new file mode 100644 index 0000000..81b5998 --- /dev/null +++ b/src/http/hal.rs @@ -0,0 +1,81 @@ +//! HAL representations of subscriptions, served by the HTTP API. +//! +//! These types describe API responses only (they are never stored), +//! so they live in the HTTP layer instead of `model.rs`, +//! which holds the persistence and shared models they wrap. + +use schemars::JsonSchema; +use serde::Serialize; + +use crate::model::{SourceBranchInfo, Subscription, SubscriptionWithBranch}; + +/// HAL link structure. +#[derive(Serialize, JsonSchema)] +pub struct HalLink { + /// URL of the link. + pub href: String, +} + +/// HAL links for a subscription. +#[derive(Serialize, JsonSchema)] +pub struct SubscriptionLinks { + /// Self link. + #[serde(rename = "self")] + pub self_link: HalLink, + /// Update link. + pub update: HalLink, + /// Delete link. + pub delete: HalLink, +} + +/// HAL representation of a subscription. +#[derive(Serialize, JsonSchema)] +pub struct SubscriptionHal { + /// The subscription data. + #[serde(flatten)] + pub subscription: Subscription, + /// The source repository and branch. + pub source_branch: SourceBranchInfo, + /// HAL links. + #[serde(rename = "_links")] + pub links: SubscriptionLinks, +} + +/// HAL links for a subscription page. +#[derive(Serialize, JsonSchema)] +pub struct SubscriptionPageLinks { + /// Next page link. + pub next: Option, +} + +/// Paginated representation of subscriptions. +#[derive(Serialize, JsonSchema)] +pub struct SubscriptionPage { + /// The subscription data. + pub data: Vec, + /// Number of elements remaining after this page. + pub remaining_count: i64, + /// HAL links. + #[serde(rename = "_links")] + pub links: SubscriptionPageLinks, +} + +/// Maps a [`SubscriptionWithBranch`] to its HAL representation. +pub(super) fn map_to_hal(sub_with_branch: SubscriptionWithBranch) -> SubscriptionHal { + let id = sub_with_branch.subscription.id; + SubscriptionHal { + subscription: sub_with_branch.subscription, + source_branch: sub_with_branch.source_branch, + links: SubscriptionLinks { + self_link: HalLink { + href: format!("/subscriptions/{}", id), + }, + update: HalLink { + href: format!("/subscriptions/{}", id), + }, + delete: HalLink { + href: format!("/subscriptions/{}", id), + }, + }, + } +} diff --git a/src/http/handler.rs b/src/http/handler.rs index 0eddaf7..72941b0 100644 --- a/src/http/handler.rs +++ b/src/http/handler.rs @@ -17,28 +17,6 @@ pub use get::get_subscription; pub use list::list_subscriptions; pub use update::update_subscription; -use crate::model::{HalLink, SubscriptionHal, SubscriptionLinks, SubscriptionWithBranch}; - -/// Maps a [`SubscriptionWithBranch`] to its HAL representation. -fn map_to_hal(sub_with_branch: SubscriptionWithBranch) -> SubscriptionHal { - let id = sub_with_branch.subscription.id; - SubscriptionHal { - subscription: sub_with_branch.subscription, - source_branch: sub_with_branch.source_branch, - links: SubscriptionLinks { - self_link: HalLink { - href: format!("/subscriptions/{}", id), - }, - update: HalLink { - href: format!("/subscriptions/{}", id), - }, - delete: HalLink { - href: format!("/subscriptions/{}", id), - }, - }, - } -} - #[cfg(test)] mod tests { #![allow( diff --git a/src/http/handler/create.rs b/src/http/handler/create.rs index 0b515f1..d300536 100644 --- a/src/http/handler/create.rs +++ b/src/http/handler/create.rs @@ -1,9 +1,9 @@ //! Create a new subscription handler. -use super::map_to_hal; use crate::http::error::HandlerError; +use crate::http::hal::{SubscriptionHal, map_to_hal}; use crate::http::state::AppState; -use crate::model::{CreateSubscription, SubscriptionHal}; +use crate::model::CreateSubscription; use crate::repository::subscription::SubscriptionRepository; use axum::{Json, extract::State}; use rovo::rovo; diff --git a/src/http/handler/get.rs b/src/http/handler/get.rs index 2e6fe56..cb5e640 100644 --- a/src/http/handler/get.rs +++ b/src/http/handler/get.rs @@ -1,9 +1,8 @@ //! Get a single subscription handler. -use super::map_to_hal; use crate::http::error::HandlerError; +use crate::http::hal::{SubscriptionHal, map_to_hal}; use crate::http::state::AppState; -use crate::model::SubscriptionHal; use crate::repository::subscription::SubscriptionRepository; use axum::{ Json, diff --git a/src/http/handler/list.rs b/src/http/handler/list.rs index 898d9d7..2a59c5a 100644 --- a/src/http/handler/list.rs +++ b/src/http/handler/list.rs @@ -1,9 +1,10 @@ //! List subscriptions handler. -use super::map_to_hal; use crate::http::error::HandlerError; +use crate::http::hal::{ + HalLink, SubscriptionHal, SubscriptionPage, SubscriptionPageLinks, map_to_hal, +}; use crate::http::state::AppState; -use crate::model::{HalLink, SubscriptionHal, SubscriptionPage, SubscriptionPageLinks}; use crate::repository::subscription::SubscriptionRepository; use axum::{ Json, diff --git a/src/http/handler/update.rs b/src/http/handler/update.rs index 6e627d8..f49d4bd 100644 --- a/src/http/handler/update.rs +++ b/src/http/handler/update.rs @@ -1,9 +1,9 @@ //! Update an existing subscription handler. -use super::map_to_hal; use crate::http::error::HandlerError; +use crate::http::hal::{SubscriptionHal, map_to_hal}; use crate::http::state::AppState; -use crate::model::{SubscriptionHal, UpdateSubscription}; +use crate::model::UpdateSubscription; use crate::repository::subscription::SubscriptionRepository; use axum::{ Json, diff --git a/src/model.rs b/src/model.rs index 3cffc4d..852922a 100644 --- a/src/model.rs +++ b/src/model.rs @@ -3,15 +3,6 @@ //! The `Create_` `struct`s represent the payload //! to create the corresponding row. -// FIXME: Some docstrings have been duplicated. -// Maybe this problem can be solved by including an external Markdown file. -// For example: -// -// ```rust -// #[doc = include_str!("docs/my_struct.md")] -// pub struct MyStruct { ... } -// ``` - use crate::domain::{BranchName, CommitHash, EventType, RepoUrl, TargetRepo}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -84,44 +75,6 @@ pub struct SourceBranchInfo { pub name: BranchName, } -/// HAL links for a subscription page. -#[derive(Serialize, JsonSchema)] -pub struct SubscriptionPageLinks { - /// Next page link. - pub next: Option, -} - -/// Paginated representation of subscriptions. -#[derive(Serialize, JsonSchema)] -pub struct SubscriptionPage { - /// The subscription data. - pub data: Vec, - /// Number of elements remaining after this page. - pub remaining_count: i64, - /// HAL links. - #[serde(rename = "_links")] - pub links: SubscriptionPageLinks, -} - -/// HAL link structure. -#[derive(Serialize, JsonSchema)] -pub struct HalLink { - /// URL of the link. - pub href: String, -} - -/// HAL links for a subscription. -#[derive(Serialize, JsonSchema)] -pub struct SubscriptionLinks { - /// Self link. - #[serde(rename = "self")] - pub self_link: HalLink, - /// Update link. - pub update: HalLink, - /// Delete link. - pub delete: HalLink, -} - /// Combined subscription and branch information. #[derive(Debug, Serialize, JsonSchema)] pub struct SubscriptionWithBranch { @@ -132,19 +85,6 @@ pub struct SubscriptionWithBranch { pub source_branch: SourceBranchInfo, } -/// HAL representation of a subscription. -#[derive(Serialize, JsonSchema)] -pub struct SubscriptionHal { - /// The subscription data. - #[serde(flatten)] - pub subscription: Subscription, - /// The source repository and branch. - pub source_branch: SourceBranchInfo, - /// HAL links. - #[serde(rename = "_links")] - pub links: SubscriptionLinks, -} - /// Holds payload data for the creation of a [`Subscription`]. #[derive(Debug, Clone, Deserialize, JsonSchema)] pub struct CreateSubscription { @@ -157,18 +97,10 @@ pub struct CreateSubscription { /// The repository whose workflow needs to be triggered. pub target_repo: TargetRepo, - /// Identifies the specific [`repository_dispatch`] event. - /// - /// The values must contain at most 100 characters. - /// - /// - /// [`repository_dispatch`]: https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#repository_dispatch + /// The `repository_dispatch` event type (at most 100 characters). pub event_type: EventType, - /// Allows authenticating as a [GitHub App installation][gh_app_auth]. - /// - /// - /// [gh_app_auth]: https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation + /// The GitHub App installation used to authenticate the dispatch. pub gh_app_installation_id: i64, } @@ -178,18 +110,10 @@ pub struct UpdateSubscription { /// The repository whose workflow needs to be triggered. pub target_repo: Option, - /// Identifies the specific [`repository_dispatch`] event. - /// - /// The values must contain at most 100 characters. - /// - /// - /// [`repository_dispatch`]: https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#repository_dispatch + /// The `repository_dispatch` event type (at most 100 characters). pub event_type: Option, - /// Allows authenticating as a [GitHub App installation][gh_app_auth]. - /// - /// - /// [gh_app_auth]: https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation + /// The GitHub App installation used to authenticate the dispatch. pub gh_app_installation_id: Option, } @@ -208,16 +132,10 @@ pub struct TriggerQueueItem { /// The repository whose workflow needs to be triggered. pub target_repo: TargetRepo, - /// Identifies the specific [`repository_dispatch`] event. - /// - /// - /// [`repository_dispatch`]: https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#repository_dispatch + /// The `repository_dispatch` event type (at most 100 characters). pub event_type: EventType, - /// Allows authenticating as a [GitHub App installation][gh_app_auth]. - /// - /// - /// [gh_app_auth]: https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation + /// The GitHub App installation used to authenticate the dispatch. pub gh_app_installation_id: i64, /// Number of times the task has been attempted.