grafbase_sdk/
types.rs

1//! Type definitions of the input and output data structures of the SDK.
2
3pub use http::StatusCode;
4use 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 = crate::cbor::to_vec(output).expect("serialization error is Infallible, so it should never happen");
94
95        self.0.outputs.push(Ok(output));
96    }
97
98    /// Push a new error to the response.
99    pub fn push_error(&mut self, error: crate::wit::Error) {
100        self.0.outputs.push(Err(error))
101    }
102}
103
104impl From<FieldOutput> for crate::wit::FieldOutput {
105    fn from(value: FieldOutput) -> Self {
106        value.0
107    }
108}
109
110/// A container for field inputs.
111#[derive(Debug)]
112pub struct FieldInputs(Vec<Vec<u8>>);
113
114impl FieldInputs {
115    pub(crate) fn new(inputs: Vec<Vec<u8>>) -> Self {
116        Self(inputs)
117    }
118
119    /// Deserializes each byte slice in the `FieldInputs` to a collection of items.
120    pub fn deserialize<'de, T>(&'de self) -> Result<Vec<T>, Box<dyn std::error::Error>>
121    where
122        T: Deserialize<'de>,
123    {
124        self.0
125            .iter()
126            .map(|input| minicbor_serde::from_slice(input).map_err(|e| Box::new(e) as Box<dyn std::error::Error>))
127            .collect()
128    }
129}
130
131/// Configuration data for the extension, from the gateway toml config.
132pub struct Configuration(Vec<u8>);
133
134impl Configuration {
135    /// Creates a new `Configuration` from a CBOR byte vector.
136    pub(crate) fn new(config: Vec<u8>) -> Self {
137        Self(config)
138    }
139
140    /// Deserializes the configuration bytes into the requested type.
141    ///
142    /// # Errors
143    ///
144    /// Returns an error if deserialization fails.
145    pub fn deserialize<'de, T>(&'de self) -> Result<T, Box<dyn std::error::Error>>
146    where
147        T: Deserialize<'de>,
148    {
149        minicbor_serde::from_slice(&self.0).map_err(|e| Box::new(e) as Box<dyn std::error::Error>)
150    }
151}
152
153/// A cache implementation for storing data between requests.
154pub struct Cache;
155
156/// A response containing a status code and multiple errors.
157pub struct ErrorResponse(crate::wit::ErrorResponse);
158
159impl From<ErrorResponse> for crate::wit::ErrorResponse {
160    fn from(resp: ErrorResponse) -> Self {
161        resp.0
162    }
163}
164
165impl ErrorResponse {
166    /// Creates a new `ErrorResponse` with the given HTTP status code.
167    pub fn new(status_code: http::StatusCode) -> Self {
168        Self(crate::wit::ErrorResponse {
169            status_code: status_code.as_u16(),
170            errors: Vec::new(),
171        })
172    }
173
174    /// Add a new error to the response and return self
175    #[must_use]
176    pub fn with_error(mut self, error: crate::wit::Error) -> Self {
177        self.0.errors.push(error);
178        self
179    }
180
181    /// Adds a new error to the response.
182    pub fn push_error(&mut self, error: crate::wit::Error) {
183        self.0.errors.push(error);
184    }
185}
186
187/// A structure representing an authentication token claims.
188pub struct Token {
189    claims: Vec<u8>,
190}
191
192impl From<Token> for wit::Token {
193    fn from(token: Token) -> wit::Token {
194        wit::Token { raw: token.claims }
195    }
196}
197
198impl Token {
199    /// Creates a new `Token` with the given claims. The claims can be defined by the extension,
200    /// but to use the [`@requiredScopes`](https://grafbase.com/docs/reference/graphql-directives#requiresscopes)
201    /// directive, the claims must contain a `scopes` field with an array of strings.
202    pub fn new<T>(claims: T) -> Self
203    where
204        T: serde::Serialize,
205    {
206        Self {
207            claims: crate::cbor::to_vec(&claims).expect("serialization error is Infallible, so it should never happen"),
208        }
209    }
210}