diff --git a/src/GraphQL.Conventions/Adapters/Engine/ErrorTransformations/DefaultErrorTransformation.cs b/src/GraphQL.Conventions/Adapters/Engine/ErrorTransformations/DefaultErrorTransformation.cs new file mode 100644 index 00000000..da494765 --- /dev/null +++ b/src/GraphQL.Conventions/Adapters/Engine/ErrorTransformations/DefaultErrorTransformation.cs @@ -0,0 +1,22 @@ +using System.Linq; +using GraphQL.Conventions.Execution; + +namespace GraphQL.Conventions.Adapters.Engine.ErrorTransformations +{ + public class DefaultErrorTransformation : IErrorTransformation + { + public ExecutionErrors Transform(ExecutionErrors errors) + => errors.Aggregate(new ExecutionErrors(), (result, executionError) => + { + var exception = new FieldResolutionException(executionError); + var error = new ExecutionError(exception.Message, exception); + foreach (var location in executionError.Locations ?? Enumerable.Empty()) + { + error.AddLocation(location.Line, location.Column); + } + error.Path = executionError.Path; + result.Add(error); + return result; + }); + } +} diff --git a/src/GraphQL.Conventions/Adapters/Engine/ErrorTransformations/IErrorTransformation.cs b/src/GraphQL.Conventions/Adapters/Engine/ErrorTransformations/IErrorTransformation.cs new file mode 100644 index 00000000..652329e6 --- /dev/null +++ b/src/GraphQL.Conventions/Adapters/Engine/ErrorTransformations/IErrorTransformation.cs @@ -0,0 +1,7 @@ +namespace GraphQL.Conventions.Adapters.Engine.ErrorTransformations +{ + public interface IErrorTransformation + { + ExecutionErrors Transform(ExecutionErrors errors); + } +} diff --git a/src/GraphQL.Conventions/Adapters/Engine/GraphQLEngine.cs b/src/GraphQL.Conventions/Adapters/Engine/GraphQLEngine.cs index 42305b66..40388d56 100644 --- a/src/GraphQL.Conventions/Adapters/Engine/GraphQLEngine.cs +++ b/src/GraphQL.Conventions/Adapters/Engine/GraphQLEngine.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using GraphQL.Conventions.Adapters; +using GraphQL.Conventions.Adapters.Engine.ErrorTransformations; using GraphQL.Conventions.Adapters.Engine.Listeners.DataLoader; using GraphQL.Conventions.Builders; using GraphQL.Conventions.Execution; @@ -44,6 +45,8 @@ public class GraphQLEngine List _middleware = new List(); + IErrorTransformation _errorTransformation = new DefaultErrorTransformation(); + bool _includeFieldDescriptions; bool _includeFieldDeprecationReasons; @@ -171,6 +174,12 @@ public GraphQLEngine WithMiddleware() return WithMiddleware(typeof(T)); } + public GraphQLEngine WithCustomErrorTransformation(IErrorTransformation errorTransformation) + { + _errorTransformation = errorTransformation; + return this; + } + public GraphQLEngine PrintFieldDescriptions(bool include = true) { _includeFieldDescriptions = include; @@ -283,21 +292,9 @@ internal async Task Execute( var result = await _documentExecutor.ExecuteAsync(configuration).ConfigureAwait(false); - if (result.Errors != null) + if (result.Errors != null && _errorTransformation != null) { - var errors = new ExecutionErrors(); - foreach (var executionError in result.Errors) - { - var exception = new FieldResolutionException(executionError); - var error = new ExecutionError(exception.Message, exception); - foreach (var location in executionError.Locations ?? new ErrorLocation[0]) - { - error.AddLocation(location.Line, location.Column); - } - error.Path = executionError.Path; - errors.Add(error); - } - result.Errors = errors; + result.Errors = _errorTransformation.Transform(result.Errors); } return result; diff --git a/test/Tests/Adapters/Engine/CustomErrorTransformationTests.cs b/test/Tests/Adapters/Engine/CustomErrorTransformationTests.cs new file mode 100644 index 00000000..a93501aa --- /dev/null +++ b/test/Tests/Adapters/Engine/CustomErrorTransformationTests.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using GraphQL; +using GraphQL.Conventions; +using GraphQL.Conventions.Adapters.Engine.ErrorTransformations; +using GraphQL.Conventions.Execution; +using GraphQL.Conventions.Tests; +using GraphQL.Conventions.Tests.Templates; +using GraphQL.Conventions.Tests.Templates.Extensions; + +namespace Tests.Adapters.Engine +{ + public class CustomErrorTransformationTests : TestBase + { + [Test] + public async Task Will_Use_Default_Error_Transformation_When_Not_Provided() + { + var engine = GraphQLEngine.New(); + var result = await engine + .NewExecutor() + .WithQueryString("query { queryData }") + .Execute(); + + result.Errors.ShouldNotBeNull(); + result.Errors.Count.ShouldEqual(1); + var error = result.Errors.First(); + error.ShouldBeOfType(); + error.InnerException.ShouldBeOfType(); + error.InnerException.InnerException.ShouldBeOfType(); + } + + [Test] + public async Task Will_Use_Custom_Error_Transformation_When_Provided() + { + var engine = GraphQLEngine.New(); + var result = await engine + .WithCustomErrorTransformation(new CustomErrorTransformation()) + .NewExecutor() + .WithQueryString("query { queryData }") + .Execute(); + + result.Errors.ShouldNotBeNull(); + result.Errors.Count.ShouldEqual(1); + var error = result.Errors.First(); + error.ShouldBeOfType(); + error.InnerException.ShouldBeOfType(); + error.InnerException.InnerException.ShouldBeOfType(); + } + + class Query + { + public string QueryData() => throw new CustomException(); + } + + class CustomErrorTransformation : IErrorTransformation + { + public ExecutionErrors Transform(ExecutionErrors errors) + => errors; + } + + class CustomException : Exception { } + } +} diff --git a/test/Tests/Templates/Extensions/TestExtensions.cs b/test/Tests/Templates/Extensions/TestExtensions.cs index b360f9db..fafd6508 100644 --- a/test/Tests/Templates/Extensions/TestExtensions.cs +++ b/test/Tests/Templates/Extensions/TestExtensions.cs @@ -79,6 +79,11 @@ public static void ShouldContainWhenReformatted(this string str, string substrin str.ShouldContain(substring); } + public static void ShouldBeOfType(this object actual) + { + Assert.IsInstanceOfType(actual, typeof(T)); + } + public static void ShouldBeNamed(this GraphEntityInfo entity, string name) { entity.Name.ShouldEqual(name); diff --git a/test/Tests/Tests.csproj b/test/Tests/Tests.csproj index bd98bc3c..f72ef693 100755 --- a/test/Tests/Tests.csproj +++ b/test/Tests/Tests.csproj @@ -15,7 +15,6 @@ -