supabase_rust_realtime/
message.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4/// Represents a full message received or sent over the WebSocket.
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct RealtimeMessage {
7    pub topic: String,
8    pub event: ChannelEvent,        // Use the ChannelEvent enum
9    pub payload: serde_json::Value, // Flexible payload
10    #[serde(rename = "ref")]
11    pub message_ref: serde_json::Value, // Can be string or null
12}
13
14/// チャンネルイベント (including Phoenix/Realtime specific events)
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
16#[serde(rename_all = "snake_case")] // Use snake_case for serialization
17pub enum ChannelEvent {
18    Insert, // Database change events
19    Update,
20    Delete,
21    All,             // Wildcard for database changes
22    PostgresChanges, // Specific event type for Supabase DB changes
23
24    #[serde(rename = "phx_join")] // Explicit rename for Phoenix events
25    PhoenixJoin,
26    #[serde(rename = "phx_reply")]
27    PhoenixReply,
28    #[serde(rename = "phx_error")]
29    PhoenixError,
30    #[serde(rename = "phx_close")]
31    PhoenixClose,
32
33    Heartbeat,
34    Presence,
35    Broadcast,
36    // Add other known events as needed
37}
38
39impl std::fmt::Display for ChannelEvent {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        // Use serde to get the correct string representation
42        // This relies on the rename attributes defined above.
43        write!(
44            f,
45            "{}",
46            serde_json::to_string(self).unwrap_or_else(|_| format!("{:?}", self))
47        )
48        // Simple match for basic cases (less reliable than serde)
49        // match self {
50        //     Self::Insert => write!(f, "INSERT"),
51        //     Self::Update => write!(f, "UPDATE"),
52        //     Self::Delete => write!(f, "DELETE"),
53        //     Self::All => write!(f, "*"),
54        //     Self::PostgresChanges => write!(f, "postgres_changes"),
55        //     Self::PhoenixJoin => write!(f, "phx_join"),
56        //     Self::PhoenixReply => write!(f, "phx_reply"),
57        //     Self::PhoenixError => write!(f, "phx_error"),
58        //     Self::PhoenixClose => write!(f, "phx_close"),
59        //     Self::Heartbeat => write!(f, "heartbeat"),
60        //     Self::Presence => write!(f, "presence"),
61        //     Self::Broadcast => write!(f, "broadcast"),
62        // }
63    }
64}
65
66/// メッセージペイロード
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct Payload {
69    // Consider making fields private and using accessors if necessary
70    pub data: serde_json::Value,
71    #[serde(rename = "type")] // Map 'type' field in JSON
72    pub event_type: Option<String>,
73    pub timestamp: Option<String>, // Timestamps often come as strings
74}
75
76/// プレゼンス変更情報
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct PresenceChange {
79    pub joins: HashMap<String, serde_json::Value>,
80    pub leaves: HashMap<String, serde_json::Value>,
81}
82
83/// プレゼンス状態全体
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct PresenceState {
86    // Consider wrapping HashMap for better type safety/abstraction
87    pub state: HashMap<String, serde_json::Value>,
88}
89
90impl PresenceState {
91    pub fn new() -> Self {
92        Self {
93            state: HashMap::new(),
94        }
95    }
96
97    /// Apply presence diff to update the state
98    pub fn sync(&mut self, presence_diff: &PresenceChange) {
99        for (key, value) in &presence_diff.joins {
100            self.state.insert(key.clone(), value.clone());
101        }
102        for key in presence_diff.leaves.keys() {
103            self.state.remove(key);
104        }
105    }
106
107    /// List current presence state as key-value pairs
108    pub fn list(&self) -> Vec<(String, serde_json::Value)> {
109        self.state
110            .iter()
111            .map(|(k, v)| (k.clone(), v.clone()))
112            .collect()
113    }
114
115    /// Get presence info for a specific key
116    pub fn get(&self, key: &str) -> Option<&serde_json::Value> {
117        self.state.get(key)
118    }
119}
120
121impl Default for PresenceState {
122    fn default() -> Self {
123        Self::new()
124    }
125}