plunk-rs 0.1.2

Async Rust client for the Plunk transactional email API
Documentation
use crate::wire::{WireContact, WireDeliveredEmail, WireSendResponseData};

/// Successful send result.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SendResponse {
    deliveries: Vec<Delivery>,
    timestamp: String,
}

impl SendResponse {
    pub fn deliveries(&self) -> &[Delivery] {
        &self.deliveries
    }

    pub fn timestamp(&self) -> &str {
        &self.timestamp
    }
}

impl From<WireSendResponseData> for SendResponse {
    fn from(value: WireSendResponseData) -> Self {
        Self {
            deliveries: value.emails.into_iter().map(Delivery::from).collect(),
            timestamp: value.timestamp,
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Delivery {
    contact: Contact,
    id: String,
}

impl Delivery {
    pub fn contact(&self) -> &Contact {
        &self.contact
    }

    pub fn id(&self) -> &str {
        &self.id
    }
}

impl From<WireDeliveredEmail> for Delivery {
    fn from(value: WireDeliveredEmail) -> Self {
        Self {
            contact: Contact::from(value.contact),
            id: value.email,
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Contact {
    id: String,
    email: String,
}

impl Contact {
    pub fn id(&self) -> &str {
        &self.id
    }

    pub fn email(&self) -> &str {
        &self.email
    }
}

impl From<WireContact> for Contact {
    fn from(value: WireContact) -> Self {
        Self {
            id: value.id,
            email: value.email,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::wire::WireSendResponse;
    use serde_json::json;

    #[test]
    fn deserializes_success_response_into_domain_types() {
        let response = serde_json::from_value::<WireSendResponse>(json!({
            "success": true,
            "data": {
                "emails": [
                    {
                        "contact": {
                            "id": "cnt_abc123",
                            "email": "user@example.com"
                        },
                        "email": "ac32f08e-c6b9-45d3-9824-a73dff1e3bbf"
                    }
                ],
                "timestamp": "2025-01-15T10:30:00.000Z"
            }
        }))
        .unwrap();

        let response = SendResponse::from(response.data);

        assert_eq!(response.deliveries().len(), 1);
        assert_eq!(
            response.deliveries()[0].contact().email(),
            "user@example.com"
        );
        assert_eq!(
            response.deliveries()[0].id(),
            "ac32f08e-c6b9-45d3-9824-a73dff1e3bbf"
        );
    }
}