grafbase_sdk_mock/
entity_resolver.rs

1use async_graphql::{ServerError, dynamic::ResolverContext};
2
3/// Context provided to entity resolvers.
4pub struct EntityResolverContext<'a> {
5    /// The underlying resolver context.
6    pub resolver_context: &'a ResolverContext<'a>,
7    /// The __typename of the entity being resolved.
8    pub typename: String,
9    /// The representation of the entity being resolved.
10    pub representation: serde_json::Map<String, serde_json::Value>,
11}
12
13impl<'a> EntityResolverContext<'a> {
14    pub(super) fn new(resolver_context: &'a ResolverContext<'a>, representation: serde_json::Value) -> Self {
15        let serde_json::Value::Object(representation) = representation else {
16            panic!("repesentations need to be objects");
17        };
18
19        let typename = representation["__typename"]
20            .as_str()
21            .expect("a representation must have __typename")
22            .into();
23
24        EntityResolverContext {
25            resolver_context,
26            typename,
27            representation,
28        }
29    }
30
31    /// Adds an error to the response.
32    pub fn add_error(&self, error: ServerError) {
33        self.resolver_context.query_env.errors.lock().unwrap().push(error);
34    }
35}
36
37pub trait EntityResolver: Send + Sync {
38    fn resolve(&mut self, context: EntityResolverContext<'_>) -> Option<serde_json::Value>;
39}
40
41impl<F> EntityResolver for F
42where
43    for<'a> F: FnMut(EntityResolverContext<'a>) -> Option<serde_json::Value> + Send + Sync,
44{
45    fn resolve(&mut self, context: EntityResolverContext<'_>) -> Option<serde_json::Value> {
46        self(context)
47    }
48}
49
50impl EntityResolver for serde_json::Value {
51    fn resolve(&mut self, _context: EntityResolverContext<'_>) -> Option<serde_json::Value> {
52        Some(self.clone())
53    }
54}
55
56impl EntityResolver for ServerError {
57    fn resolve(&mut self, context: EntityResolverContext<'_>) -> Option<serde_json::Value> {
58        context.add_error(self.clone());
59        None
60    }
61}
62
63impl EntityResolver for Option<serde_json::Value> {
64    fn resolve(&mut self, _context: EntityResolverContext<'_>) -> Option<serde_json::Value> {
65        self.clone()
66    }
67}