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 /// Returns a key for a subscription field.
56 ///
57 /// This method is used to identify unique subscription channels or connections
58 /// when managing multiple active subscriptions. The returned key can be
59 /// used to track, manage, or deduplicate subscriptions.
60 ///
61 /// # Arguments
62 ///
63 /// * `headers` - The subgraph headers associated with this subscription
64 /// * `subgraph_name` - The name of the subgraph associated with this subscription
65 /// * `directive` - The directive associated with this subscription field
66 ///
67 /// # Returns
68 ///
69 /// Returns an `Option<Vec<u8>>` containing either a unique key for this
70 /// subscription or `None` if no deduplication is desired.
71 #[allow(unused)]
72 fn subscription_key(
73 &mut self,
74 headers: &Headers,
75 subgraph_name: &str,
76 directive: FieldDefinitionDirective<'_>,
77 ) -> Option<Vec<u8>> {
78 None
79 }
80}
81
82/// A trait for consuming field outputs from streams.
83///
84/// This trait provides an abstraction over different implementations
85/// of subscriptions to field output streams. Implementors should handle
86/// the details of their specific transport mechanism while providing a
87/// consistent interface for consumers.
88pub trait Subscription {
89 /// Retrieves the next field output from the subscription.
90 ///
91 /// Returns:
92 /// - `Ok(Some(FieldOutput))` if a field output was available
93 /// - `Ok(None)` if the subscription has ended normally
94 /// - `Err(Error)` if an error occurred while retrieving the next field output
95 fn next(&mut self) -> Result<Option<FieldOutput>, Error>;
96}
97
98#[doc(hidden)]
99pub fn register<T: Resolver>() {
100 pub(super) struct Proxy<T: Resolver>(T);
101
102 impl<T: Resolver> AnyExtension for Proxy<T> {
103 fn resolve_field(
104 &mut self,
105 headers: Headers,
106 subgraph_name: &str,
107 directive: FieldDefinitionDirective<'_>,
108 inputs: FieldInputs,
109 ) -> Result<FieldOutput, Error> {
110 Resolver::resolve_field(&mut self.0, headers, subgraph_name, directive, inputs)
111 }
112 fn resolve_subscription(
113 &mut self,
114 headers: Headers,
115 subgraph_name: &str,
116 directive: FieldDefinitionDirective<'_>,
117 ) -> Result<Box<dyn Subscription>, Error> {
118 Resolver::resolve_subscription(&mut self.0, headers, subgraph_name, directive)
119 }
120
121 fn subscription_key(
122 &mut self,
123 headers: &Headers,
124 subgraph_name: &str,
125 directive: FieldDefinitionDirective<'_>,
126 ) -> Result<Option<Vec<u8>>, Error> {
127 Ok(Resolver::subscription_key(
128 &mut self.0,
129 headers,
130 subgraph_name,
131 directive,
132 ))
133 }
134 }
135
136 crate::component::register_extension(Box::new(|schema_directives, config| {
137 <T as Extension>::new(schema_directives, config)
138 .map(|extension| Box::new(Proxy(extension)) as Box<dyn AnyExtension>)
139 }))
140}