grafbase_sdk/
types.rs

1//! Type definitions of the input and output data structures of the SDK.
2
3pub use http::StatusCode;
4pub use minicbor_serde::error::DecodeError;
5pub use serde::Deserialize;
6use serde::Serialize;
7
8use crate::wit;
9
10/// The directive and its arguments which define the extension in the GraphQL SDK.
11pub struct Directive(crate::wit::Directive);
12
13impl Directive {
14    /// The name of the directive.
15    pub fn name(&self) -> &str {
16        &self.0.name
17    }
18
19    /// The name of the subgraph this directive is part of.
20    pub fn subgraph_name(&self) -> &str {
21        &self.0.subgraph_name
22    }
23
24    /// The directive arguments. The output is a Serde structure, that must map to
25    /// the arguments of the directive.
26    ///
27    /// Error is returned if the directive argument does not match the output structure.
28    pub fn arguments<'de, T>(&'de self) -> Result<T, DecodeError>
29    where
30        T: Deserialize<'de>,
31    {
32        minicbor_serde::from_slice(&self.0.arguments)
33    }
34}
35
36impl From<crate::wit::Directive> for Directive {
37    fn from(value: crate::wit::Directive) -> Self {
38        Self(value)
39    }
40}
41
42/// The input data structure of the field.
43pub struct FieldDefinition(crate::wit::FieldDefinition);
44
45impl FieldDefinition {
46    /// The name of the field.
47    pub fn name(&self) -> &str {
48        self.0.name.as_str()
49    }
50
51    /// The name of the field type.
52    pub fn type_name(&self) -> &str {
53        self.0.type_name.as_str()
54    }
55}
56
57impl From<crate::wit::FieldDefinition> for FieldDefinition {
58    fn from(value: crate::wit::FieldDefinition) -> Self {
59        Self(value)
60    }
61}
62
63/// Output responses from the field resolver.
64pub struct FieldOutput(crate::wit::FieldOutput);
65
66impl Default for FieldOutput {
67    fn default() -> Self {
68        Self::new()
69    }
70}
71
72impl FieldOutput {
73    /// Construct a new output response.
74    pub fn new() -> Self {
75        Self(crate::wit::FieldOutput { outputs: Vec::new() })
76    }
77
78    /// Constructs a new, empty output with at least the specified capacity.
79    ///
80    /// The output will be able to hold at least `capacity` elements without
81    /// reallocating.
82    pub fn with_capacity(capacity: usize) -> Self {
83        Self(crate::wit::FieldOutput {
84            outputs: Vec::with_capacity(capacity),
85        })
86    }
87
88    /// Push a new output data to the response.
89    pub fn push_value<T>(&mut self, output: T)
90    where
91        T: Serialize,
92    {
93        let output =
94            minicbor_serde::to_vec(output).expect("serialization error is Infallible, so it should never happen");
95
96        self.0.outputs.push(Ok(output));
97    }
98
99    /// Push a new error to the response.
100    pub fn push_error(&mut self, error: crate::wit::Error) {
101        self.0.outputs.push(Err(error))
102    }
103}
104
105impl From<FieldOutput> for crate::wit::FieldOutput {
106    fn from(value: FieldOutput) -> Self {
107        value.0
108    }
109}
110
111/// A container for field inputs.
112#[derive(Debug)]
113pub struct FieldInputs(Vec<Vec<u8>>);
114
115impl FieldInputs {
116    pub(crate) fn new(inputs: Vec<Vec<u8>>) -> Self {
117        Self(inputs)
118    }
119
120    /// Deserializes each byte slice in the `FieldInputs` to a collection of items.
121    pub fn deserialize<'de, T>(&'de self) -> Result<Vec<T>, Box<dyn std::error::Error>>
122    where
123        T: Deserialize<'de>,
124    {
125        self.0
126            .iter()
127            .map(|input| minicbor_serde::from_slice(input).map_err(|e| Box::new(e) as Box<dyn std::error::Error>))
128            .collect()
129    }
130}
131
132/// Configuration data for the extension, from the gateway toml config.
133pub struct Configuration(Vec<u8>);
134
135impl Configuration {
136    /// Creates a new `Configuration` from a CBOR byte vector.
137    pub(crate) fn new(config: Vec<u8>) -> Self {
138        Self(config)
139    }
140
141    /// Deserializes the configuration bytes into the requested type.
142    ///
143    /// # Errors
144    ///
145    /// Returns an error if deserialization fails.
146    pub fn deserialize<'de, T>(&'de self) -> Result<T, Box<dyn std::error::Error>>
147    where
148        T: Deserialize<'de>,
149    {
150        minicbor_serde::from_slice(&self.0).map_err(|e| Box::new(e) as Box<dyn std::error::Error>)
151    }
152}
153
154/// A cache implementation for storing data between requests.
155pub struct Cache;
156
157/// A response containing a status code and multiple errors.
158pub struct ErrorResponse(crate::wit::ErrorResponse);
159
160impl From<ErrorResponse> for crate::wit::ErrorResponse {
161    fn from(resp: ErrorResponse) -> Self {
162        resp.0
163    }
164}
165
166impl ErrorResponse {
167    /// Creates a new `ErrorResponse` with the given HTTP status code.
168    pub fn new(status_code: http::StatusCode) -> Self {
169        Self(crate::wit::ErrorResponse {
170            status_code: status_code.as_u16(),
171            errors: Vec::new(),
172        })
173    }
174
175    /// Add a new error to the response and return self
176    #[must_use]
177    pub fn with_error(mut self, error: crate::wit::Error) -> Self {
178        self.0.errors.push(error);
179        self
180    }
181
182    /// Adds a new error to the response.
183    pub fn push_error(&mut self, error: crate::wit::Error) {
184        self.0.errors.push(error);
185    }
186}
187
188/// A structure representing an authentication token claims.
189pub struct Token {
190    claims: Vec<u8>,
191}
192
193impl From<Token> for wit::Token {
194    fn from(token: Token) -> wit::Token {
195        wit::Token { raw: token.claims }
196    }
197}
198
199impl Token {
200    /// Creates a new `Token` with the given claims. The claims can be defined by the extension,
201    /// but to use the [`@requiredScopes`](https://grafbase.com/docs/reference/graphql-directives#requiresscopes)
202    /// directive, the claims must contain a `scopes` field with an array of strings.
203    pub fn new<T>(claims: T) -> Self
204    where
205        T: serde::Serialize,
206    {
207        Self {
208            claims: minicbor_serde::to_vec(&claims)
209                .expect("serialization error is Infallible, so it should never happen"),
210        }
211    }
212}