@@ -14,40 +14,54 @@ open Microsoft.FSharp.Reflection
1414
1515/// Tries to convert type defined in AST into one of the type defs known in schema.
1616let inline tryConvertAst schema ast =
17- let rec convert isNullable ( schema : ISchema ) ( ast : InputType ) : TypeDef option =
17+ let rec convert isNullable ( schema : ISchema ) ( ast : InputType ) : TypeDef option =
1818 match ast with
1919 | NamedType name ->
2020 match schema.TryFindType name with
2121 | Some namedDef ->
22- Some ( if isNullable then upcast namedDef.MakeNullable() else upcast namedDef)
22+ Some (
23+ if isNullable then
24+ upcast namedDef.MakeNullable ()
25+ else
26+ upcast namedDef
27+ )
2328 | None -> None
2429 | ListType inner ->
2530 convert true schema inner
2631 |> Option.map ( fun i ->
27- if isNullable
28- then upcast i.MakeList() .MakeNullable()
29- else upcast i.MakeList())
30- | NonNullType inner ->
31- convert false schema inner
32+ if isNullable then
33+ upcast i.MakeList() .MakeNullable ()
34+ else
35+ upcast i.MakeList ())
36+ | NonNullType inner -> convert false schema inner
37+
3238 convert true schema ast
3339
34- let inline private notAssignableMsg ( innerDef : InputDef ) value : string =
40+ let inline private notAssignableMsg ( innerDef : InputDef ) value : string =
3541 sprintf " value of type %s is not assignable from %s " innerDef.Type.Name ( value.GetType() .Name)
3642
37- let rec internal compileByType ( errMsg : string ) ( inputDef : InputDef ): ExecuteInput =
43+ let rec internal compileByType ( errMsg : string ) ( inputDef : InputDef ) : ExecuteInput =
3844 match inputDef with
39- | Scalar scalardef ->
40- variableOrElse ( scalardef.CoerceInput >> Option.toObj)
45+ | Scalar scalardef -> variableOrElse ( scalardef.CoerceInput >> Option.toObj)
4146 | InputObject objdef ->
4247 let objtype = objdef.Type
4348 let ctor = ReflectionHelper.matchConstructor objtype ( objdef.Fields |> Array.map ( fun x -> x.Name))
49+
4450 let mapper =
45- ctor.GetParameters()
46- |> Array.map( fun param ->
47- match objdef.Fields |> Array.tryFind( fun field -> field.Name = param.Name) with
51+ ctor.GetParameters ()
52+ |> Array.map ( fun param ->
53+ match
54+ objdef.Fields
55+ |> Array.tryFind ( fun field -> field.Name = param.Name)
56+ with
4857 | Some x -> x
4958 | None ->
50- failwithf " Input object '%s ' refers to type '%O ', but constructor parameter '%s ' doesn't match any of the defined input fields" objdef.Name objtype param.Name)
59+ failwithf
60+ " Input object '%s ' refers to type '%O ', but constructor parameter '%s ' doesn't match any of the defined input fields"
61+ objdef.Name
62+ objtype
63+ param.Name)
64+
5165 fun value variables ->
5266 match value with
5367 | ObjectValue props ->
@@ -57,7 +71,8 @@ let rec internal compileByType (errMsg: string) (inputDef: InputDef): ExecuteInp
5771 match Map.tryFind field.Name props with
5872 | None -> null
5973 | Some prop -> field.ExecuteInput prop variables)
60- let instance = ctor.Invoke( args)
74+
75+ let instance = ctor.Invoke ( args)
6176 instance
6277 | Variable variableName ->
6378 match Map.tryFind variableName variables with
@@ -73,6 +88,7 @@ let rec internal compileByType (errMsg: string) (inputDef: InputDef): ExecuteInp
7388 match value with
7489 | ListValue list ->
7590 let mappedValues = list |> List.map ( fun value -> inner value variables)
91+
7692 if isArray then
7793 ReflectionHelper.arrayOfList innerdef.Type mappedValues
7894 else
@@ -81,21 +97,30 @@ let rec internal compileByType (errMsg: string) (inputDef: InputDef): ExecuteInp
8197 | _ ->
8298 // try to construct a list from single element
8399 let single = inner value variables
84- if single = null then null else
85- if isArray then ReflectionHelper.arrayOfList innerdef.Type [ single]
86- else cons single nil
100+
101+ if single = null then
102+ null
103+ else if isArray then
104+ ReflectionHelper.arrayOfList innerdef.Type [ single ]
105+ else
106+ cons single nil
87107 | Nullable ( Input innerdef) ->
88108 let inner = compileByType errMsg innerdef
89109 let some , none , _ = ReflectionHelper.optionOfType innerdef.Type
90110
91111 fun variables value ->
92112 let i = inner variables value
113+
93114 match i with
94115 | null -> none
95116 | coerced ->
96117 let c = some coerced
97- if c <> null then c
98- else raise( GraphQLException ( errMsg + notAssignableMsg innerdef coerced))
118+
119+ if c <> null then
120+ c
121+ else
122+ raise
123+ <| GraphQLException ( errMsg + notAssignableMsg innerdef coerced)
99124 | Enum enumdef ->
100125 fun value variables ->
101126 match value with
@@ -105,35 +130,50 @@ let rec internal compileByType (errMsg: string) (inputDef: InputDef): ExecuteInp
105130 | None -> failwithf " Variable '%s ' not supplied.\n Variables: %A " variableName variables
106131 | _ ->
107132 let coerced = coerceEnumInput value
133+
108134 match coerced with
109135 | None -> null
110- | Some s -> ReflectionHelper.parseUnion enumdef.Type s
136+ | Some s ->
137+ enumdef.Options
138+ |> Seq.tryFind ( fun v -> v.Name = s)
139+ |> Option.map ( fun x -> x.Value :?> _)
140+ |> Option.defaultWith ( fun () -> ReflectionHelper.parseUnion enumdef.Type s)
111141 | _ -> failwithf " Unexpected value of inputDef: %O " inputDef
112142
113- let rec private coerceVariableValue isNullable typedef ( vardef : VarDef ) ( input : obj ) ( errMsg : string ) : obj =
143+ let rec private coerceVariableValue isNullable typedef ( vardef : VarDef ) ( input : obj ) ( errMsg : string ) : obj =
114144 match typedef with
115145 | Scalar scalardef ->
116146 match scalardef.CoerceValue input with
117147 | None when isNullable -> null
118148 | None ->
119- raise ( GraphQLException <| errMsg + ( sprintf " expected value of type %s but got None" scalardef.Name))
149+ raise (
150+ GraphQLException
151+ <| $" %s {errMsg}expected value of type '%s {scalardef.Name}' but got 'None'."
152+ )
120153 | Some res -> res
121154 | Nullable ( Input innerdef) ->
122155 let some , none , innerValue = ReflectionHelper.optionOfType innerdef.Type
123156 let input = innerValue input
124157 let coerced = coerceVariableValue true innerdef vardef input errMsg
125- if coerced <> null
126- then
158+
159+ if coerced <> null then
127160 let s = some coerced
128- if s <> null
129- then s
130- else raise ( GraphQLException <| errMsg + ( sprintf " value of type %O is not assignable from %O " innerdef.Type ( coerced.GetType())))
131- else none
161+
162+ if s <> null then
163+ s
164+ else
165+ raise
166+ <| GraphQLException ( $" %s {errMsg}value of type '%O {innerdef.Type}' is not assignable from '%O {coerced.GetType ()}'." )
167+ else
168+ none
132169 | List ( Input innerdef) ->
133170 let cons , nil = ReflectionHelper.listOfType innerdef.Type
171+
134172 match input with
135173 | null when isNullable -> null
136- | null -> raise( GraphQLException <| errMsg + ( sprintf " expected value of type %s , but no value was found." ( vardef.TypeDef.ToString())))
174+ | null ->
175+ raise
176+ <| GraphQLException ( $" %s {errMsg}expected value of type '%s {vardef.TypeDef.ToString ()}', but no value was found." )
137177 // special case - while single values should be wrapped with a list in this scenario,
138178 // string would be treat as IEnumerable and coerced into a list of chars
139179 | :? string as s ->
@@ -148,37 +188,52 @@ let rec private coerceVariableValue isNullable typedef (vardef: VarDef) (input:
148188 |> Seq.toList
149189 |> List.rev
150190 |> List.fold ( fun acc coerced -> cons coerced acc) nil
191+
151192 mapped
152- | other -> raise ( GraphQLException <| errMsg + ( sprintf " Cannot coerce value of type '%O ' to list." ( other.GetType())))
153- | InputObject objdef ->
154- coerceVariableInputObject objdef vardef input ( errMsg + ( sprintf " in input object '%s ': " objdef.Name))
193+ | other ->
194+ raise
195+ <| GraphQLException ( $" {errMsg}Cannot coerce value of type '%O {other.GetType ()}' to list." )
196+ | InputObject objdef -> coerceVariableInputObject objdef vardef input ( errMsg + ( sprintf " in input object '%s ': " objdef.Name))
155197 | Enum enumdef ->
156198 match input with
157- | :? string as s ->
158- ReflectionHelper.parseUnion enumdef.Type s
199+ | :? string as s -> ReflectionHelper.parseUnion enumdef.Type s
159200 | null when isNullable -> null
160- | null -> raise( GraphQLException <| errMsg + ( sprintf " Expected Enum '%s ', but no value was found." enumdef.Name))
161- | u when FSharpType.IsUnion( enumdef.Type) && enumdef.Type = input.GetType() -> u
162- | o when Enum.IsDefined( enumdef.Type, o) -> o
201+ | null ->
202+ raise
203+ <| GraphQLException ( $" %s {errMsg}Expected Enum '%s {enumdef.Name}', but no value was found." )
204+
205+ | u when
206+ FSharpType.IsUnion ( enumdef.Type)
207+ && enumdef.Type = input.GetType ()
208+ ->
209+ u
210+ | o when Enum.IsDefined ( enumdef.Type, o) -> o
163211 | _ ->
164- raise ( GraphQLException <| errMsg + ( sprintf " Cannot coerce value of type '%O ' to type Enum '%s '" ( input.GetType()) enumdef.Name))
165- | _ -> raise ( GraphQLException <| errMsg + " Only Scalars, Nullables, Lists and InputObjects are valid type definitions." )
212+ raise (
213+ GraphQLException
214+ <| $" %s {errMsg}Cannot coerce value of type '%O {input.GetType ()}' to type Enum '%s {enumdef.Name}'."
215+ )
216+ | _ ->
217+ raise
218+ <| GraphQLException ( $" %s {errMsg}Only Scalars, Nullables, Lists, and InputObjects are valid type definitions." )
166219
167- and private coerceVariableInputObject ( objdef ) ( vardef : VarDef ) ( input : obj ) errMsg =
220+ and private coerceVariableInputObject ( objdef ) ( vardef : VarDef ) ( input : obj ) errMsg =
168221 //TODO: this should be eventually coerced to complex object
169222 match input with
170223 | :? Map< string, obj> as map ->
171224 let mapped =
172225 objdef.Fields
173226 |> Array.map ( fun field ->
174227 let valueFound = Map.tryFind field.Name map |> Option.toObj
175- ( field.Name, coerceVariableValue false field.TypeDef vardef valueFound ( errMsg + ( sprintf " in field '%s ': " field.Name )) ))
228+ ( field.Name, coerceVariableValue false field.TypeDef vardef valueFound $ " %s {errMsg} in field '%s {field.Name} ': " ))
176229 |> Map.ofArray
230+
177231 upcast mapped
178232 | _ -> input
179233
180- let internal coerceVariable ( vardef : VarDef ) ( inputs ) =
234+ let internal coerceVariable ( vardef : VarDef ) ( inputs ) =
181235 let vname = vardef.Name
236+
182237 match Map.tryFind vname inputs with
183238 | None ->
184239 match vardef.DefaultValue with
@@ -189,5 +244,7 @@ let internal coerceVariable (vardef: VarDef) (inputs) =
189244 | None ->
190245 match vardef.TypeDef with
191246 | Nullable _ -> null
192- | _ -> raise ( GraphQLException ( sprintf " Variable '$%s ' of required type %s has no value provided." vname ( vardef.TypeDef.ToString())))
247+ | _ ->
248+ raise
249+ <| GraphQLException ( $" Variable '$%s {vname}' of required type '%s {vardef.TypeDef.ToString ()}' has no value provided." )
193250 | Some input -> coerceVariableValue false vardef.TypeDef vardef input ( sprintf " Variable '$%s ': " vname)
0 commit comments