diff --git a/derive/src/complex_object.rs b/derive/src/complex_object.rs index dd8859b1..f473a7c9 100644 --- a/derive/src/complex_object.rs +++ b/derive/src/complex_object.rs @@ -309,7 +309,7 @@ pub fn generate( let resolve_obj = quote! { { let res = self.#field_ident(ctx, #(#use_params),*).await; - res.map_err(|err| err.into_server_error().at(ctx.item.pos))? + res.map_err(|err| ::std::convert::Into::<#crate_name::Error>::into(err).into_server_error().at(ctx.item.pos))? } }; diff --git a/derive/src/interface.rs b/derive/src/interface.rs index 04023cde..def538a1 100644 --- a/derive/src/interface.rs +++ b/derive/src/interface.rs @@ -237,7 +237,9 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult obj.#method_name(#(#use_params),*).await.map(::std::convert::Into::into) + #ident::#enum_name(obj) => obj.#method_name(#(#use_params),*) + .await.map_err(|err| ::std::convert::Into::<#crate_name::Error>::into(err)) + .map(::std::convert::Into::into) }); } @@ -287,7 +289,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult::into(err).into_server_error().at(ctx.item.pos))? }; resolvers.push(quote! { diff --git a/derive/src/object.rs b/derive/src/object.rs index ade3eaa4..9fe25fe8 100644 --- a/derive/src/object.rs +++ b/derive/src/object.rs @@ -209,7 +209,7 @@ pub fn generate( syn::parse2::(quote! { -> #crate_name::Result<#inner_ty> }) .expect("invalid result type"); } - let do_find = quote! { self.#field_ident(ctx, #(#use_keys),*).await.map_err(|err| err.into_server_error().at(ctx.item.pos))? }; + let do_find = quote! { self.#field_ident(ctx, #(#use_keys),*).await.map_err(|err| ::std::convert::Into::<#crate_name::Error>::into(err).into_server_error().at(ctx.item.pos))? }; find_entities.push(( args.len(), @@ -513,7 +513,7 @@ pub fn generate( let resolve_obj = quote! { { let res = self.#field_ident(ctx, #(#use_params),*).await; - res.map_err(|err| err.into_server_error().at(ctx.item.pos))? + res.map_err(|err| ::std::convert::Into::<#crate_name::Error>::into(err).into_server_error().at(ctx.item.pos))? } }; diff --git a/derive/src/subscription.rs b/derive/src/subscription.rs index 9c51c594..f5e3cc16 100644 --- a/derive/src/subscription.rs +++ b/derive/src/subscription.rs @@ -318,7 +318,7 @@ pub fn generate( self.#ident(ctx, #(#use_params),*) .await .map_err(|err| { - err.into_server_error() + ::std::convert::Into::<#crate_name::Error>::into(err).into_server_error() .at(ctx.item.pos) .path(#crate_name::PathSegment::Field(::std::borrow::ToOwned::to_owned(&*field_name))) })? diff --git a/src/base.rs b/src/base.rs index 64a6e791..c3d3b938 100644 --- a/src/base.rs +++ b/src/base.rs @@ -6,8 +6,8 @@ use async_graphql_value::ConstValue; use crate::parser::types::Field; use crate::registry::{self, Registry}; use crate::{ - ContainerType, Context, ContextSelectionSet, InputValueError, InputValueResult, Positioned, - Result, ServerResult, Value, + ContainerType, Context, ContextSelectionSet, Error, InputValueError, InputValueResult, + Positioned, Result, ServerResult, Value, }; #[doc(hidden)] @@ -86,7 +86,7 @@ impl OutputType for &T { } } -impl Type for Result { +impl + Send + Sync + Clone> Type for Result { fn type_name() -> Cow<'static, str> { T::type_name() } @@ -101,7 +101,7 @@ impl Type for Result { } #[async_trait::async_trait] -impl OutputType for Result { +impl + Send + Sync + Clone> OutputType for Result { async fn resolve( &self, ctx: &ContextSelectionSet<'_>, @@ -109,7 +109,7 @@ impl OutputType for Result { ) -> ServerResult { match self { Ok(value) => Ok(value.resolve(ctx, field).await?), - Err(err) => Err(err.clone().into_server_error().at(field.pos)), + Err(err) => Err(err.clone().into().into_server_error().at(field.pos)), } } } diff --git a/tests/result.rs b/tests/result.rs index deec300e..8fcbe04b 100644 --- a/tests/result.rs +++ b/tests/result.rs @@ -1,4 +1,5 @@ use async_graphql::*; +use futures_util::stream::Stream; #[tokio::test] pub async fn test_fieldresult() { @@ -62,3 +63,56 @@ pub async fn test_fieldresult() { }] ); } + +#[tokio::test] +pub async fn test_custom_error() { + #[derive(Clone)] + struct MyError; + + impl From for Error { + fn from(_: MyError) -> Self { + Error::new("custom error") + } + } + + #[derive(SimpleObject)] + #[graphql(complex)] + struct MyObj { + value1: i32, + } + + #[ComplexObject] + impl MyObj { + async fn value2(&self) -> Result { + Err(MyError) + } + } + + #[derive(Interface)] + #[graphql(field(name = "value2", type = "i32"))] + enum MyInterface { + MyObj(MyObj), + } + + struct Query; + + #[Object] + impl Query { + async fn value(&self) -> Result { + Err(MyError) + } + } + + struct Subscription; + + #[Subscription] + impl Subscription { + async fn value1(&self) -> Result, MyError> { + Err::>, _>(MyError) + } + + async fn value2(&self) -> impl Stream> { + futures_util::stream::once(async move { Err(MyError) }) + } + } +}