grafbase_sdk/extension/resolver.rs
1use crate::{
2 component::AnyExtension,
3 types::{Directive, FieldDefinition, FieldInputs, FieldOutput},
4 wit::{Error, 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 directive: Directive,
32 definition: FieldDefinition,
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 directive: Directive,
51 definition: FieldDefinition,
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 directive: Directive,
80 definition: FieldDefinition,
81 inputs: FieldInputs,
82 ) -> Result<FieldOutput, Error> {
83 Resolver::resolve_field(&mut self.0, context, directive, definition, inputs)
84 }
85 fn resolve_subscription(
86 &mut self,
87 context: SharedContext,
88 directive: Directive,
89 definition: FieldDefinition,
90 ) -> Result<Box<dyn Subscription>, Error> {
91 Resolver::resolve_subscription(&mut self.0, context, directive, definition)
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}