From ca1c8ab34716a6a1bdc11a57926b0bfbb6c20781 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 29 Jun 2026 21:10:24 +0100 Subject: [PATCH 1/3] refactor(api): align v1 namespace and move conversion tests #1959 Part A: Move misplaced tests - Move conversion unit tests from axum-rest-api-server to rest-api-runtime-adapter::v1::conversion (tests belong with the production code they exercise) - Add torrust-clock dev-dependency to rest-api-runtime-adapter - Remove empty peer.rs stub (only doc comment, no code) - Clean up resources/mod.rs module declaration Part B: Align v1 namespace - Add v1/ module to rest-api-application, move ports/ and use_cases/ under it - Add v1/ module to rest-api-runtime-adapter, move adapters/, container.rs, conversion.rs under it - Update all internal crate:: paths - Update all cross-package imports across workspace (axum-rest-api-server, src/bootstrap, src/container) --- Cargo.lock | 1 + packages/axum-rest-api-server/src/routes.rs | 2 +- packages/axum-rest-api-server/src/server.rs | 4 +- .../src/testing/environment.rs | 2 +- .../src/v1/context/auth_key/handlers.rs | 2 +- .../src/v1/context/auth_key/routes.rs | 2 +- .../src/v1/context/stats/handlers.rs | 2 +- .../src/v1/context/stats/routes.rs | 2 +- .../src/v1/context/torrent/handlers.rs | 2 +- .../src/v1/context/torrent/resources/mod.rs | 1 - .../src/v1/context/torrent/resources/peer.rs | 3 - .../v1/context/torrent/resources/torrent.rs | 64 ------------------- .../src/v1/context/torrent/routes.rs | 2 +- .../src/v1/context/whitelist/handlers.rs | 2 +- .../src/v1/context/whitelist/routes.rs | 2 +- .../axum-rest-api-server/src/v1/routes.rs | 18 +++--- .../server/v1/contract/context/torrent.rs | 2 +- packages/rest-api-application/src/lib.rs | 3 +- packages/rest-api-application/src/v1/mod.rs | 5 ++ .../src/{ => v1}/ports/auth_key.rs | 0 .../src/{ => v1}/ports/mod.rs | 0 .../src/{ => v1}/ports/stats.rs | 0 .../src/{ => v1}/ports/torrent.rs | 0 .../src/{ => v1}/ports/whitelist.rs | 0 .../src/{ => v1}/use_cases/auth_key.rs | 2 +- .../src/{ => v1}/use_cases/mod.rs | 0 .../src/{ => v1}/use_cases/stats.rs | 2 +- .../src/{ => v1}/use_cases/torrent.rs | 2 +- .../src/{ => v1}/use_cases/whitelist.rs | 2 +- packages/rest-api-runtime-adapter/Cargo.toml | 3 + packages/rest-api-runtime-adapter/src/lib.rs | 4 +- .../src/{ => v1}/adapters/auth_key.rs | 2 +- .../src/{ => v1}/adapters/mod.rs | 0 .../src/{ => v1}/adapters/stats.rs | 2 +- .../src/{ => v1}/adapters/torrent.rs | 2 +- .../src/{ => v1}/adapters/whitelist.rs | 2 +- .../src/{ => v1}/container.rs | 0 .../src/{ => v1}/conversion.rs | 64 +++++++++++++++++++ .../rest-api-runtime-adapter/src/v1/mod.rs | 7 ++ src/bootstrap/jobs/tracker_apis.rs | 4 +- src/container.rs | 2 +- 41 files changed, 115 insertions(+), 106 deletions(-) delete mode 100644 packages/axum-rest-api-server/src/v1/context/torrent/resources/peer.rs create mode 100644 packages/rest-api-application/src/v1/mod.rs rename packages/rest-api-application/src/{ => v1}/ports/auth_key.rs (100%) rename packages/rest-api-application/src/{ => v1}/ports/mod.rs (100%) rename packages/rest-api-application/src/{ => v1}/ports/stats.rs (100%) rename packages/rest-api-application/src/{ => v1}/ports/torrent.rs (100%) rename packages/rest-api-application/src/{ => v1}/ports/whitelist.rs (100%) rename packages/rest-api-application/src/{ => v1}/use_cases/auth_key.rs (97%) rename packages/rest-api-application/src/{ => v1}/use_cases/mod.rs (100%) rename packages/rest-api-application/src/{ => v1}/use_cases/stats.rs (95%) rename packages/rest-api-application/src/{ => v1}/use_cases/torrent.rs (96%) rename packages/rest-api-application/src/{ => v1}/use_cases/whitelist.rs (96%) rename packages/rest-api-runtime-adapter/src/{ => v1}/adapters/auth_key.rs (97%) rename packages/rest-api-runtime-adapter/src/{ => v1}/adapters/mod.rs (100%) rename packages/rest-api-runtime-adapter/src/{ => v1}/adapters/stats.rs (98%) rename packages/rest-api-runtime-adapter/src/{ => v1}/adapters/torrent.rs (95%) rename packages/rest-api-runtime-adapter/src/{ => v1}/adapters/whitelist.rs (94%) rename packages/rest-api-runtime-adapter/src/{ => v1}/container.rs (100%) rename packages/rest-api-runtime-adapter/src/{ => v1}/conversion.rs (50%) create mode 100644 packages/rest-api-runtime-adapter/src/v1/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 6b89e2076..bad5a7a4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5240,6 +5240,7 @@ version = "3.0.0-develop" dependencies = [ "async-trait", "tokio", + "torrust-clock", "torrust-info-hash", "torrust-metrics", "torrust-tracker-configuration", diff --git a/packages/axum-rest-api-server/src/routes.rs b/packages/axum-rest-api-server/src/routes.rs index 6ab422ec2..2d4e360dd 100644 --- a/packages/axum-rest-api-server/src/routes.rs +++ b/packages/axum-rest-api-server/src/routes.rs @@ -17,7 +17,7 @@ use axum::{BoxError, Router, middleware}; use hyper::{Request, StatusCode}; use torrust_server_lib::logging::Latency; use torrust_tracker_configuration::AccessTokens; -use torrust_tracker_rest_api_runtime_adapter::container::TrackerHttpApiCoreContainer; +use torrust_tracker_rest_api_runtime_adapter::v1::container::TrackerHttpApiCoreContainer; use tower::ServiceBuilder; use tower::timeout::TimeoutLayer; use tower_http::LatencyUnit; diff --git a/packages/axum-rest-api-server/src/server.rs b/packages/axum-rest-api-server/src/server.rs index f7a666dba..3b8faedc0 100644 --- a/packages/axum-rest-api-server/src/server.rs +++ b/packages/axum-rest-api-server/src/server.rs @@ -40,7 +40,7 @@ use torrust_server_lib::signals::{Halted, Started}; use torrust_tracker_axum_server::custom_axum_server::{self, TimeoutAcceptor}; use torrust_tracker_axum_server::signals::graceful_shutdown; use torrust_tracker_configuration::AccessTokens; -use torrust_tracker_rest_api_runtime_adapter::container::TrackerHttpApiCoreContainer; +use torrust_tracker_rest_api_runtime_adapter::v1::container::TrackerHttpApiCoreContainer; use tracing::{Level, instrument}; use super::routes::router; @@ -310,7 +310,7 @@ mod tests { use torrust_server_lib::registar::Registar; use torrust_tracker_axum_server::tsl::make_rust_tls; use torrust_tracker_configuration::{Configuration, logging}; - use torrust_tracker_rest_api_runtime_adapter::container::TrackerHttpApiCoreContainer; + use torrust_tracker_rest_api_runtime_adapter::v1::container::TrackerHttpApiCoreContainer; use torrust_tracker_test_helpers::configuration::ephemeral_public; use crate::server::{ApiServer, Launcher}; diff --git a/packages/axum-rest-api-server/src/testing/environment.rs b/packages/axum-rest-api-server/src/testing/environment.rs index be7cb9afb..7b610ea3d 100644 --- a/packages/axum-rest-api-server/src/testing/environment.rs +++ b/packages/axum-rest-api-server/src/testing/environment.rs @@ -9,7 +9,7 @@ use torrust_tracker_core::container::TrackerCoreContainer; use torrust_tracker_http_core::container::HttpTrackerCoreContainer; use torrust_tracker_primitives::peer; use torrust_tracker_rest_api_client::connection_info::{ConnectionInfo, Origin}; -use torrust_tracker_rest_api_runtime_adapter::container::TrackerHttpApiCoreContainer; +use torrust_tracker_rest_api_runtime_adapter::v1::container::TrackerHttpApiCoreContainer; use torrust_tracker_swarm_coordination_registry::container::SwarmCoordinationRegistryContainer; use torrust_tracker_udp_core::container::UdpTrackerCoreContainer; use torrust_tracker_udp_server::container::UdpTrackerServerContainer; diff --git a/packages/axum-rest-api-server/src/v1/context/auth_key/handlers.rs b/packages/axum-rest-api-server/src/v1/context/auth_key/handlers.rs index aa5d3ae4b..f840361ef 100644 --- a/packages/axum-rest-api-server/src/v1/context/auth_key/handlers.rs +++ b/packages/axum-rest-api-server/src/v1/context/auth_key/handlers.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use axum::extract::{self, Path, State}; use axum::response::Response; use serde::Deserialize; -use torrust_tracker_rest_api_application::use_cases::auth_key::AuthKeyApiService; +use torrust_tracker_rest_api_application::v1::use_cases::auth_key::AuthKeyApiService; use torrust_tracker_rest_api_protocol::v1::context::auth_key::forms::add_key_form::AddKeyForm; use super::responses::{ diff --git a/packages/axum-rest-api-server/src/v1/context/auth_key/routes.rs b/packages/axum-rest-api-server/src/v1/context/auth_key/routes.rs index 3fa0d0a11..7d5d509e3 100644 --- a/packages/axum-rest-api-server/src/v1/context/auth_key/routes.rs +++ b/packages/axum-rest-api-server/src/v1/context/auth_key/routes.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use axum::Router; use axum::routing::{get, post}; -use torrust_tracker_rest_api_application::use_cases::auth_key::AuthKeyApiService; +use torrust_tracker_rest_api_application::v1::use_cases::auth_key::AuthKeyApiService; use super::handlers::{add_auth_key_handler, delete_auth_key_handler, generate_auth_key_handler, reload_keys_handler}; diff --git a/packages/axum-rest-api-server/src/v1/context/stats/handlers.rs b/packages/axum-rest-api-server/src/v1/context/stats/handlers.rs index 051c7a362..f0e3a0177 100644 --- a/packages/axum-rest-api-server/src/v1/context/stats/handlers.rs +++ b/packages/axum-rest-api-server/src/v1/context/stats/handlers.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use axum::extract::{Query, State}; use axum::response::Response; use serde::Deserialize; -use torrust_tracker_rest_api_application::use_cases::stats::StatsApiService; +use torrust_tracker_rest_api_application::v1::use_cases::stats::StatsApiService; use super::responses::{labeled_metrics_response, labeled_stats_response, metrics_response, stats_response}; diff --git a/packages/axum-rest-api-server/src/v1/context/stats/routes.rs b/packages/axum-rest-api-server/src/v1/context/stats/routes.rs index f013c92ee..d5954f010 100644 --- a/packages/axum-rest-api-server/src/v1/context/stats/routes.rs +++ b/packages/axum-rest-api-server/src/v1/context/stats/routes.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use axum::Router; use axum::routing::get; -use torrust_tracker_rest_api_application::use_cases::stats::StatsApiService; +use torrust_tracker_rest_api_application::v1::use_cases::stats::StatsApiService; use super::handlers::{get_metrics_handler, get_stats_handler}; diff --git a/packages/axum-rest-api-server/src/v1/context/torrent/handlers.rs b/packages/axum-rest-api-server/src/v1/context/torrent/handlers.rs index ea8b51b51..d7ba0509a 100644 --- a/packages/axum-rest-api-server/src/v1/context/torrent/handlers.rs +++ b/packages/axum-rest-api-server/src/v1/context/torrent/handlers.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Deserializer, de}; use thiserror::Error; use torrust_info_hash::InfoHash; use torrust_tracker_primitives::pagination::Pagination; -use torrust_tracker_rest_api_application::use_cases::torrent::TorrentApiService; +use torrust_tracker_rest_api_application::v1::use_cases::torrent::TorrentApiService; use super::responses::{torrent_info_response, torrent_list_response, torrent_not_known_response}; use crate::InfoHashParam; diff --git a/packages/axum-rest-api-server/src/v1/context/torrent/resources/mod.rs b/packages/axum-rest-api-server/src/v1/context/torrent/resources/mod.rs index 8e31036d3..1c5d8f6cb 100644 --- a/packages/axum-rest-api-server/src/v1/context/torrent/resources/mod.rs +++ b/packages/axum-rest-api-server/src/v1/context/torrent/resources/mod.rs @@ -1,4 +1,3 @@ //! API resources for the [`torrent`](crate::v1::context::torrent) //! API context. -pub mod peer; pub mod torrent; diff --git a/packages/axum-rest-api-server/src/v1/context/torrent/resources/peer.rs b/packages/axum-rest-api-server/src/v1/context/torrent/resources/peer.rs deleted file mode 100644 index 1405aa129..000000000 --- a/packages/axum-rest-api-server/src/v1/context/torrent/resources/peer.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! `Peer` and Peer `Id` API resources. -//! -//! Protocol DTOs are defined in `torrust-tracker-rest-api-protocol`. diff --git a/packages/axum-rest-api-server/src/v1/context/torrent/resources/torrent.rs b/packages/axum-rest-api-server/src/v1/context/torrent/resources/torrent.rs index dc158a187..3b7371f90 100644 --- a/packages/axum-rest-api-server/src/v1/context/torrent/resources/torrent.rs +++ b/packages/axum-rest-api-server/src/v1/context/torrent/resources/torrent.rs @@ -1,67 +1,3 @@ //! `Torrent` and `ListItem` API resources. //! //! Protocol DTOs are defined in `torrust-tracker-rest-api-protocol`. -//! This module only contains unit tests for domain→DTO conversions. - -#[cfg(test)] -mod tests { - use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - use std::str::FromStr; - - use torrust_clock::DurationSinceUnixEpoch; - use torrust_info_hash::InfoHash; - use torrust_tracker_core::torrent::services::{BasicInfo, Info}; - use torrust_tracker_primitives::{AnnounceEvent, NumberOfBytes, PeerId, peer}; - use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::torrent::{ListItem, Torrent}; - use torrust_tracker_rest_api_runtime_adapter::conversion; - - fn sample_peer() -> peer::Peer { - peer::Peer { - peer_id: PeerId(*b"-qB00000000000000000"), - peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), - updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), - uploaded: NumberOfBytes::new(0), - downloaded: NumberOfBytes::new(0), - left: NumberOfBytes::new(0), - event: AnnounceEvent::Started, - } - } - - #[test] - fn torrent_resource_should_be_converted_from_torrent_info() { - assert_eq!( - conversion::from_domain_info(Info { - info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 - seeders: 1, - completed: 2, - leechers: 3, - peers: Some(vec![sample_peer()]), - }), - Torrent { - info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 - seeders: 1, - completed: 2, - leechers: 3, - peers: Some(vec![conversion::from_domain_peer(sample_peer())]), - } - ); - } - - #[test] - fn torrent_resource_list_item_should_be_converted_from_the_basic_torrent_info() { - assert_eq!( - conversion::list_item_from_domain(&BasicInfo { - info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 - seeders: 1, - completed: 2, - leechers: 3, - }), - ListItem { - info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 - seeders: 1, - completed: 2, - leechers: 3, - } - ); - } -} diff --git a/packages/axum-rest-api-server/src/v1/context/torrent/routes.rs b/packages/axum-rest-api-server/src/v1/context/torrent/routes.rs index 423a30f7a..b960582d5 100644 --- a/packages/axum-rest-api-server/src/v1/context/torrent/routes.rs +++ b/packages/axum-rest-api-server/src/v1/context/torrent/routes.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use axum::Router; use axum::routing::get; -use torrust_tracker_rest_api_application::use_cases::torrent::TorrentApiService; +use torrust_tracker_rest_api_application::v1::use_cases::torrent::TorrentApiService; use super::handlers::{get_torrent_handler, get_torrents_handler}; diff --git a/packages/axum-rest-api-server/src/v1/context/whitelist/handlers.rs b/packages/axum-rest-api-server/src/v1/context/whitelist/handlers.rs index 571bee86c..a2aed9146 100644 --- a/packages/axum-rest-api-server/src/v1/context/whitelist/handlers.rs +++ b/packages/axum-rest-api-server/src/v1/context/whitelist/handlers.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use axum::extract::{Path, State}; use axum::response::Response; use torrust_info_hash::InfoHash; -use torrust_tracker_rest_api_application::use_cases::whitelist::WhitelistApiService; +use torrust_tracker_rest_api_application::v1::use_cases::whitelist::WhitelistApiService; use super::responses::{ failed_to_reload_whitelist_response, failed_to_remove_torrent_from_whitelist_response, failed_to_whitelist_torrent_response, diff --git a/packages/axum-rest-api-server/src/v1/context/whitelist/routes.rs b/packages/axum-rest-api-server/src/v1/context/whitelist/routes.rs index d4728b1df..1f2375308 100644 --- a/packages/axum-rest-api-server/src/v1/context/whitelist/routes.rs +++ b/packages/axum-rest-api-server/src/v1/context/whitelist/routes.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use axum::Router; use axum::routing::{delete, get, post}; -use torrust_tracker_rest_api_application::use_cases::whitelist::WhitelistApiService; +use torrust_tracker_rest_api_application::v1::use_cases::whitelist::WhitelistApiService; use super::handlers::{add_torrent_to_whitelist_handler, reload_whitelist_handler, remove_torrent_from_whitelist_handler}; diff --git a/packages/axum-rest-api-server/src/v1/routes.rs b/packages/axum-rest-api-server/src/v1/routes.rs index fa97dc8b4..e8cbb4bd4 100644 --- a/packages/axum-rest-api-server/src/v1/routes.rs +++ b/packages/axum-rest-api-server/src/v1/routes.rs @@ -2,15 +2,15 @@ use std::sync::Arc; use axum::Router; -use torrust_tracker_rest_api_application::use_cases::auth_key::AuthKeyApiService; -use torrust_tracker_rest_api_application::use_cases::stats::StatsApiService; -use torrust_tracker_rest_api_application::use_cases::torrent::TorrentApiService; -use torrust_tracker_rest_api_application::use_cases::whitelist::WhitelistApiService; -use torrust_tracker_rest_api_runtime_adapter::adapters::auth_key::TrackerAuthKeyAdapter; -use torrust_tracker_rest_api_runtime_adapter::adapters::stats::TrackerStatsAdapter; -use torrust_tracker_rest_api_runtime_adapter::adapters::torrent::TrackerTorrentQueryAdapter; -use torrust_tracker_rest_api_runtime_adapter::adapters::whitelist::TrackerWhitelistAdapter; -use torrust_tracker_rest_api_runtime_adapter::container::TrackerHttpApiCoreContainer; +use torrust_tracker_rest_api_application::v1::use_cases::auth_key::AuthKeyApiService; +use torrust_tracker_rest_api_application::v1::use_cases::stats::StatsApiService; +use torrust_tracker_rest_api_application::v1::use_cases::torrent::TorrentApiService; +use torrust_tracker_rest_api_application::v1::use_cases::whitelist::WhitelistApiService; +use torrust_tracker_rest_api_runtime_adapter::v1::adapters::auth_key::TrackerAuthKeyAdapter; +use torrust_tracker_rest_api_runtime_adapter::v1::adapters::stats::TrackerStatsAdapter; +use torrust_tracker_rest_api_runtime_adapter::v1::adapters::torrent::TrackerTorrentQueryAdapter; +use torrust_tracker_rest_api_runtime_adapter::v1::adapters::whitelist::TrackerWhitelistAdapter; +use torrust_tracker_rest_api_runtime_adapter::v1::container::TrackerHttpApiCoreContainer; use super::context::{auth_key, stats, torrent, whitelist}; diff --git a/packages/axum-rest-api-server/tests/server/v1/contract/context/torrent.rs b/packages/axum-rest-api-server/tests/server/v1/contract/context/torrent.rs index 052bed556..d46069c96 100644 --- a/packages/axum-rest-api-server/tests/server/v1/contract/context/torrent.rs +++ b/packages/axum-rest-api-server/tests/server/v1/contract/context/torrent.rs @@ -6,7 +6,7 @@ use torrust_tracker_primitives::peer::fixture::PeerBuilder; use torrust_tracker_rest_api_client::common::http::{Query, QueryParam}; use torrust_tracker_rest_api_client::v1::client::{Client, headers_with_request_id}; use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::torrent::{self, Torrent}; -use torrust_tracker_rest_api_runtime_adapter::conversion; +use torrust_tracker_rest_api_runtime_adapter::v1::conversion; use torrust_tracker_test_helpers::logging::logs_contains_a_line_with; use torrust_tracker_test_helpers::{configuration, logging}; use uuid::Uuid; diff --git a/packages/rest-api-application/src/lib.rs b/packages/rest-api-application/src/lib.rs index aeb870d23..e880d9953 100644 --- a/packages/rest-api-application/src/lib.rs +++ b/packages/rest-api-application/src/lib.rs @@ -14,5 +14,4 @@ //! - Axum server routing or middleware. //! - Tracker internal database or domain logic. //! - Protocol DTOs (those belong to `rest-api-protocol`). -pub mod ports; -pub mod use_cases; +pub mod v1; diff --git a/packages/rest-api-application/src/v1/mod.rs b/packages/rest-api-application/src/v1/mod.rs new file mode 100644 index 000000000..ff22d8eeb --- /dev/null +++ b/packages/rest-api-application/src/v1/mod.rs @@ -0,0 +1,5 @@ +//! Version 1 of the Torrust Tracker REST API application layer. +//! +//! This module contains all v1-specific port traits and use-case services. +pub mod ports; +pub mod use_cases; \ No newline at end of file diff --git a/packages/rest-api-application/src/ports/auth_key.rs b/packages/rest-api-application/src/v1/ports/auth_key.rs similarity index 100% rename from packages/rest-api-application/src/ports/auth_key.rs rename to packages/rest-api-application/src/v1/ports/auth_key.rs diff --git a/packages/rest-api-application/src/ports/mod.rs b/packages/rest-api-application/src/v1/ports/mod.rs similarity index 100% rename from packages/rest-api-application/src/ports/mod.rs rename to packages/rest-api-application/src/v1/ports/mod.rs diff --git a/packages/rest-api-application/src/ports/stats.rs b/packages/rest-api-application/src/v1/ports/stats.rs similarity index 100% rename from packages/rest-api-application/src/ports/stats.rs rename to packages/rest-api-application/src/v1/ports/stats.rs diff --git a/packages/rest-api-application/src/ports/torrent.rs b/packages/rest-api-application/src/v1/ports/torrent.rs similarity index 100% rename from packages/rest-api-application/src/ports/torrent.rs rename to packages/rest-api-application/src/v1/ports/torrent.rs diff --git a/packages/rest-api-application/src/ports/whitelist.rs b/packages/rest-api-application/src/v1/ports/whitelist.rs similarity index 100% rename from packages/rest-api-application/src/ports/whitelist.rs rename to packages/rest-api-application/src/v1/ports/whitelist.rs diff --git a/packages/rest-api-application/src/use_cases/auth_key.rs b/packages/rest-api-application/src/v1/use_cases/auth_key.rs similarity index 97% rename from packages/rest-api-application/src/use_cases/auth_key.rs rename to packages/rest-api-application/src/v1/use_cases/auth_key.rs index eb1bde71c..ff8405444 100644 --- a/packages/rest-api-application/src/use_cases/auth_key.rs +++ b/packages/rest-api-application/src/v1/use_cases/auth_key.rs @@ -5,7 +5,7 @@ use torrust_tracker_rest_api_protocol::v1::context::auth_key::forms::add_key_form::AddKeyForm; use torrust_tracker_rest_api_protocol::v1::context::auth_key::resources::auth_key::{AuthKey, AuthKeyError}; -use crate::ports::auth_key::AuthKeyPort; +use crate::v1::ports::auth_key::AuthKeyPort; /// Use-case service for auth-key-related API operations. /// diff --git a/packages/rest-api-application/src/use_cases/mod.rs b/packages/rest-api-application/src/v1/use_cases/mod.rs similarity index 100% rename from packages/rest-api-application/src/use_cases/mod.rs rename to packages/rest-api-application/src/v1/use_cases/mod.rs diff --git a/packages/rest-api-application/src/use_cases/stats.rs b/packages/rest-api-application/src/v1/use_cases/stats.rs similarity index 95% rename from packages/rest-api-application/src/use_cases/stats.rs rename to packages/rest-api-application/src/v1/use_cases/stats.rs index 4f206ab53..51eefb8de 100644 --- a/packages/rest-api-application/src/use_cases/stats.rs +++ b/packages/rest-api-application/src/v1/use_cases/stats.rs @@ -3,7 +3,7 @@ //! Orchestrates calls to the [`StatsQueryPort`] to retrieve tracker metrics. use torrust_tracker_rest_api_protocol::v1::context::stats::resources::stats::{LabeledStats, Stats}; -use crate::ports::stats::StatsQueryPort; +use crate::v1::ports::stats::StatsQueryPort; /// Use-case service for stats-related API operations. /// diff --git a/packages/rest-api-application/src/use_cases/torrent.rs b/packages/rest-api-application/src/v1/use_cases/torrent.rs similarity index 96% rename from packages/rest-api-application/src/use_cases/torrent.rs rename to packages/rest-api-application/src/v1/use_cases/torrent.rs index 47c182e10..bcbda9673 100644 --- a/packages/rest-api-application/src/use_cases/torrent.rs +++ b/packages/rest-api-application/src/v1/use_cases/torrent.rs @@ -3,7 +3,7 @@ use torrust_info_hash::InfoHash; use torrust_tracker_primitives::pagination::Pagination; use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::torrent::{ListItem, Torrent}; -use crate::ports::torrent::TorrentQueryPort; +use crate::v1::ports::torrent::TorrentQueryPort; /// Use-case service for torrent-related API operations. /// diff --git a/packages/rest-api-application/src/use_cases/whitelist.rs b/packages/rest-api-application/src/v1/use_cases/whitelist.rs similarity index 96% rename from packages/rest-api-application/src/use_cases/whitelist.rs rename to packages/rest-api-application/src/v1/use_cases/whitelist.rs index 05c0b6e6d..ab1e3a5ac 100644 --- a/packages/rest-api-application/src/use_cases/whitelist.rs +++ b/packages/rest-api-application/src/v1/use_cases/whitelist.rs @@ -5,7 +5,7 @@ use torrust_info_hash::InfoHash; use torrust_tracker_rest_api_protocol::v1::context::whitelist::resources::whitelist::WhitelistError; -use crate::ports::whitelist::WhitelistCommandPort; +use crate::v1::ports::whitelist::WhitelistCommandPort; /// Use-case service for whitelist-related API operations. /// diff --git a/packages/rest-api-runtime-adapter/Cargo.toml b/packages/rest-api-runtime-adapter/Cargo.toml index 4af100498..73a401df9 100644 --- a/packages/rest-api-runtime-adapter/Cargo.toml +++ b/packages/rest-api-runtime-adapter/Cargo.toml @@ -27,3 +27,6 @@ torrust-metrics = "0.1.0" torrust-info-hash = "=0.2.0" async-trait = "0.1" tokio = { version = "1", features = [ "sync" ] } + +[dev-dependencies] +torrust-clock = "3.0.0" diff --git a/packages/rest-api-runtime-adapter/src/lib.rs b/packages/rest-api-runtime-adapter/src/lib.rs index 9d6dc1967..2d11ab94b 100644 --- a/packages/rest-api-runtime-adapter/src/lib.rs +++ b/packages/rest-api-runtime-adapter/src/lib.rs @@ -14,6 +14,4 @@ //! - Protocol DTOs (those belong to `rest-api-protocol`). //! - Use-case services (those belong to `rest-api-application`). //! - Axum server routing or middleware. -pub mod adapters; -pub mod container; -pub mod conversion; +pub mod v1; diff --git a/packages/rest-api-runtime-adapter/src/adapters/auth_key.rs b/packages/rest-api-runtime-adapter/src/v1/adapters/auth_key.rs similarity index 97% rename from packages/rest-api-runtime-adapter/src/adapters/auth_key.rs rename to packages/rest-api-runtime-adapter/src/v1/adapters/auth_key.rs index dbd8300de..c730c4c12 100644 --- a/packages/rest-api-runtime-adapter/src/adapters/auth_key.rs +++ b/packages/rest-api-runtime-adapter/src/v1/adapters/auth_key.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use async_trait::async_trait; use torrust_tracker_core::authentication::handler::{AddKeyRequest, KeysHandler}; use torrust_tracker_core::authentication::{Key, PeerKey}; -use torrust_tracker_rest_api_application::ports::auth_key::AuthKeyPort; +use torrust_tracker_rest_api_application::v1::ports::auth_key::AuthKeyPort; use torrust_tracker_rest_api_protocol::v1::context::auth_key::forms::add_key_form::AddKeyForm; use torrust_tracker_rest_api_protocol::v1::context::auth_key::resources::auth_key::{AuthKey, AuthKeyError}; diff --git a/packages/rest-api-runtime-adapter/src/adapters/mod.rs b/packages/rest-api-runtime-adapter/src/v1/adapters/mod.rs similarity index 100% rename from packages/rest-api-runtime-adapter/src/adapters/mod.rs rename to packages/rest-api-runtime-adapter/src/v1/adapters/mod.rs diff --git a/packages/rest-api-runtime-adapter/src/adapters/stats.rs b/packages/rest-api-runtime-adapter/src/v1/adapters/stats.rs similarity index 98% rename from packages/rest-api-runtime-adapter/src/adapters/stats.rs rename to packages/rest-api-runtime-adapter/src/v1/adapters/stats.rs index 9438f6cc7..83ddac976 100644 --- a/packages/rest-api-runtime-adapter/src/adapters/stats.rs +++ b/packages/rest-api-runtime-adapter/src/v1/adapters/stats.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use async_trait::async_trait; use torrust_metrics::metric_collection::MetricCollection; use torrust_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; -use torrust_tracker_rest_api_application::ports::stats::StatsQueryPort; +use torrust_tracker_rest_api_application::v1::ports::stats::StatsQueryPort; use torrust_tracker_rest_api_protocol::v1::context::stats::resources::stats::{LabeledStats, Stats}; /// Adapter that queries all tracker-internal data sources and converts /// domain types to protocol DTOs. diff --git a/packages/rest-api-runtime-adapter/src/adapters/torrent.rs b/packages/rest-api-runtime-adapter/src/v1/adapters/torrent.rs similarity index 95% rename from packages/rest-api-runtime-adapter/src/adapters/torrent.rs rename to packages/rest-api-runtime-adapter/src/v1/adapters/torrent.rs index 0f69cde44..0b304af1f 100644 --- a/packages/rest-api-runtime-adapter/src/adapters/torrent.rs +++ b/packages/rest-api-runtime-adapter/src/v1/adapters/torrent.rs @@ -6,7 +6,7 @@ use torrust_info_hash::InfoHash; use torrust_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use torrust_tracker_core::torrent::services; use torrust_tracker_primitives::pagination::Pagination; -use torrust_tracker_rest_api_application::ports::torrent::TorrentQueryPort; +use torrust_tracker_rest_api_application::v1::ports::torrent::TorrentQueryPort; use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::torrent::{ListItem, Torrent}; use super::super::conversion; diff --git a/packages/rest-api-runtime-adapter/src/adapters/whitelist.rs b/packages/rest-api-runtime-adapter/src/v1/adapters/whitelist.rs similarity index 94% rename from packages/rest-api-runtime-adapter/src/adapters/whitelist.rs rename to packages/rest-api-runtime-adapter/src/v1/adapters/whitelist.rs index a354572f9..536281450 100644 --- a/packages/rest-api-runtime-adapter/src/adapters/whitelist.rs +++ b/packages/rest-api-runtime-adapter/src/v1/adapters/whitelist.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use async_trait::async_trait; use torrust_info_hash::InfoHash; use torrust_tracker_core::whitelist::manager::WhitelistManager; -use torrust_tracker_rest_api_application::ports::whitelist::WhitelistCommandPort; +use torrust_tracker_rest_api_application::v1::ports::whitelist::WhitelistCommandPort; use torrust_tracker_rest_api_protocol::v1::context::whitelist::resources::whitelist::WhitelistError; /// Adapter that wraps [`WhitelistManager`] and implements the diff --git a/packages/rest-api-runtime-adapter/src/container.rs b/packages/rest-api-runtime-adapter/src/v1/container.rs similarity index 100% rename from packages/rest-api-runtime-adapter/src/container.rs rename to packages/rest-api-runtime-adapter/src/v1/container.rs diff --git a/packages/rest-api-runtime-adapter/src/conversion.rs b/packages/rest-api-runtime-adapter/src/v1/conversion.rs similarity index 50% rename from packages/rest-api-runtime-adapter/src/conversion.rs rename to packages/rest-api-runtime-adapter/src/v1/conversion.rs index 65f668a97..8eecb0ea9 100644 --- a/packages/rest-api-runtime-adapter/src/conversion.rs +++ b/packages/rest-api-runtime-adapter/src/v1/conversion.rs @@ -63,3 +63,67 @@ pub fn list_item_from_domain(basic_info: &BasicInfo) -> ListItem { leechers: basic_info.leechers, } } + +#[cfg(test)] +mod tests { + use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use std::str::FromStr; + + use torrust_clock::DurationSinceUnixEpoch; + use torrust_info_hash::InfoHash; + use torrust_tracker_core::torrent::services::{BasicInfo, Info}; + use torrust_tracker_primitives::{AnnounceEvent, NumberOfBytes, PeerId, peer}; + use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::torrent::{ListItem, Torrent}; + + use super::*; + + fn sample_peer() -> peer::Peer { + peer::Peer { + peer_id: PeerId(*b"-qB00000000000000000"), + peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), + updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), + uploaded: NumberOfBytes::new(0), + downloaded: NumberOfBytes::new(0), + left: NumberOfBytes::new(0), + event: AnnounceEvent::Started, + } + } + + #[test] + fn torrent_resource_should_be_converted_from_torrent_info() { + assert_eq!( + from_domain_info(Info { + info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 + seeders: 1, + completed: 2, + leechers: 3, + peers: Some(vec![sample_peer()]), + }), + Torrent { + info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 + seeders: 1, + completed: 2, + leechers: 3, + peers: Some(vec![from_domain_peer(sample_peer())]), + } + ); + } + + #[test] + fn torrent_resource_list_item_should_be_converted_from_the_basic_torrent_info() { + assert_eq!( + list_item_from_domain(&BasicInfo { + info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 + seeders: 1, + completed: 2, + leechers: 3, + }), + ListItem { + info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 + seeders: 1, + completed: 2, + leechers: 3, + } + ); + } +} diff --git a/packages/rest-api-runtime-adapter/src/v1/mod.rs b/packages/rest-api-runtime-adapter/src/v1/mod.rs new file mode 100644 index 000000000..937335d07 --- /dev/null +++ b/packages/rest-api-runtime-adapter/src/v1/mod.rs @@ -0,0 +1,7 @@ +//! Version 1 of the Torrust Tracker REST API runtime adapter. +//! +//! This module contains all v1-specific adapter implementations, +//! the dependency injection container, and domain→protocol DTO conversions. +pub mod adapters; +pub mod container; +pub mod conversion; \ No newline at end of file diff --git a/src/bootstrap/jobs/tracker_apis.rs b/src/bootstrap/jobs/tracker_apis.rs index 6f4dfb358..4ea4d9e68 100644 --- a/src/bootstrap/jobs/tracker_apis.rs +++ b/src/bootstrap/jobs/tracker_apis.rs @@ -30,7 +30,7 @@ use torrust_tracker_axum_rest_api_server::Version; use torrust_tracker_axum_rest_api_server::server::{ApiServer, Launcher}; use torrust_tracker_axum_server::tsl::make_rust_tls; use torrust_tracker_configuration::AccessTokens; -use torrust_tracker_rest_api_runtime_adapter::container::TrackerHttpApiCoreContainer; +use torrust_tracker_rest_api_runtime_adapter::v1::container::TrackerHttpApiCoreContainer; use tracing::instrument; /// This is the message that the "launcher" spawned task sends to the main @@ -104,7 +104,7 @@ mod tests { use torrust_server_lib::registar::Registar; use torrust_tracker_axum_rest_api_server::Version; - use torrust_tracker_rest_api_runtime_adapter::container::TrackerHttpApiCoreContainer; + use torrust_tracker_rest_api_runtime_adapter::v1::container::TrackerHttpApiCoreContainer; use torrust_tracker_test_helpers::configuration::ephemeral_public; use crate::bootstrap::app::initialize_global_services; diff --git a/src/container.rs b/src/container.rs index b0167c134..de4097d67 100644 --- a/src/container.rs +++ b/src/container.rs @@ -6,7 +6,7 @@ use torrust_server_lib::registar::Registar; use torrust_tracker_configuration::{Configuration, HttpApi}; use torrust_tracker_core::container::TrackerCoreContainer; use torrust_tracker_http_core::container::{HttpTrackerCoreContainer, HttpTrackerCoreServices}; -use torrust_tracker_rest_api_runtime_adapter::container::TrackerHttpApiCoreContainer; +use torrust_tracker_rest_api_runtime_adapter::v1::container::TrackerHttpApiCoreContainer; use torrust_tracker_swarm_coordination_registry::container::SwarmCoordinationRegistryContainer; use torrust_tracker_udp_core::container::{UdpTrackerCoreContainer, UdpTrackerCoreServices}; use torrust_tracker_udp_core::{self}; From 0d922a97608e65bc87f7ec1cb1aae43254461bd0 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 30 Jun 2026 08:11:40 +0100 Subject: [PATCH 2/3] style: fix trailing newlines in v1/mod.rs files rustfmt requires files to end with a single trailing newline. Both new v1/mod.rs files were missing trailing newlines. --- packages/rest-api-application/src/v1/mod.rs | 2 +- .../src/conversion.rs | 129 ++++++++++++++++++ .../rest-api-runtime-adapter/src/v1/mod.rs | 2 +- 3 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 packages/rest-api-runtime-adapter/src/conversion.rs diff --git a/packages/rest-api-application/src/v1/mod.rs b/packages/rest-api-application/src/v1/mod.rs index ff22d8eeb..e66a1927f 100644 --- a/packages/rest-api-application/src/v1/mod.rs +++ b/packages/rest-api-application/src/v1/mod.rs @@ -2,4 +2,4 @@ //! //! This module contains all v1-specific port traits and use-case services. pub mod ports; -pub mod use_cases; \ No newline at end of file +pub mod use_cases; diff --git a/packages/rest-api-runtime-adapter/src/conversion.rs b/packages/rest-api-runtime-adapter/src/conversion.rs new file mode 100644 index 000000000..8eecb0ea9 --- /dev/null +++ b/packages/rest-api-runtime-adapter/src/conversion.rs @@ -0,0 +1,129 @@ +//! Conversions from domain types to protocol DTOs. +//! +//! These functions bridge tracker-internal domain types (e.g., `Info`, +//! `BasicInfo`, `peer::Peer`) with transport-agnostic protocol DTOs. +use torrust_tracker_core::torrent::services::{BasicInfo, Info}; +use torrust_tracker_primitives::{PeerId, peer as domain_peer}; +use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::peer as protocol_peer; +use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::torrent::{ListItem, Torrent}; + +/// Convert a domain [`domain_peer::Peer`] into a protocol [`protocol_peer::Peer`]. +#[must_use] +pub fn from_domain_peer(value: domain_peer::Peer) -> protocol_peer::Peer { + #[allow(deprecated)] + protocol_peer::Peer { + peer_id: from_domain_peer_id(value.peer_id), + peer_addr: value.peer_addr.to_string(), + updated: value.updated.as_millis(), + updated_milliseconds_ago: value.updated.as_millis(), + uploaded: value.uploaded.0, + downloaded: value.downloaded.0, + left: value.left.0, + event: format!("{:?}", value.event), + } +} + +/// Convert a domain [`PeerId`] into a protocol [`protocol_peer::Id`]. +#[must_use] +pub fn from_domain_peer_id(peer_id: PeerId) -> protocol_peer::Id { + let pid = domain_peer::Id::from(peer_id); + protocol_peer::Id { + id: pid.to_hex_string(), + client: pid.get_client_name(), + } +} + +/// Convert a domain [`Info`] into a protocol [`Torrent`]. +#[must_use] +pub fn from_domain_info(info: Info) -> Torrent { + let peers: Option> = info.peers.map(|peers| peers.into_iter().map(from_domain_peer).collect()); + + Torrent { + info_hash: info.info_hash.to_string(), + seeders: info.seeders, + completed: info.completed, + leechers: info.leechers, + peers, + } +} + +/// Build a vector of [`ListItem`] from domain [`BasicInfo`] slices. +#[must_use] +pub fn list_items_from_domain(basic_info_vec: &[BasicInfo]) -> Vec { + basic_info_vec.iter().map(list_item_from_domain).collect() +} + +/// Build a [`ListItem`] from a domain [`BasicInfo`]. +#[must_use] +pub fn list_item_from_domain(basic_info: &BasicInfo) -> ListItem { + ListItem { + info_hash: basic_info.info_hash.to_string(), + seeders: basic_info.seeders, + completed: basic_info.completed, + leechers: basic_info.leechers, + } +} + +#[cfg(test)] +mod tests { + use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use std::str::FromStr; + + use torrust_clock::DurationSinceUnixEpoch; + use torrust_info_hash::InfoHash; + use torrust_tracker_core::torrent::services::{BasicInfo, Info}; + use torrust_tracker_primitives::{AnnounceEvent, NumberOfBytes, PeerId, peer}; + use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::torrent::{ListItem, Torrent}; + + use super::*; + + fn sample_peer() -> peer::Peer { + peer::Peer { + peer_id: PeerId(*b"-qB00000000000000000"), + peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), + updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), + uploaded: NumberOfBytes::new(0), + downloaded: NumberOfBytes::new(0), + left: NumberOfBytes::new(0), + event: AnnounceEvent::Started, + } + } + + #[test] + fn torrent_resource_should_be_converted_from_torrent_info() { + assert_eq!( + from_domain_info(Info { + info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 + seeders: 1, + completed: 2, + leechers: 3, + peers: Some(vec![sample_peer()]), + }), + Torrent { + info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 + seeders: 1, + completed: 2, + leechers: 3, + peers: Some(vec![from_domain_peer(sample_peer())]), + } + ); + } + + #[test] + fn torrent_resource_list_item_should_be_converted_from_the_basic_torrent_info() { + assert_eq!( + list_item_from_domain(&BasicInfo { + info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 + seeders: 1, + completed: 2, + leechers: 3, + }), + ListItem { + info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 + seeders: 1, + completed: 2, + leechers: 3, + } + ); + } +} diff --git a/packages/rest-api-runtime-adapter/src/v1/mod.rs b/packages/rest-api-runtime-adapter/src/v1/mod.rs index 937335d07..d5ca09557 100644 --- a/packages/rest-api-runtime-adapter/src/v1/mod.rs +++ b/packages/rest-api-runtime-adapter/src/v1/mod.rs @@ -4,4 +4,4 @@ //! the dependency injection container, and domain→protocol DTO conversions. pub mod adapters; pub mod container; -pub mod conversion; \ No newline at end of file +pub mod conversion; From 3800b129bd6a0290804adb5b3cbc5ecc0595a118 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 30 Jun 2026 08:16:29 +0100 Subject: [PATCH 3/3] fix: remove stray conversion.rs left at old path by cargo fmt --- .../src/conversion.rs | 129 ------------------ 1 file changed, 129 deletions(-) delete mode 100644 packages/rest-api-runtime-adapter/src/conversion.rs diff --git a/packages/rest-api-runtime-adapter/src/conversion.rs b/packages/rest-api-runtime-adapter/src/conversion.rs deleted file mode 100644 index 8eecb0ea9..000000000 --- a/packages/rest-api-runtime-adapter/src/conversion.rs +++ /dev/null @@ -1,129 +0,0 @@ -//! Conversions from domain types to protocol DTOs. -//! -//! These functions bridge tracker-internal domain types (e.g., `Info`, -//! `BasicInfo`, `peer::Peer`) with transport-agnostic protocol DTOs. -use torrust_tracker_core::torrent::services::{BasicInfo, Info}; -use torrust_tracker_primitives::{PeerId, peer as domain_peer}; -use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::peer as protocol_peer; -use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::torrent::{ListItem, Torrent}; - -/// Convert a domain [`domain_peer::Peer`] into a protocol [`protocol_peer::Peer`]. -#[must_use] -pub fn from_domain_peer(value: domain_peer::Peer) -> protocol_peer::Peer { - #[allow(deprecated)] - protocol_peer::Peer { - peer_id: from_domain_peer_id(value.peer_id), - peer_addr: value.peer_addr.to_string(), - updated: value.updated.as_millis(), - updated_milliseconds_ago: value.updated.as_millis(), - uploaded: value.uploaded.0, - downloaded: value.downloaded.0, - left: value.left.0, - event: format!("{:?}", value.event), - } -} - -/// Convert a domain [`PeerId`] into a protocol [`protocol_peer::Id`]. -#[must_use] -pub fn from_domain_peer_id(peer_id: PeerId) -> protocol_peer::Id { - let pid = domain_peer::Id::from(peer_id); - protocol_peer::Id { - id: pid.to_hex_string(), - client: pid.get_client_name(), - } -} - -/// Convert a domain [`Info`] into a protocol [`Torrent`]. -#[must_use] -pub fn from_domain_info(info: Info) -> Torrent { - let peers: Option> = info.peers.map(|peers| peers.into_iter().map(from_domain_peer).collect()); - - Torrent { - info_hash: info.info_hash.to_string(), - seeders: info.seeders, - completed: info.completed, - leechers: info.leechers, - peers, - } -} - -/// Build a vector of [`ListItem`] from domain [`BasicInfo`] slices. -#[must_use] -pub fn list_items_from_domain(basic_info_vec: &[BasicInfo]) -> Vec { - basic_info_vec.iter().map(list_item_from_domain).collect() -} - -/// Build a [`ListItem`] from a domain [`BasicInfo`]. -#[must_use] -pub fn list_item_from_domain(basic_info: &BasicInfo) -> ListItem { - ListItem { - info_hash: basic_info.info_hash.to_string(), - seeders: basic_info.seeders, - completed: basic_info.completed, - leechers: basic_info.leechers, - } -} - -#[cfg(test)] -mod tests { - use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - use std::str::FromStr; - - use torrust_clock::DurationSinceUnixEpoch; - use torrust_info_hash::InfoHash; - use torrust_tracker_core::torrent::services::{BasicInfo, Info}; - use torrust_tracker_primitives::{AnnounceEvent, NumberOfBytes, PeerId, peer}; - use torrust_tracker_rest_api_protocol::v1::context::torrent::resources::torrent::{ListItem, Torrent}; - - use super::*; - - fn sample_peer() -> peer::Peer { - peer::Peer { - peer_id: PeerId(*b"-qB00000000000000000"), - peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), - updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), - uploaded: NumberOfBytes::new(0), - downloaded: NumberOfBytes::new(0), - left: NumberOfBytes::new(0), - event: AnnounceEvent::Started, - } - } - - #[test] - fn torrent_resource_should_be_converted_from_torrent_info() { - assert_eq!( - from_domain_info(Info { - info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 - seeders: 1, - completed: 2, - leechers: 3, - peers: Some(vec![sample_peer()]), - }), - Torrent { - info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 - seeders: 1, - completed: 2, - leechers: 3, - peers: Some(vec![from_domain_peer(sample_peer())]), - } - ); - } - - #[test] - fn torrent_resource_list_item_should_be_converted_from_the_basic_torrent_info() { - assert_eq!( - list_item_from_domain(&BasicInfo { - info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 - seeders: 1, - completed: 2, - leechers: 3, - }), - ListItem { - info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 - seeders: 1, - completed: 2, - leechers: 3, - } - ); - } -}