Skip to content

Commit 7a513a5

Browse files
Andrii Chebukinxperiandri
authored andcommitted
WIP implementing input object path within errors
1 parent 175a650 commit 7a513a5

File tree

12 files changed

+362
-181
lines changed

12 files changed

+362
-181
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// The MIT License (MIT)
2+
3+
module FSharp.Data.GraphQL.ErrorMessagess
4+
5+
let variableNotFound variableName = $"Variable '%s{variableName}' not provided"
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
// The MIT License (MIT)
2+
namespace FSharp.Data.GraphQL
3+
4+
open System
5+
open System.Collections.Generic
6+
open System.Collections.Immutable
7+
open System.Collections.ObjectModel
8+
open FsToolkit.ErrorHandling
9+
open FSharp.Data.GraphQL.Types
10+
11+
type InputRoot =
12+
| Variable of VarDef: VarDef
13+
| Argument of ArgDef: InputFieldDef
14+
15+
type ErrorKind =
16+
| InputCoercion
17+
| InputObjectValidation
18+
| Execution
19+
20+
type internal CoercionError =
21+
{
22+
InnerError : IGQLError
23+
ErrorKind : ErrorKind
24+
ObjectType : string voption
25+
FieldType : string voption
26+
Path : FieldPath
27+
}
28+
interface IGQLError with
29+
30+
member this.Message = this.InnerError.Message
31+
32+
interface IGQLErrorExtensions with
33+
34+
member this.Extensions =
35+
36+
[
37+
yield KeyValuePair("kind", this.ErrorKind |> box)
38+
if this.ObjectType.IsSome then yield KeyValuePair("objectType", this.ObjectType.Value |> box)
39+
if this.FieldType.IsSome then yield KeyValuePair("fieldType", this.FieldType.Value |> box)
40+
41+
match this.Path with
42+
| [] -> ()
43+
| path -> yield KeyValuePair("path", path |> Seq.rev |> box)
44+
45+
match this.InnerError with
46+
| :? IGQLErrorExtensions as ext ->
47+
match ext.Extensions with
48+
| ValueSome extensions -> yield! extensions
49+
| ValueNone -> ()
50+
| _ -> ()
51+
]
52+
|> Dictionary<_,_>
53+
|> ReadOnlyDictionary<_,_>
54+
:> IReadOnlyDictionary<string, obj>
55+
|> ValueSome
56+
57+
[<Struct>]
58+
type internal ObjectFieldErrorDetails = {
59+
ObjectDef : InputObjectDef
60+
FieldDef : InputFieldDef voption
61+
}
62+
63+
type internal CoerceVariableError =
64+
{
65+
Message : string
66+
ErrorKind : ErrorKind
67+
Variable : VarDef
68+
Path : FieldPath
69+
FieldErrorDetails : ObjectFieldErrorDetails voption
70+
}
71+
interface IGQLError with
72+
73+
member this.Message = this.Message
74+
75+
interface IGQLErrorExtensions with
76+
77+
member this.Extensions =
78+
79+
[
80+
yield KeyValuePair("kind", this.ErrorKind |> box)
81+
yield KeyValuePair("variableName", this.Variable.Name |> box)
82+
yield KeyValuePair("variableType", (this.Variable.TypeDef :?> NamedDef).Name |> box)
83+
match this.Path with
84+
| [] -> ()
85+
| path -> yield KeyValuePair("path", path |> Seq.rev |> box)
86+
87+
match this.FieldErrorDetails with
88+
| ValueSome details ->
89+
yield KeyValuePair("objectType", details.ObjectDef.Name |> box)
90+
match details.FieldDef with
91+
| ValueSome fieldDef ->
92+
yield KeyValuePair("fieldType", (fieldDef.TypeDef :?> NamedDef).Name|> box)
93+
| ValueNone -> ()
94+
| ValueNone -> ()
95+
]
96+
|> Dictionary<_,_>
97+
|> ReadOnlyDictionary<_,_>
98+
:> IReadOnlyDictionary<string, obj>
99+
|> ValueSome
100+
101+
type internal CoerceVariableErrorWrapper =
102+
{
103+
InnerError : IGQLError
104+
ErrorKind : ErrorKind
105+
Variable: VarDef
106+
Path : FieldPath
107+
FieldErrorDetails : ObjectFieldErrorDetails voption
108+
}
109+
interface IGQLError with
110+
111+
member this.Message = this.InnerError.Message
112+
113+
interface IGQLErrorExtensions with
114+
115+
member this.Extensions =
116+
117+
[
118+
yield KeyValuePair("kind", this.ErrorKind |> box)
119+
yield KeyValuePair("variableName", this.Variable.Name |> box)
120+
yield KeyValuePair("variableType", (this.Variable.TypeDef :?> NamedDef).Name |> box)
121+
match this.Path with
122+
| [] -> ()
123+
| path -> yield KeyValuePair("path", path |> Seq.rev |> box)
124+
125+
match this.FieldErrorDetails with
126+
| ValueSome details ->
127+
yield KeyValuePair("objectType", details.ObjectDef.Name |> box)
128+
match details.FieldDef with
129+
| ValueSome fieldDef ->
130+
yield KeyValuePair("fieldType", (fieldDef.TypeDef :?> NamedDef).Name|> box)
131+
| ValueNone -> ()
132+
| ValueNone -> ()
133+
134+
match this.InnerError with
135+
| :? IGQLErrorExtensions as ext ->
136+
match ext.Extensions with
137+
| ValueSome extensions -> yield! extensions
138+
| ValueNone -> ()
139+
| _ -> ()
140+
]
141+
|> Dictionary<_,_>
142+
|> ReadOnlyDictionary<_,_>
143+
:> IReadOnlyDictionary<string, obj>
144+
|> ValueSome
145+
146+
type internal CoerceArgumentError =
147+
{
148+
InnerError : IGQLError
149+
ArgumentName : string
150+
TypeName : string
151+
Path : FieldPath
152+
}
153+
interface IGQLError with
154+
155+
member this.Message = this.InnerError.Message
156+
157+
interface IGQLErrorExtensions with
158+
159+
member this.Extensions =
160+
161+
[
162+
yield KeyValuePair("argumentName", this.ArgumentName |> box)
163+
yield KeyValuePair("typeName", this.TypeName |> box)
164+
165+
match this.Path with
166+
| [] -> ()
167+
| path -> yield KeyValuePair("path", path |> Seq.rev |> box)
168+
169+
match this.InnerError with
170+
| :? IGQLErrorExtensions as ext ->
171+
match ext.Extensions with
172+
| ValueSome extensions -> yield! extensions
173+
| ValueNone -> ()
174+
| _ -> ()
175+
]
176+
|> Dictionary<_,_>
177+
|> ReadOnlyDictionary<_,_>
178+
:> IReadOnlyDictionary<string, obj>
179+
|> ValueSome
180+

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

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

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

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -642,9 +642,8 @@ let private executeSubscription (resultSet: (string * ExecutionInfo) []) (ctx: E
642642
let private compileInputObject (indef: InputObjectDef) =
643643
indef.Fields
644644
|> Array.iter(fun inputField ->
645-
// TODO: Implement compilaiton cache to reuse for the same type
646-
let errMsg = $"Input object '%s{indef.Name}': in field '%s{inputField.Name}': "
647-
inputField.ExecuteInput <- compileByType errMsg inputField.TypeDef
645+
// TODO: Implement compilation cache to reuse for the same type
646+
inputField.ExecuteInput <- compileByType [inputField.Name |> box] inputField.TypeDef
648647
match inputField.TypeDef with
649648
| InputObject inputObjDef -> inputObjDef.ExecuteInput <- inputField.ExecuteInput
650649
| _ -> ()
@@ -660,8 +659,9 @@ let private compileObject (objdef: ObjectDef) (executeFields: FieldDef -> unit)
660659
executeFields fieldDef
661660
fieldDef.Args
662661
|> Array.iter (fun arg ->
663-
let errMsg = $"Object '%s{objdef.Name}': field '%s{fieldDef.Name}': argument '%s{arg.Name}': "
664-
arg.ExecuteInput <- compileByType errMsg arg.TypeDef
662+
//let errMsg = $"Object '%s{objdef.Name}': field '%s{fieldDef.Name}': argument '%s{arg.Name}': "
663+
// TODO: Pass arg name
664+
arg.ExecuteInput <- compileByType [fieldDef.Name |> box] arg.TypeDef
665665
match arg.TypeDef with
666666
| InputObject inputObjDef -> inputObjDef.ExecuteInput <- arg.ExecuteInput
667667
| _ -> ()
@@ -688,22 +688,28 @@ let internal coerceVariables (variables: VarDef list) (vars: ImmutableDictionary
688688
let variables, inlineValues, nulls =
689689
variables
690690
|> List.fold
691-
(fun (valiables, inlineValues, missing) vardef ->
692-
match vars.TryGetValue vardef.Name with
691+
(fun (valiables, inlineValues, missing) varDef ->
692+
match vars.TryGetValue varDef.Name with
693693
| false, _ ->
694-
match vardef.DefaultValue with
694+
match varDef.DefaultValue with
695695
| Some defaultValue ->
696-
let item = struct(vardef, defaultValue)
696+
let item = struct(varDef, defaultValue)
697697
(valiables, item::inlineValues, missing)
698698
| None ->
699699
let item =
700-
match vardef.TypeDef with
701-
| Nullable _ -> Ok <| KeyValuePair(vardef.Name, null)
702-
| Named typeDef -> Error [ { new IGQLError with member _.Message = $"Variable '$%s{vardef.Name}' of required type '%s{typeDef.Name}!' was not provided." } ]
703-
| _ -> System.Diagnostics.Debug.Fail $"{vardef.TypeDef.GetType().Name} is not Named"; failwith "Impossible case"
700+
match varDef.TypeDef with
701+
| Nullable _ -> Ok <| KeyValuePair(varDef.Name, null)
702+
| Named typeDef -> Error [ {
703+
Message = $"Variable '$%s{varDef.Name}' of type '%s{typeDef.Name}!' is not nullable but neither value was provided, nor a default value was specified."
704+
ErrorKind = InputCoercion
705+
Variable = varDef
706+
Path = []
707+
FieldErrorDetails = ValueNone
708+
} :> IGQLError ]
709+
| _ -> System.Diagnostics.Debug.Fail $"{varDef.TypeDef.GetType().Name} is not Named"; failwith "Impossible case"
704710
(valiables, inlineValues, item::missing)
705711
| true, jsonElement ->
706-
let item = struct(vardef, jsonElement)
712+
let item = struct(varDef, jsonElement)
707713
(item::valiables, inlineValues, missing)
708714
)
709715
([], [], [])
@@ -713,7 +719,7 @@ let internal coerceVariables (variables: VarDef list) (vars: ImmutableDictionary
713719
variables
714720
|> List.fold (
715721
fun (acc : Result<ImmutableDictionary<string, obj>.Builder, IGQLError list>) struct(vardef, jsonElement) -> validation {
716-
let! value = coerceVariableValue false vardef.TypeDef vardef jsonElement $"Variable '$%s{vardef.Name}': "
722+
let! value = coerceVariableValue false [] ValueNone vardef.TypeDef vardef jsonElement
717723
and! acc = acc
718724
acc.Add(vardef.Name, value)
719725
return acc
@@ -728,7 +734,7 @@ let internal coerceVariables (variables: VarDef list) (vars: ImmutableDictionary
728734
inlineValues
729735
|> List.fold (
730736
fun (acc : Result<ImmutableDictionary<string, obj>.Builder, IGQLError list>) struct(vardef, defaultValue) -> validation {
731-
let executeInput = compileByType $"Variable '%s{vardef.Name}': " vardef.TypeDef
737+
let executeInput = compileByType [] vardef.TypeDef
732738
let! value = executeInput defaultValue suppliedVaribles
733739
and! acc = acc
734740
acc.Add(vardef.Name, value)

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333

3434
<ItemGroup>
3535
<Compile Include="ReflectionHelper.fs" />
36-
<Compile Include="Errors.fs" />
36+
<Compile Include="ErrorTypes.fs" />
37+
<Compile Include="ErrorMessages.fs" />
3738
<Compile Include="ErrorsProcessing.fs" />
3839
<Compile Include="Exceptions.fs" />
3940
<Compile Include="Values.fs" />

0 commit comments

Comments
 (0)