Skip to content

Commit dd2d83c

Browse files
committed
Moved all GraphQL exceptions to the Server project
1 parent 47bd7cf commit dd2d83c

File tree

12 files changed

+66
-45
lines changed

12 files changed

+66
-45
lines changed

src/FSharp.Data.GraphQL.Server.Relay/FSharp.Data.GraphQL.Server.Relay.fsproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
</ItemGroup>
2020

2121
<ItemGroup>
22-
<PackageReference Condition="$(IsNuget) != ''" Include="FSharp.Data.GraphQL.Shared" VersionOverride="$(Version)" />
23-
<ProjectReference Condition="$(IsNuget) == ''" Include="..\FSharp.Data.GraphQL.Shared\FSharp.Data.GraphQL.Shared.fsproj" />
22+
<PackageReference Condition="$(IsNuget) != ''" Include="FSharp.Data.GraphQL.Server" VersionOverride="$(Version)" />
23+
<ProjectReference Condition="$(IsNuget) == ''" Include="..\FSharp.Data.GraphQL.Server\FSharp.Data.GraphQL.Server.fsproj" />
2424
</ItemGroup>
2525

2626
</Project>
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// The MIT License (MIT)
22

3-
module FSharp.Data.GraphQL.ErrorMessagess
3+
module FSharp.Data.GraphQL.ErrorMessages
4+
5+
open System
46

57
let variableNotFound variableName = $"A variable '$%s{variableName}' was not provided"
8+
9+
let expectedEnumerableValue indetifier ``type`` = $"Expected to have enumerable value in field '%s{indetifier}' but got '%O{(``type``:Type)}'"

src/FSharp.Data.GraphQL.Server/Exceptions.fs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,37 @@ namespace FSharp.Data.GraphQL
55

66
open System
77
open System.Collections.Immutable
8+
open System.Collections.Generic
9+
open System.Runtime.InteropServices
10+
11+
[<AbstractClass>]
12+
type GraphQLException =
13+
inherit Exception
14+
15+
new () = { inherit Exception () }
16+
new (msg) = { inherit Exception (msg) }
17+
new (info : Runtime.Serialization.SerializationInfo, context : Runtime.Serialization.StreamingContext) = { inherit Exception (info, context) }
18+
19+
[<AbstractClass>]
20+
type GQLMessageExceptionBase (errorKind, msg, [<Optional>] extensions) =
21+
inherit GraphQLException (msg)
22+
interface IGQLError with
23+
member _.Message = msg
24+
interface IGQLErrorExtensions with
25+
member _.Extensions =
26+
match extensions with
27+
| null -> Dictionary<string, obj> 1
28+
| _ -> extensions
29+
|> GQLProblemDetails.SetErrorKind errorKind
30+
|> ValueSome
31+
32+
type GQLMessageException (msg) =
33+
inherit GQLMessageExceptionBase (Execution, msg)
834

935
type InvalidInputTypeException (msg, unmatchedOptionalFields) =
10-
inherit Exception(msg)
36+
inherit GQLMessageExceptionBase (InputCoercion, msg)
1137

1238
member _.UnmatchedOptionalFields : string ImmutableHashSet = unmatchedOptionalFields
1339

14-
type MalformedGQLQueryException(msg) =
15-
inherit GraphQLException(msg)
40+
type MalformedGQLQueryException (msg) =
41+
inherit GQLMessageExceptionBase (Validation, msg)

src/FSharp.Data.GraphQL.Server/Execution.fs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,12 @@ let private raiseErrors errs = AsyncVal.wrap <| Error errs
273273
/// to a list of <see href="GQLProblemDetails">GQLProblemDetails</see>.
274274
let private resolverError path ctx e = ctx.Schema.ParseError path e |> List.map (GQLProblemDetails.OfFieldExecutionError (path |> List.rev))
275275
// Helper functions for generating more specific <see href="GQLProblemDetails">GQLProblemDetails</see>.
276-
let private nullResolverError name path ctx = resolverError path ctx (GraphQLException <| sprintf "Non-Null field %s resolved as a null!" name)
277-
let private coercionError value tyName path ctx = resolverError path ctx (GraphQLException <| sprintf "Value '%O' could not be coerced to scalar %s" value tyName)
278-
let private interfaceImplError ifaceName tyName path ctx = resolverError path ctx (GraphQLException <| sprintf "GraphQL Interface '%s' is not implemented by the type '%s'" ifaceName tyName)
279-
let private unionImplError unionName tyName path ctx = resolverError path ctx (GraphQLException (sprintf "GraphQL Union '%s' is not implemented by the type '%s'" unionName tyName))
280-
let private deferredNullableError name tyName path ctx = resolverError path ctx (GraphQLException (sprintf "Deferred field %s of type '%s' must be nullable" name tyName))
281-
let private streamListError name tyName path ctx = resolverError path ctx (GraphQLException (sprintf "Streamed field %s of type '%s' must be list" name tyName))
276+
let private nullResolverError name path ctx = resolverError path ctx (GQLMessageException <| sprintf "Non-Null field %s resolved as a null!" name)
277+
let private coercionError value tyName path ctx = resolverError path ctx (GQLMessageException <| sprintf "Value '%O' could not be coerced to scalar %s" value tyName)
278+
let private interfaceImplError ifaceName tyName path ctx = resolverError path ctx (GQLMessageException <| sprintf "GraphQL Interface '%s' is not implemented by the type '%s'" ifaceName tyName)
279+
let private unionImplError unionName tyName path ctx = resolverError path ctx (GQLMessageException (sprintf "GraphQL Union '%s' is not implemented by the type '%s'" unionName tyName))
280+
let private deferredNullableError name tyName path ctx = resolverError path ctx (GQLMessageException (sprintf "Deferred field %s of type '%s' must be nullable" name tyName))
281+
let private streamListError name tyName path ctx = resolverError path ctx (GQLMessageException (sprintf "Streamed field %s of type '%s' must be list" name tyName))
282282

283283
let private resolved name v : AsyncVal<ResolverResult<KeyValuePair<string, obj>>> = AsyncVal.wrap <| Ok(KeyValuePair(name, box v), None, [])
284284

@@ -353,7 +353,7 @@ let rec private direct (returnDef : OutputDef) (ctx : ResolveFieldContext) (path
353353
|> Array.mapi resolveItem
354354
|> collectFields Parallel
355355
|> AsyncVal.map(ResolverResult.mapValue(fun items -> KeyValuePair(name, items |> Array.map(fun d -> d.Value) |> box)))
356-
| _ -> raise <| GraphQLException (sprintf "Expected to have enumerable value in field '%s' but got '%O'" ctx.ExecutionInfo.Identifier (value.GetType()))
356+
| _ -> raise <| GQLMessageException (ErrorMessages.expectedEnumerableValue ctx.ExecutionInfo.Identifier (value.GetType()))
357357

358358
| Nullable (Output innerDef) ->
359359
let innerCtx = { ctx with ExecutionInfo = { ctx.ExecutionInfo with IsNullable = true; ReturnDef = innerDef } }
@@ -445,7 +445,7 @@ and private streamed (options : BufferedStreamOptions) (innerDef : OutputDef) (c
445445
|> Observable.ofAsyncValSeq
446446
|> buffer
447447
AsyncVal.wrap <| Ok(KeyValuePair(info.Identifier, box [||]), Some stream, [])
448-
| _ -> raise <| GraphQLException (sprintf "Expected to have enumerable value in field '%s' but got '%O'" ctx.ExecutionInfo.Identifier (value.GetType()))
448+
| _ -> raise <| GQLMessageException (ErrorMessages.expectedEnumerableValue ctx.ExecutionInfo.Identifier (value.GetType()))
449449

450450
and private live (ctx : ResolveFieldContext) (path : FieldPath) (parent : obj) (value : obj) =
451451
let info = ctx.ExecutionInfo
@@ -549,7 +549,7 @@ let internal compileSubscriptionField (subfield: SubscriptionFieldDef) =
549549
match subfield.Resolve with
550550
| Resolve.BoxedFilterExpr(_, _, _, filter) -> fun ctx a b -> filter ctx a b |> AsyncVal.wrap |> AsyncVal.toAsync
551551
| Resolve.BoxedAsyncFilterExpr(_, _, _, filter) -> filter
552-
| _ -> raise <| GraphQLException ("Invalid filter expression for subscription field!")
552+
| _ -> raise <| GQLMessageException ("Invalid filter expression for subscription field!")
553553

554554
let internal compileField (fieldDef: FieldDef) : ExecuteField =
555555
match fieldDef.Resolve with

src/FSharp.Data.GraphQL.Server/Executor.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ type Executor<'Root>(schema: ISchema<'Root>, middlewares : IExecutorMiddleware s
9696
runMiddlewares (fun x -> x.PostCompileSchema) (upcast schema) ignore
9797
match Validation.Types.validateTypeMap schema.TypeMap with
9898
| Success -> ()
99-
| ValidationError errors -> raise (GraphQLException (System.String.Join("\n", errors)))
99+
| ValidationError errors -> raise (GQLMessageException (System.String.Join("\n", errors)))
100100

101101
let eval (executionPlan: ExecutionPlan, data: 'Root option, variables: ImmutableDictionary<string, JsonElement>): Async<GQLExecutionResult> =
102102
let documentId = executionPlan.DocumentId
@@ -124,7 +124,7 @@ type Executor<'Root>(schema: ISchema<'Root>, middlewares : IExecutorMiddleware s
124124
let! res = runMiddlewares (fun x -> x.ExecuteOperationAsync) executionCtx executeOperation |> AsyncVal.toAsync
125125
return prepareOutput res
126126
with
127-
| :? GraphQLException as ex -> return prepareOutput(GQLExecutionResult.Error (documentId, ex, executionPlan.Metadata))
127+
| :? GQLMessageException as ex -> return prepareOutput(GQLExecutionResult.Error (documentId, ex, executionPlan.Metadata))
128128
| ex -> return prepareOutput (GQLExecutionResult.Error(documentId, ex.ToString(), executionPlan.Metadata)) // TODO: Handle better
129129
}
130130

src/FSharp.Data.GraphQL.Server/FSharp.Data.GraphQL.Server.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<Compile Include="ErrorMessages.fs" />
3838
<Compile Include="ErrorsProcessing.fs" />
3939
<Compile Include="Exceptions.fs" />
40+
<Compile Include="TypeSystem.fs" />
4041
<Compile Include="Values.fs" />
4142
<Compile Include="Planning.fs" />
4243
<Compile Include="ObservableExtensions.fs" />

src/FSharp.Data.GraphQL.Server/Schema.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ type SchemaConfig =
132132
ParseError =
133133
fun path ex ->
134134
match ex with
135-
| :? GraphQLException as ex -> [ex]
135+
| :? GQLMessageException as ex -> [ex]
136136
| ex -> [{ new IGQLError with member _.Message = ex.Message }]
137137
SubscriptionProvider = SchemaConfig.DefaultSubscriptionProvider()
138138
LiveFieldSubscriptionProvider = SchemaConfig.DefaultLiveFieldSubscriptionProvider()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// The MIT License (MIT)
2+
// Copyright (c) 2016 Bazinga Technologies Inc
3+
[<AutoOpen>]
4+
module FSharp.Data.GraphQL.Types.ResolveFieldContextExtensions
5+
6+
open FSharp.Data.GraphQL
7+
open FSharp.Data.GraphQL.Extensions
8+
9+
type ResolveFieldContext with
10+
11+
/// Returns an argument by provided name. If argument was not found a GraphQL exception will be thrown.
12+
/// <exception cref="GraphQLException">When argument with the name not found in the Args.</exception>
13+
member x.Arg(name : string) : 't =
14+
match Map.tryFind name x.Args with
15+
| Some found -> downcast found
16+
| None -> raise (GQLMessageException $"Argument '%s{name}' was not provided within context of a field '%s{x.ExecutionInfo.Identifier}'. Check if it was supplied within GraphQL query.")
17+

src/FSharp.Data.GraphQL.Shared/Exceptions.fs

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/FSharp.Data.GraphQL.Shared/FSharp.Data.GraphQL.Shared.fsproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
<Compile Include="Helpers\Reflection.fs" />
5050
<Compile Include="Helpers\MemoryCache.fs" />
5151
<Compile Include="Errors.fs" />
52-
<Compile Include="Exceptions.fs" />
5352
<Compile Include="ValidationTypes.fs" />
5453
<Compile Include="AsyncVal.fs" />
5554
<Compile Include="Ast.fs" />

0 commit comments

Comments
 (0)