33module FSharp.Data.GraphQL.Server.Middleware.SchemaDefinitions
44
55open System
6- open System.Collections .Generic
7- open System.Collections .Immutable
8- open System.Text .Json
96open FSharp.Data .GraphQL
107open FSharp.Data .GraphQL .Types
118open FSharp.Data .GraphQL .Ast
@@ -22,7 +19,7 @@ type private ComparisonOperator =
2219 | LessThanOrEqual of string
2320 | In of string
2421
25- let rec private coerceObjectListFilterInput x : Result < ObjectListFilter voption , IGQLError list > =
22+ let rec private coerceObjectListFilterInput ( variables : Variables ) inputValue : Result < ObjectListFilter voption , IGQLError list > =
2623
2724 let parseFieldCondition ( s : string ) =
2825 let s = s.ToLowerInvariant ()
@@ -81,17 +78,17 @@ let rec private coerceObjectListFilterInput x : Result<ObjectListFilter voption,
8178 | ValueSome acc -> build ( ValueSome ( Or ( acc, x))) xs
8279 build ValueNone x
8380
84- let rec mapFilter ( name : string , value : InputValue ) =
81+ let rec mapFilter ( condition : ComparisonOperator ) ( value : InputValue ) =
8582 let mapFilters fields =
8683 let coerceResults =
8784 fields
88- |> Seq.map coerceObjectListFilterInput
85+ |> Seq.map ( coerceObjectListFilterInput variables )
8986 |> Seq.toList
9087 |> splitSeqErrorsList
9188 match coerceResults with
9289 | Error errs -> Error errs
9390 | Ok coerced -> coerced |> Seq.vchoose id |> Seq.toList |> Ok
94- match parseFieldCondition name , value with
91+ match condition , value with
9592 | Equals " and" , ListValue fields -> fields |> mapFilters |> Result.map buildAnd
9693 | Equals " or" , ListValue fields -> fields |> mapFilters |> Result.map buildOr
9794 | Equals " not" , ObjectValue value ->
@@ -126,76 +123,58 @@ let rec private coerceObjectListFilterInput x : Result<ObjectListFilter voption,
126123 |> splitSeqErrors
127124 return ValueSome ( ObjectListFilter.In { FieldName = fname; Value = parsedValues |> Array.toList })
128125 }
126+ | condition, VariableName variableName ->
127+ match variables.TryGetValue variableName with
128+ | true , value -> mapFilter condition ( value |> InputValue.OfObject)
129+ | false , _ -> Errors.Variables.getVariableNotFoundError variableName
129130 | _ -> Ok ValueNone
130131
131132 and mapInput value =
132133 let filterResults =
133134 value
134- |> Map.toSeq
135- |> Seq.map mapFilter
135+ |> Seq.map ( fun kvp -> mapFilter ( parseFieldCondition kvp.Key) kvp.Value)
136136 |> Seq.toList
137137 |> splitSeqErrorsList
138138 match filterResults with
139139 | Error errs -> Error errs
140140 | Ok filters -> filters |> Seq.vchoose id |> List.ofSeq |> buildAnd |> Ok
141141
142- match x with
143- | ObjectValue x -> mapInput x
144- | NullValue -> ValueNone |> Ok
145- // TODO: Get union case
146- | _ ->
147- Error [
148- { new IGQLError with
149- member _.Message = $" 'ObjectListFilter' must be defined as object but got '{x.GetType ()}'"
150- }
151- ]
142+ let rec parse inputValue =
143+ match inputValue with
144+ | ObjectValue x -> mapInput x
145+ | NullValue -> ValueNone |> Ok
146+ | VariableName variableName ->
147+ match variables.TryGetValue variableName with
148+ | true , (:? ObjectListFilter as filter) -> ValueSome filter |> Ok
149+ | true , value ->
150+ System.Diagnostics.Debug.Fail " We expect the root value is parsed into ObjectListFilter"
151+ value |> InputValue.OfObject |> parse
152+ | false , _ -> Errors.Variables.getVariableNotFoundError variableName
153+ // TODO: Get union case
154+ | _ ->
155+ Error [
156+ { new IGQLError with
157+ member _.Message = $" 'ObjectListFilter' must be defined as object but got '{inputValue.GetType ()}'"
158+ }
159+ ]
160+ parse inputValue
152161
153- let private coerceObjectListFilterValue ( x : obj ) : ObjectListFilter option =
154- match x with
155- | :? ObjectListFilter as x -> Some x
156- | _ -> None
157- //let private coerceObjectListFilterValue (x : obj) =
158- // match x with
159- // | :? ObjectListFilter as x -> Ok x
160- // | _ -> Error [{ new IGQLError with member _.Message = $"Cannot coerce ObjectListFilter output. '%s{x.GetType().FullName}' is not 'ObjectListFilter'" }]
161-
162- // TODO: Move to shared and make public
163- let rec private jsonElementToInputValue ( element : JsonElement ) =
164- match element.ValueKind with
165- | JsonValueKind.Null -> NullValue
166- | JsonValueKind.True -> BooleanValue true
167- | JsonValueKind.False -> BooleanValue false
168- | JsonValueKind.String -> StringValue ( element.GetString ())
169- | JsonValueKind.Number -> FloatValue ( element.GetDouble ())
170- | JsonValueKind.Array ->
171- ListValue (
172- element.EnumerateArray ()
173- |> Seq.map jsonElementToInputValue
174- |> List.ofSeq
175- )
176- | JsonValueKind.Object ->
177- ObjectValue (
178- element.EnumerateObject ()
179- |> Seq.map ( fun p -> p.Name, jsonElementToInputValue p.Value)
180- |> Map.ofSeq
181- )
182- | _ -> raise ( NotSupportedException " Unsupported JSON element type" )
183162
184163/// Defines an object list filter for use as an argument for filter list of object fields.
185- let ObjectListFilterType : ScalarDefinition < ObjectListFilter > = {
164+ let ObjectListFilterType : InputCustomDefinition < ObjectListFilter > = {
186165 Name = " ObjectListFilter"
187166 Description =
188167 Some
189168 " The `Filter` scalar type represents a filter on one or more fields of an object in an object list. The filter is represented by a JSON object where the fields are the complemented by specific suffixes to represent a query."
190169 CoerceInput =
191- ( function
192- | InlineConstant c ->
193- coerceObjectListFilterInput c
194- |> Result.map ValueOption.toObj
195- | Variable json ->
196- json
197- |> jsonElementToInputValue
198- |> coerceObjectListFilterInput
199- |> Result.map ValueOption.toObj )
200- CoerceOutput = coerceObjectListFilterValue
170+ ( fun input variables ->
171+ match input with
172+ | InlineConstant c ->
173+ ( coerceObjectListFilterInput variables c )
174+ |> Result.map ValueOption.toObj
175+ | Variable json ->
176+ json
177+ |> InputValue.OfJsonElement
178+ |> ( coerceObjectListFilterInput variables )
179+ |> Result.map ValueOption.toObj )
201180}
0 commit comments