grafbase_sdk/extension/
resolver.rs

1use crate::{
2    component::AnyExtension,
3    types::{Error, FieldDefinitionDirective, FieldInputs, FieldOutput},
4    Headers,
5};
6
7use super::Extension;
8
9/// A trait that extends `Extension` and provides functionality for resolving fields.
10///
11/// Implementors of this trait are expected to provide a method to resolve field values based on
12/// the given context, directive, and inputs. This is typically used in scenarios where field
13/// resolution logic needs to be encapsulated within a resolver object, allowing for modular
14/// and reusable code design.
15pub trait Resolver: Extension {
16    /// Resolves a field value based on the given context, directive, definition, and inputs.
17    ///
18    /// # Arguments
19    ///
20    /// * `headers` - The subgraph headers associated with this field resolution
21    /// * `subgraph_name` - The name of the subgraph associated with this field resolution
22    /// * `directive` - The directive associated with this field resolution
23    /// * `definition` - The field definition containing metadata
24    /// * `inputs` - The input values provided for this field
25    ///
26    /// # Returns
27    ///
28    /// Returns a `Result` containing either the resolved `FieldOutput` value or an `Error`
29    fn resolve_field(
30        &mut self,
31        headers: Headers,
32        subgraph_name: &str,
33        directive: FieldDefinitionDirective<'_>,
34        inputs: FieldInputs,
35    ) -> Result<FieldOutput, Error>;
36
37    /// Resolves a subscription field by setting up a subscription handler.
38    ///
39    /// # Arguments
40    ///
41    /// * `headers` - The subgraph headers associated with this field resolution
42    /// * `directive` - The directive associated with this subscription field
43    /// * `definition` - The field definition containing metadata about the subscription
44    ///
45    /// # Returns
46    ///
47    /// Returns a `Result` containing either a boxed `Subscriber` implementation or an `Error`
48    fn resolve_subscription(
49        &mut self,
50        headers: Headers,
51        subgraph_name: &str,
52        directive: FieldDefinitionDirective<'_>,
53    ) -> Result<Box<dyn Subscription>, Error>;
54}
55
56/// A trait for consuming field outputs from streams.
57///
58/// This trait provides an abstraction over different implementations
59/// of subscriptions to field output streams. Implementors should handle
60/// the details of their specific transport mechanism while providing a
61/// consistent interface for consumers.
62pub trait Subscription {
63    /// Retrieves the next field output from the subscription.
64    ///
65    /// Returns:
66    /// - `Ok(Some(FieldOutput))` if a field output was available
67    /// - `Ok(None)` if the subscription has ended normally
68    /// - `Err(Error)` if an error occurred while retrieving the next field output
69    fn next(&mut self) -> Result<Option<FieldOutput>, Error>;
70}
71
72#[doc(hidden)]
73pub fn register<T: Resolver>() {
74    pub(super) struct Proxy<T: Resolver>(T);
75
76    impl<T: Resolver> AnyExtension for Proxy<T> {
77        fn resolve_field(
78            &mut self,
79            headers: Headers,
80            subgraph_name: &str,
81            directive: FieldDefinitionDirective<'_>,
82            inputs: FieldInputs,
83        ) -> Result<FieldOutput, Error> {
84            Resolver::resolve_field(&mut self.0, headers, subgraph_name, directive, inputs)
85        }
86        fn resolve_subscription(
87            &mut self,
88            headers: Headers,
89            subgraph_name: &str,
90            directive: FieldDefinitionDirective<'_>,
91        ) -> Result<Box<dyn Subscription>, Error> {
92            Resolver::resolve_subscription(&mut self.0, headers, subgraph_name, directive)
93        }
94    }
95    crate::component::register_extension(Box::new(|schema_directives, config| {
96        <T as Extension>::new(schema_directives, config)
97            .map(|extension| Box::new(Proxy(extension)) as Box<dyn AnyExtension>)
98    }))
99}