Skip to content

Commit 3234f16

Browse files
committed
step: [#220] implement TrackerCoreSection DTO
1 parent a6741cf commit 3234f16

File tree

3 files changed

+166
-1
lines changed

3 files changed

+166
-1
lines changed

docs/implementation-plans/issue-220-test-command-architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Phase 0: Architecture Fix
4444
[x] Step 0.2: Implement UdpTrackerSection DTO
4545
[x] Step 0.3: Implement HttpTrackerSection DTO
4646
[x] Step 0.4: Implement HttpApiSection DTO
47-
[ ] Step 0.5: Implement TrackerCoreSection DTO
47+
[x] Step 0.5: Implement TrackerCoreSection DTO
4848
[ ] Step 0.6: Implement TrackerSection DTO
4949
[ ] Step 0.7: Update domain types to use SocketAddr
5050
[ ] Step 0.8: Update EnvironmentCreationConfig

src/application/command_handlers/create/config/tracker/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
77
mod http_api_section;
88
mod http_tracker_section;
9+
mod tracker_core_section;
910
mod udp_tracker_section;
1011

1112
pub use http_api_section::HttpApiSection;
1213
pub use http_tracker_section::HttpTrackerSection;
14+
pub use tracker_core_section::{DatabaseSection, TrackerCoreSection};
1315
pub use udp_tracker_section::UdpTrackerSection;
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
//! Tracker Core configuration section (application DTO)
2+
//!
3+
//! This module provides the DTO for tracker core configuration,
4+
//! used for JSON deserialization and validation before converting
5+
//! to domain types.
6+
7+
use serde::{Deserialize, Serialize};
8+
9+
use crate::application::command_handlers::create::config::errors::CreateConfigError;
10+
use crate::domain::tracker::{DatabaseConfig, TrackerCoreConfig};
11+
12+
/// Database configuration section (application DTO)
13+
///
14+
/// Mirrors the domain `DatabaseConfig` enum but at the application layer.
15+
/// Currently only `SQLite` is supported.
16+
///
17+
/// # Examples
18+
///
19+
/// ```json
20+
/// {
21+
/// "driver": "sqlite3",
22+
/// "database_name": "tracker.db"
23+
/// }
24+
/// ```
25+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
26+
#[serde(tag = "driver")]
27+
pub enum DatabaseSection {
28+
/// `SQLite` file-based database
29+
#[serde(rename = "sqlite3")]
30+
Sqlite {
31+
/// Database file name
32+
database_name: String,
33+
},
34+
}
35+
36+
impl DatabaseSection {
37+
/// Converts this DTO to the domain `DatabaseConfig` type.
38+
///
39+
/// # Errors
40+
///
41+
/// This conversion currently cannot fail, but returns `Result`
42+
/// for consistency with other DTO conversions and to allow
43+
/// future validation.
44+
pub fn to_database_config(&self) -> Result<DatabaseConfig, CreateConfigError> {
45+
match self {
46+
Self::Sqlite { database_name } => Ok(DatabaseConfig::Sqlite {
47+
database_name: database_name.clone(),
48+
}),
49+
}
50+
}
51+
}
52+
53+
/// Tracker core configuration section (application DTO)
54+
///
55+
/// Contains core tracker settings like database and privacy mode.
56+
///
57+
/// # Examples
58+
///
59+
/// ```json
60+
/// {
61+
/// "database": {
62+
/// "driver": "sqlite3",
63+
/// "database_name": "tracker.db"
64+
/// },
65+
/// "private": false
66+
/// }
67+
/// ```
68+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
69+
pub struct TrackerCoreSection {
70+
/// Database configuration
71+
pub database: DatabaseSection,
72+
/// Privacy mode: true for private tracker, false for public
73+
pub private: bool,
74+
}
75+
76+
impl TrackerCoreSection {
77+
/// Converts this DTO to the domain `TrackerCoreConfig` type.
78+
///
79+
/// # Errors
80+
///
81+
/// Returns error if database validation fails.
82+
pub fn to_tracker_core_config(&self) -> Result<TrackerCoreConfig, CreateConfigError> {
83+
Ok(TrackerCoreConfig {
84+
database: self.database.to_database_config()?,
85+
private: self.private,
86+
})
87+
}
88+
}
89+
90+
#[cfg(test)]
91+
mod tests {
92+
use super::*;
93+
94+
#[test]
95+
fn test_tracker_core_section_converts_to_domain_config() {
96+
let section = TrackerCoreSection {
97+
database: DatabaseSection::Sqlite {
98+
database_name: "tracker.db".to_string(),
99+
},
100+
private: false,
101+
};
102+
103+
let config = section.to_tracker_core_config().unwrap();
104+
105+
assert_eq!(
106+
config.database,
107+
DatabaseConfig::Sqlite {
108+
database_name: "tracker.db".to_string()
109+
}
110+
);
111+
assert!(!config.private);
112+
}
113+
114+
#[test]
115+
fn test_tracker_core_section_handles_private_mode() {
116+
let section = TrackerCoreSection {
117+
database: DatabaseSection::Sqlite {
118+
database_name: "private.db".to_string(),
119+
},
120+
private: true,
121+
};
122+
123+
let config = section.to_tracker_core_config().unwrap();
124+
125+
assert!(config.private);
126+
}
127+
128+
#[test]
129+
fn test_tracker_core_section_serialization() {
130+
let section = TrackerCoreSection {
131+
database: DatabaseSection::Sqlite {
132+
database_name: "tracker.db".to_string(),
133+
},
134+
private: false,
135+
};
136+
137+
let json = serde_json::to_string(&section).unwrap();
138+
assert!(json.contains("\"driver\":\"sqlite3\""));
139+
assert!(json.contains("\"database_name\":\"tracker.db\""));
140+
assert!(json.contains("\"private\":false"));
141+
}
142+
143+
#[test]
144+
fn test_tracker_core_section_deserialization() {
145+
let json = r#"{
146+
"database": {
147+
"driver": "sqlite3",
148+
"database_name": "tracker.db"
149+
},
150+
"private": true
151+
}"#;
152+
153+
let section: TrackerCoreSection = serde_json::from_str(json).unwrap();
154+
155+
assert_eq!(
156+
section.database,
157+
DatabaseSection::Sqlite {
158+
database_name: "tracker.db".to_string()
159+
}
160+
);
161+
assert!(section.private);
162+
}
163+
}

0 commit comments

Comments
 (0)