grafbase_sdk/extension/
resolver.rs

1use crate::{
2    component::AnyExtension,
3    types::{Error, FieldDefinitionDirective, FieldInputs, FieldOutput},
4    wit::SharedContext,
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    /// * `context` - The shared context containing runtime information
21    /// * `directive` - The directive associated with this field resolution
22    /// * `definition` - The field definition containing metadata
23    /// * `inputs` - The input values provided for this field
24    ///
25    /// # Returns
26    ///
27    /// Returns a `Result` containing either the resolved `FieldOutput` value or an `Error`
28    fn resolve_field(
29        &mut self,
30        context: SharedContext,
31        subgraph_name: &str,
32        directive: FieldDefinitionDirective<'_>,
33        inputs: FieldInputs,
34    ) -> Result<FieldOutput, Error>;
35
36    /// Resolves a subscription field by setting up a subscription handler.
37    ///
38    /// # Arguments
39    ///
40    /// * `context` - The shared context containing runtime information
41    /// * `directive` - The directive associated with this subscription field
42    /// * `definition` - The field definition containing metadata about the subscription
43    ///
44    /// # Returns
45    ///
46    /// Returns a `Result` containing either a boxed `Subscriber` implementation or an `Error`
47    fn resolve_subscription(
48        &mut self,
49        context: SharedContext,
50        subgraph_name: &str,
51        directive: FieldDefinitionDirective<'_>,
52    ) -> Result<Box<dyn Subscription>, Error>;
53}
54
55/// A trait for consuming field outputs from streams.
56///
57/// This trait provides an abstraction over different implementations
58/// of subscriptions to field output streams. Implementors should handle
59/// the details of their specific transport mechanism while providing a
60/// consistent interface for consumers.
61pub trait Subscription {
62    /// Retrieves the next field output from the subscription.
63    ///
64    /// Returns:
65    /// - `Ok(Some(FieldOutput))` if a field output was available
66    /// - `Ok(None)` if the subscription has ended normally
67    /// - `Err(Error)` if an error occurred while retrieving the next field output
68    fn next(&mut self) -> Result<Option<FieldOutput>, Error>;
69}
70
71#[doc(hidden)]
72pub fn register<T: Resolver>() {
73    pub(super) struct Proxy<T: Resolver>(T);
74
75    impl<T: Resolver> AnyExtension for Proxy<T> {
76        fn resolve_field(
77            &mut self,
78            context: SharedContext,
79            subgraph_name: &str,
80            directive: FieldDefinitionDirective<'_>,
81            inputs: FieldInputs,
82        ) -> Result<FieldOutput, Error> {
83            Resolver::resolve_field(&mut self.0, context, subgraph_name, directive, inputs)
84        }
85        fn resolve_subscription(
86            &mut self,
87            context: SharedContext,
88            subgraph_name: &str,
89            directive: FieldDefinitionDirective<'_>,
90        ) -> Result<Box<dyn Subscription>, Error> {
91            Resolver::resolve_subscription(&mut self.0, context, subgraph_name, directive)
92        }
93    }
94    crate::component::register_extension(Box::new(|schema_directives, config| {
95        <T as Extension>::new(schema_directives, config)
96            .map(|extension| Box::new(Proxy(extension)) as Box<dyn AnyExtension>)
97    }))
98}