supabase_client_graphql/
types.rs1use serde::{Deserialize, Serialize};
2
3use crate::error::GraphqlApiError;
4
5#[derive(Debug, Clone, Deserialize)]
9pub struct GraphqlResponse<T> {
10 pub data: Option<T>,
11 #[serde(default)]
12 pub errors: Vec<GraphqlApiError>,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
19#[serde(rename_all = "camelCase")]
20pub struct Connection<T> {
21 pub edges: Vec<Edge<T>>,
22 pub page_info: PageInfo,
23 #[serde(default)]
24 pub total_count: Option<i64>,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct Edge<T> {
30 pub cursor: String,
31 pub node: T,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
36#[serde(rename_all = "camelCase")]
37pub struct PageInfo {
38 pub has_next_page: bool,
39 pub has_previous_page: bool,
40 #[serde(default)]
41 pub start_cursor: Option<String>,
42 #[serde(default)]
43 pub end_cursor: Option<String>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(rename_all = "camelCase")]
49pub struct MutationResult<T> {
50 pub affected_count: i64,
51 pub records: Vec<T>,
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use serde_json::json;
58
59 #[test]
60 fn deserialize_connection() {
61 let json = json!({
62 "edges": [
63 {
64 "cursor": "abc123",
65 "node": { "id": 1, "title": "Hello" }
66 }
67 ],
68 "pageInfo": {
69 "hasNextPage": true,
70 "hasPreviousPage": false,
71 "startCursor": "abc123",
72 "endCursor": "abc123"
73 },
74 "totalCount": 42
75 });
76
77 let conn: Connection<serde_json::Value> = serde_json::from_value(json).unwrap();
78 assert_eq!(conn.edges.len(), 1);
79 assert_eq!(conn.edges[0].cursor, "abc123");
80 assert!(conn.page_info.has_next_page);
81 assert!(!conn.page_info.has_previous_page);
82 assert_eq!(conn.total_count, Some(42));
83 }
84
85 #[test]
86 fn deserialize_connection_no_total_count() {
87 let json = json!({
88 "edges": [],
89 "pageInfo": {
90 "hasNextPage": false,
91 "hasPreviousPage": false
92 }
93 });
94
95 let conn: Connection<serde_json::Value> = serde_json::from_value(json).unwrap();
96 assert!(conn.edges.is_empty());
97 assert_eq!(conn.total_count, None);
98 }
99
100 #[test]
101 fn deserialize_mutation_result() {
102 let json = json!({
103 "affectedCount": 2,
104 "records": [
105 { "id": 1, "title": "A" },
106 { "id": 2, "title": "B" }
107 ]
108 });
109
110 let result: MutationResult<serde_json::Value> = serde_json::from_value(json).unwrap();
111 assert_eq!(result.affected_count, 2);
112 assert_eq!(result.records.len(), 2);
113 }
114
115 #[test]
116 fn deserialize_graphql_response_with_data() {
117 let json = json!({
118 "data": { "blogCollection": { "edges": [] } }
119 });
120
121 let resp: GraphqlResponse<serde_json::Value> = serde_json::from_value(json).unwrap();
122 assert!(resp.data.is_some());
123 assert!(resp.errors.is_empty());
124 }
125
126 #[test]
127 fn deserialize_graphql_response_with_errors() {
128 let json = json!({
129 "data": null,
130 "errors": [
131 { "message": "Column not found" }
132 ]
133 });
134
135 let resp: GraphqlResponse<serde_json::Value> = serde_json::from_value(json).unwrap();
136 assert!(resp.data.is_none());
137 assert_eq!(resp.errors.len(), 1);
138 assert_eq!(resp.errors[0].message, "Column not found");
139 }
140}