thegraph_graphql_http/
compat.rs

1//! Compatibility layer for third-party GraphQL libraries.
2
3#[cfg(feature = "graphql-parser")]
4pub mod compat_graphql_parser {
5    use graphql_parser::query::Text;
6
7    use crate::graphql::{Document, IntoDocument};
8
9    // Implement `IntoRequestParameters` for `graphql_parser::query::Document` so that we can use
10    // `graphql_parser` to parse GraphQL queries.
11    //
12    // As any type implementing `IntoQuery` also implements `IntoRequestParameters`, this allows us to
13    // seamlessly support `graphql_parser` generated queries.
14    impl<'a, T: Text<'a>> IntoDocument for graphql_parser::query::Document<'a, T> {
15        fn into_document(self) -> Document {
16            Document::new(self.to_string())
17        }
18    }
19}
20
21#[cfg(feature = "graphql-client")]
22pub mod compat_graphql_client {
23    use graphql_client::QueryBody;
24
25    use crate::{
26        graphql::IntoDocument,
27        http::request::{IntoRequestParameters, RequestParameters},
28    };
29
30    // Implement `IntoRequestParameters` for `graphql_client::QueryBody` so that we can seamlessly
31    // support `graphql_client` generated queries.
32    impl<V> IntoRequestParameters for QueryBody<V>
33    where
34        V: serde::ser::Serialize,
35    {
36        fn into_request_parameters(self) -> RequestParameters {
37            let query = self.query.into_document();
38
39            // Do not send the `operation_name` field if it is empty.
40            let operation_name = if !self.operation_name.is_empty() {
41                Some(self.operation_name.to_owned())
42            } else {
43                None
44            };
45
46            // Do not send the `variables` field if the json serialization fails, or if the
47            // serialization result is not a JSON object.
48            let variables = match serde_json::to_value(self.variables) {
49                Ok(serde_json::Value::Object(vars)) => Some(vars),
50                _ => None,
51            };
52
53            RequestParameters {
54                query,
55                operation_name,
56                variables: variables.unwrap_or_default(),
57                extensions: Default::default(),
58            }
59        }
60    }
61}
62
63#[cfg(feature = "async-graphql")]
64pub mod compat_async_graphql {
65    use async_graphql::Request;
66
67    use crate::{
68        graphql::IntoDocument,
69        http::request::{IntoRequestParameters, RequestParameters},
70    };
71
72    // Implement `IntoRequestParameters` for `async_graphql::Request` so that we can seamlessly
73    // support `async_graphql` requests.
74    impl IntoRequestParameters for Request {
75        fn into_request_parameters(self) -> RequestParameters {
76            let query = self.query.into_document();
77
78            // Serialize the `async_graphql::Request` _variables_ and _extensions_ fields to JSON
79            // objects. If the serialization fails, or if the result is not a JSON object, avoid
80            // sending an invalid JSON to the server.
81            let variables = match serde_json::to_value(self.variables) {
82                Ok(serde_json::Value::Object(vars)) => vars,
83                _ => Default::default(),
84            };
85
86            let extensions = match serde_json::to_value(self.extensions) {
87                Ok(serde_json::Value::Object(vars)) => vars,
88                _ => Default::default(),
89            };
90
91            RequestParameters {
92                query,
93                operation_name: self.operation_name,
94                variables,
95                extensions,
96            }
97        }
98    }
99}