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}