Skip to main content

fraiseql_server/realtime/
protocol.rs

1//! Wire protocol messages for the realtime `WebSocket` endpoint.
2//!
3//! Defines the JSON message types exchanged between server and client
4//! over the `/realtime/v1` `WebSocket` connection.
5
6use serde::{Deserialize, Serialize};
7
8/// Message sent by the client over the `WebSocket` connection.
9#[derive(Debug, Clone, Deserialize)]
10#[serde(tag = "type", rename_all = "snake_case")]
11#[non_exhaustive]
12pub enum ClientMessage {
13    /// Heartbeat response from client.
14    Pong,
15
16    /// Subscribe to entity change events.
17    Subscribe {
18        /// Entity name to subscribe to (e.g., `"Post"`).
19        entity: String,
20        /// Event type filter: `"*"`, `"INSERT"`, `"UPDATE"`, or `"DELETE"`.
21        #[serde(default = "default_event_filter")]
22        event:  String,
23        /// Optional field filter in `field=op.value` format (e.g., `"author_id=eq.123"`).
24        #[serde(default)]
25        filter: Option<String>,
26    },
27
28    /// Unsubscribe from entity change events.
29    Unsubscribe {
30        /// Entity name to unsubscribe from.
31        entity: String,
32    },
33}
34
35/// Default event filter: all events.
36fn default_event_filter() -> String {
37    "*".to_owned()
38}
39
40/// Message sent by the server to the client.
41#[derive(Debug, Clone, Serialize)]
42#[serde(tag = "type", rename_all = "snake_case")]
43#[non_exhaustive]
44pub enum ServerMessage {
45    /// Sent after successful authentication and connection setup.
46    Connected {
47        /// Unique identifier for this connection.
48        connection_id: String,
49    },
50
51    /// Periodic heartbeat from server.
52    Ping,
53
54    /// Authentication token has expired; connection will close.
55    TokenExpired,
56
57    /// Subscription confirmed.
58    Subscribed {
59        /// Entity that was subscribed to.
60        entity: String,
61    },
62
63    /// Unsubscription confirmed.
64    Unsubscribed {
65        /// Entity that was unsubscribed from.
66        entity: String,
67    },
68
69    /// Error message.
70    Error {
71        /// Human-readable error description.
72        message: String,
73    },
74}
75
76impl ServerMessage {
77    /// Serialize this message to a JSON string.
78    ///
79    /// # Errors
80    ///
81    /// Returns `serde_json::Error` if serialization fails (should not happen
82    /// for well-formed `ServerMessage` variants).
83    pub fn to_json(&self) -> serde_json::Result<String> {
84        serde_json::to_string(self)
85    }
86}