dynamic_graphql/
errors.rs1use std::fmt::Display;
2use std::marker::PhantomData;
3
4use async_graphql::ErrorExtensionValues;
5use async_graphql::Pos;
6use async_graphql::ServerError;
7use async_graphql::dynamic::TypeRef;
8
9use crate::Value;
10use crate::types::GetInputTypeRef;
11
12fn get_type_name<T: GetInputTypeRef>() -> String {
13 let type_ref: TypeRef = <Option<T>>::get_input_type_ref().into();
14 type_ref.to_string()
15}
16
17#[derive(Debug)]
18pub struct InputValueError<T> {
19 message: String,
20 extensions: Option<ErrorExtensionValues>,
21 phantom: PhantomData<T>,
22}
23
24impl<T> InputValueError<T> {
25 pub fn new(message: String) -> Self {
26 Self {
27 message,
28 extensions: None,
29 phantom: PhantomData,
30 }
31 }
32 #[must_use]
34 pub fn expected_type(actual: Value) -> Self
35 where
36 T: GetInputTypeRef,
37 {
38 Self::new(format!(
39 r#"Expected input type "{}", found {}."#,
40 get_type_name::<T>(),
41 actual
42 ))
43 }
44 #[must_use]
49 pub fn custom(msg: impl Display) -> Self
50 where
51 T: GetInputTypeRef,
52 {
53 Self::new(format!(
54 r#"Failed to parse "{}": {}"#,
55 get_type_name::<T>(),
56 msg
57 ))
58 }
59
60 pub fn propagate<U: GetInputTypeRef>(self) -> InputValueError<U>
62 where
63 T: GetInputTypeRef,
64 {
65 if get_type_name::<T>() != get_type_name::<U>() {
66 InputValueError::new(format!(
67 r#"{} (occurred while parsing "{}")"#,
68 self.message,
69 get_type_name::<U>()
70 ))
71 } else {
72 InputValueError::new(self.message)
73 }
74 }
75 pub fn with_extension(mut self, name: impl AsRef<str>, value: impl Into<Value>) -> Self {
76 self.extensions
77 .get_or_insert_with(ErrorExtensionValues::default)
78 .set(name, value);
79 self
80 }
81
82 pub fn into_server_error(self, pos: Pos) -> ServerError {
84 let mut err = ServerError::new(self.message, Some(pos));
85 err.extensions = self.extensions;
86 err
87 }
88
89 pub fn into_arg_error(self, name: &str) -> crate::Error {
90 let mut error = crate::Error::new(format!(
91 "Invalid value for argument \"{}\": {}",
92 name, self.message
93 ));
94 error.extensions = self.extensions;
95 error
96 }
97 pub fn into_field_error(self, name: &str) -> crate::Error {
98 let mut error = crate::Error::new(format!(
99 "Invalid value for field \"{}\": {}",
100 name, self.message
101 ));
102 error.extensions = self.extensions;
103 error
104 }
105}
106
107impl<T: GetInputTypeRef> From<async_graphql::Error> for InputValueError<T> {
108 fn from(value: async_graphql::Error) -> Self {
109 let mut err = Self::custom(value.message);
110 err.extensions = value.extensions;
111 err
112 }
113}
114
115impl<T> From<InputValueError<T>> for async_graphql::Error {
116 fn from(value: InputValueError<T>) -> Self {
117 Self {
118 message: value.message,
119 source: None,
120 extensions: value.extensions,
121 }
122 }
123}
124
125pub type InputValueResult<T> = Result<T, InputValueError<T>>;