graphql_ws_client_old_protocol/
graphql.rs

1//! This module contains traits that abstract over GraphQL implementations,
2//! allowing this library to be used with different GraphQL client libraries.
3//!
4//! Support is provided for [`cynic`][cynic] & [`graphql_client`][graphql-client],
5//! but other client libraries can be added by implementing these traits for
6//! those libraries.
7//!
8//! [cynic]: https://cynic-rs.dev
9//! [graphql-client]: https://github.com/graphql-rust/graphql-client
10
11/// A trait for GraphQL clients.
12pub trait GraphqlClient {
13    /// The generic response type for this GraphqlClient implementation
14    ///
15    /// Our client will decode this, then pass it to a `GraphqlOperation` for decoding
16    /// to the specific response type of the GraphqlOperation.
17    type Response: serde::de::DeserializeOwned + Send;
18
19    /// The error that will be returned from failed attempts to decode a `Response`.
20    type DecodeError: std::error::Error + Send + 'static;
21
22    /// Decodes some error JSON into a `Response`
23    fn error_response(errors: Vec<serde_json::Value>) -> Result<Self::Response, Self::DecodeError>;
24}
25
26/// An abstraction over GraphQL operations.
27pub trait GraphqlOperation: serde::Serialize {
28    /// The "generic" response type.  A graphql-ws-client supports running multiple
29    /// operations at a time.  This GenericResponse is what will intially be decoded -
30    /// with the `decode` function converting this into the actual operation response.
31    ///
32    /// This type needs to match up with [GraphqlClient::Response].
33    type GenericResponse;
34
35    /// The actual response & error type of this operation.
36    type Response;
37
38    /// The error that will be returned from failed attempts to decode a `Response`.
39    type Error: std::error::Error;
40
41    /// Decodes a `GenericResponse` into the actual response that will be returned
42    /// to users for this operation.
43    fn decode(&self, data: Self::GenericResponse) -> Result<Self::Response, Self::Error>;
44}
45
46#[cfg(feature = "cynic")]
47pub use self::cynic::Cynic;
48
49#[cfg(feature = "cynic")]
50mod cynic {
51    use super::*;
52
53    /// Provides an implementation of [GraphqlClient] for the cynic GraphQL crate
54    pub struct Cynic {}
55
56    impl GraphqlClient for Cynic {
57        type Response = ::cynic::GraphQlResponse<serde_json::Value>;
58
59        type DecodeError = serde_json::Error;
60
61        fn error_response(
62            errors: Vec<serde_json::Value>,
63        ) -> Result<Self::Response, Self::DecodeError> {
64            Ok(::cynic::GraphQlResponse {
65                data: None,
66                errors: Some(
67                    errors
68                        .into_iter()
69                        .map(serde_json::from_value)
70                        .collect::<Result<Vec<_>, _>>()?,
71                ),
72            })
73        }
74    }
75
76    impl<ResponseData, Variables> GraphqlOperation
77        for ::cynic::StreamingOperation<ResponseData, Variables>
78    where
79        ResponseData: serde::de::DeserializeOwned,
80        Variables: serde::Serialize,
81    {
82        type GenericResponse = ::cynic::GraphQlResponse<serde_json::Value>;
83
84        type Response = ::cynic::GraphQlResponse<ResponseData>;
85
86        type Error = serde_json::Error;
87
88        fn decode(&self, response: Self::GenericResponse) -> Result<Self::Response, Self::Error> {
89            Ok(::cynic::GraphQlResponse {
90                data: response
91                    .data
92                    .map(|data| serde_json::from_value(data))
93                    .transpose()?,
94                errors: response.errors,
95            })
96        }
97    }
98}
99
100#[cfg(feature = "graphql_client")]
101pub use self::graphql_client::GraphQLClient;
102
103#[cfg(feature = "graphql_client")]
104pub use self::graphql_client::StreamingOperation;
105
106#[cfg(feature = "graphql_client")]
107mod graphql_client {
108    use super::*;
109    use ::graphql_client::{GraphQLQuery, QueryBody, Response};
110    use std::marker::PhantomData;
111
112    /// Provides an implementation of [GraphqlClient] for the graphql_client GraphQL crate
113    pub struct GraphQLClient {}
114
115    impl GraphqlClient for GraphQLClient {
116        type Response = Response<serde_json::Value>;
117
118        type DecodeError = serde_json::Error;
119
120        fn error_response(
121            errors: Vec<serde_json::Value>,
122        ) -> Result<Self::Response, Self::DecodeError> {
123            Ok(Response {
124                data: None,
125                errors: Some(
126                    errors
127                        .into_iter()
128                        .map(serde_json::from_value)
129                        .collect::<Result<Vec<_>, _>>()?,
130                ),
131                extensions: None,
132            })
133        }
134    }
135
136    /// A streaming operation for a GraphQLQuery
137    pub struct StreamingOperation<Q: GraphQLQuery> {
138        inner: QueryBody<Q::Variables>,
139        phantom: PhantomData<Q>,
140    }
141
142    impl<Q: GraphQLQuery> StreamingOperation<Q> {
143        /// Constructs a StreamingOperation
144        pub fn new(variables: Q::Variables) -> Self {
145            Self {
146                inner: Q::build_query(variables),
147                phantom: PhantomData::default(),
148            }
149        }
150
151        fn decode_response(
152            &self,
153            response: Response<serde_json::Value>,
154        ) -> Result<Response<Q::ResponseData>, serde_json::Error> {
155            if let Some(data) = response.data {
156                Ok(::graphql_client::Response {
157                    data: Some(serde_json::from_value(data)?),
158                    errors: response.errors,
159                    extensions: response.extensions,
160                })
161            } else {
162                Ok(::graphql_client::Response {
163                    data: None,
164                    errors: response.errors,
165                    extensions: response.extensions,
166                })
167            }
168        }
169    }
170
171    impl<Q: GraphQLQuery> serde::Serialize for StreamingOperation<Q> {
172        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
173        where
174            S: serde::Serializer,
175        {
176            self.inner.serialize(serializer)
177        }
178    }
179
180    impl<Q: GraphQLQuery> GraphqlOperation for StreamingOperation<Q> {
181        type GenericResponse = Response<serde_json::Value>;
182
183        type Response = Response<Q::ResponseData>;
184
185        type Error = serde_json::Error;
186
187        fn decode(&self, response: Self::GenericResponse) -> Result<Self::Response, Self::Error> {
188            self.decode_response(response)
189        }
190    }
191}