commit_bridge/domain/
target_repo.rs1use crate::error::ValidationError;
4use rovo::schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
9#[serde(try_from = "String", into = "String")]
10pub struct TargetRepo(String);
11
12impl TargetRepo {
13 pub fn new(value: String) -> Result<Self, ValidationError> {
15 Self::try_from(value)
16 }
17
18 pub fn into_inner(self) -> String {
20 self.0
21 }
22
23 pub fn as_str(&self) -> &str {
25 &self.0
26 }
27}
28
29impl std::fmt::Display for TargetRepo {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 write!(f, "{}", self.0)
32 }
33}
34
35crate::derive_sqlx_traits!(TargetRepo);
36
37impl TryFrom<String> for TargetRepo {
38 type Error = ValidationError;
39
40 fn try_from(value: String) -> Result<Self, Self::Error> {
41 let parts: Vec<&str> = value.split('/').collect();
42 match parts.as_slice() {
43 [owner, repo] if !owner.is_empty() && !repo.is_empty() => Ok(TargetRepo(value)),
44 _ => {
45 tracing::warn!(
46 "Validation failed for TargetRepo: {}. Must be in owner/repo format",
47 value
48 );
49 Err(ValidationError::InvalidValue(format!(
50 "Target repository must be in owner/repo format: {}",
51 value
52 )))
53 }
54 }
55 }
56}
57
58impl From<TargetRepo> for String {
59 fn from(val: TargetRepo) -> Self {
60 val.0
61 }
62}