Skip to main content

sova_graphql/
bound.rs

1//! `req.graphql()` — outbound client + optional mounted schema.
2
3use crate::client::{GraphQlClient, PendingGraphql};
4use crate::error::GraphqlError;
5use sova_core::Request;
6
7#[cfg(feature = "server")]
8use crate::server::SchemaHandle;
9
10pub trait GraphQlExt {
11    fn graphql(&self) -> GraphQlBound;
12    fn try_graphql(&self) -> Option<GraphQlBound>;
13}
14
15impl GraphQlExt for Request {
16    fn graphql(&self) -> GraphQlBound {
17        GraphQlBound {
18            client: self.state::<GraphQlClient>(),
19        }
20    }
21
22    fn try_graphql(&self) -> Option<GraphQlBound> {
23        self.try_state::<GraphQlClient>()
24            .map(|client| GraphQlBound { client })
25    }
26}
27
28/// Access the mounted GraphQL schema from HTTP handlers (server install).
29#[cfg(feature = "server")]
30pub trait GraphqlServerExt {
31    fn graphql_schema(&self) -> std::sync::Arc<SchemaHandle>;
32    fn try_graphql_schema(&self) -> Option<std::sync::Arc<SchemaHandle>>;
33}
34
35#[cfg(feature = "server")]
36impl GraphqlServerExt for Request {
37    fn graphql_schema(&self) -> std::sync::Arc<SchemaHandle> {
38        self.state::<SchemaHandle>()
39    }
40
41    fn try_graphql_schema(&self) -> Option<std::sync::Arc<SchemaHandle>> {
42        self.try_state::<SchemaHandle>()
43    }
44}
45
46pub struct GraphQlBound {
47    client: std::sync::Arc<GraphQlClient>,
48}
49
50impl GraphQlBound {
51    pub fn client(&self) -> &GraphQlClient {
52        &self.client
53    }
54
55    pub fn query(&self, query: impl Into<String>) -> PendingGraphql {
56        self.client.query(query)
57    }
58
59    pub fn mutation(&self, query: impl Into<String>) -> PendingGraphql {
60        self.client.mutation(query)
61    }
62
63    pub async fn execute(
64        &self,
65        query: impl Into<String>,
66    ) -> Result<serde_json::Value, GraphqlError> {
67        self.query(query).data().await
68    }
69}