graphql_ws_client/
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/// An abstraction over GraphQL operations.
12pub trait GraphqlOperation: serde::Serialize {
13    /// The actual response & error type of this operation.
14    type Response;
15
16    /// The error that will be returned from failed attempts to decode a `Response`.
17    type Error: std::error::Error;
18
19    /// Decodes a `GenericResponse` into the actual response that will be returned
20    /// to users for this operation.
21    fn decode(&self, data: serde_json::Value) -> Result<Self::Response, Self::Error>;
22}
23
24#[cfg(feature = "client-cynic")]
25mod cynic {
26    use super::GraphqlOperation;
27
28    #[cfg_attr(docsrs, doc(cfg(feature = "client-cynic")))]
29    impl<ResponseData, Variables> GraphqlOperation
30        for ::cynic::StreamingOperation<ResponseData, Variables>
31    where
32        ResponseData: serde::de::DeserializeOwned,
33        Variables: serde::Serialize,
34    {
35        type Response = ::cynic::GraphQlResponse<ResponseData>;
36
37        type Error = serde_json::Error;
38
39        fn decode(&self, response: serde_json::Value) -> Result<Self::Response, Self::Error> {
40            serde_json::from_value(response)
41        }
42    }
43}
44
45#[cfg(feature = "client-graphql-client")]
46pub use self::graphql_client::StreamingOperation;
47
48#[cfg(feature = "client-graphql-client")]
49mod graphql_client {
50    use super::GraphqlOperation;
51    use ::graphql_client::{GraphQLQuery, QueryBody, Response};
52    use std::marker::PhantomData;
53
54    /// A streaming operation for a [`GraphQLQuery`]
55    #[cfg_attr(docsrs, doc(cfg(feature = "client-graphql-client")))]
56    pub struct StreamingOperation<Q: GraphQLQuery> {
57        inner: QueryBody<Q::Variables>,
58        phantom: PhantomData<Q>,
59    }
60
61    impl<Q: GraphQLQuery> StreamingOperation<Q> {
62        /// Constructs a [`StreamingOperation`]
63        pub fn new(variables: Q::Variables) -> Self {
64            Self {
65                inner: Q::build_query(variables),
66                phantom: PhantomData,
67            }
68        }
69    }
70
71    impl<Q: GraphQLQuery> serde::Serialize for StreamingOperation<Q> {
72        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73        where
74            S: serde::Serializer,
75        {
76            self.inner.serialize(serializer)
77        }
78    }
79
80    impl<Q: GraphQLQuery> GraphqlOperation for StreamingOperation<Q> {
81        type Response = Response<Q::ResponseData>;
82
83        type Error = serde_json::Error;
84
85        fn decode(&self, response: serde_json::Value) -> Result<Self::Response, Self::Error> {
86            serde_json::from_value(response)
87        }
88    }
89}