Skip to main content

ferro_notifications/channels/
database.rs

1//! Database notification channel.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6
7/// A database message for in-app notifications.
8///
9/// Database notifications are stored in the database and can be
10/// displayed in the application's notification center.
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct DatabaseMessage {
13    /// Notification type identifier.
14    pub notification_type: String,
15    /// Notification data as key-value pairs.
16    pub data: HashMap<String, Value>,
17}
18
19impl DatabaseMessage {
20    /// Create a new database message with a type.
21    pub fn new(notification_type: impl Into<String>) -> Self {
22        Self {
23            notification_type: notification_type.into(),
24            data: HashMap::new(),
25        }
26    }
27
28    /// Add a data field to the notification.
29    pub fn data<V: Serialize>(mut self, key: impl Into<String>, value: V) -> Self {
30        if let Ok(v) = serde_json::to_value(value) {
31            self.data.insert(key.into(), v);
32        }
33        self
34    }
35
36    /// Add multiple data fields from a map.
37    pub fn with_data(mut self, data: HashMap<String, Value>) -> Self {
38        self.data.extend(data);
39        self
40    }
41
42    /// Get a data field value.
43    pub fn get(&self, key: &str) -> Option<&Value> {
44        self.data.get(key)
45    }
46
47    /// Serialize the entire message to JSON.
48    pub fn to_json(&self) -> Result<String, serde_json::Error> {
49        serde_json::to_string(self)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_database_message_builder() {
59        let msg = DatabaseMessage::new("order_shipped")
60            .data("order_id", 123)
61            .data("tracking", "ABC123");
62
63        assert_eq!(msg.notification_type, "order_shipped");
64        assert_eq!(msg.get("order_id"), Some(&Value::Number(123.into())));
65        assert_eq!(msg.get("tracking"), Some(&Value::String("ABC123".into())));
66    }
67
68    #[test]
69    fn test_database_message_to_json() {
70        let msg = DatabaseMessage::new("test").data("key", "value");
71
72        let json = msg.to_json().unwrap();
73        assert!(json.contains("\"notification_type\":\"test\""));
74        assert!(json.contains("\"key\":\"value\""));
75    }
76}