3
3
module FSharp.Data.GraphQL.Server.Middleware.SchemaDefinitions
4
4
5
5
open System
6
- open System.Collections .Generic
7
- open System.Collections .Immutable
8
- open System.Text .Json
9
6
open FSharp.Data .GraphQL
10
7
open FSharp.Data .GraphQL .Types
11
8
open FSharp.Data .GraphQL .Ast
@@ -22,7 +19,7 @@ type private ComparisonOperator =
22
19
| LessThanOrEqual of string
23
20
| In of string
24
21
25
- let rec private coerceObjectListFilterInput x : Result < ObjectListFilter voption , IGQLError list > =
22
+ let rec private coerceObjectListFilterInput ( variables : Variables ) inputValue : Result < ObjectListFilter voption , IGQLError list > =
26
23
27
24
let parseFieldCondition ( s : string ) =
28
25
let s = s.ToLowerInvariant ()
@@ -81,17 +78,17 @@ let rec private coerceObjectListFilterInput x : Result<ObjectListFilter voption,
81
78
| ValueSome acc -> build ( ValueSome ( Or ( acc, x))) xs
82
79
build ValueNone x
83
80
84
- let rec mapFilter ( name : string , value : InputValue ) =
81
+ let rec mapFilter ( condition : ComparisonOperator ) ( value : InputValue ) =
85
82
let mapFilters fields =
86
83
let coerceResults =
87
84
fields
88
- |> Seq.map coerceObjectListFilterInput
85
+ |> Seq.map ( coerceObjectListFilterInput variables )
89
86
|> Seq.toList
90
87
|> splitSeqErrorsList
91
88
match coerceResults with
92
89
| Error errs -> Error errs
93
90
| Ok coerced -> coerced |> Seq.vchoose id |> Seq.toList |> Ok
94
- match parseFieldCondition name , value with
91
+ match condition , value with
95
92
| Equals " and" , ListValue fields -> fields |> mapFilters |> Result.map buildAnd
96
93
| Equals " or" , ListValue fields -> fields |> mapFilters |> Result.map buildOr
97
94
| Equals " not" , ObjectValue value ->
@@ -126,76 +123,58 @@ let rec private coerceObjectListFilterInput x : Result<ObjectListFilter voption,
126
123
|> splitSeqErrors
127
124
return ValueSome ( ObjectListFilter.In { FieldName = fname; Value = parsedValues |> Array.toList })
128
125
}
126
+ | condition, VariableName variableName ->
127
+ match variables.TryGetValue variableName with
128
+ | true , value -> mapFilter condition ( value |> InputValue.OfObject)
129
+ | false , _ -> Errors.Variables.getVariableNotFoundError variableName
129
130
| _ -> Ok ValueNone
130
131
131
132
and mapInput value =
132
133
let filterResults =
133
134
value
134
- |> Map.toSeq
135
- |> Seq.map mapFilter
135
+ |> Seq.map ( fun kvp -> mapFilter ( parseFieldCondition kvp.Key) kvp.Value)
136
136
|> Seq.toList
137
137
|> splitSeqErrorsList
138
138
match filterResults with
139
139
| Error errs -> Error errs
140
140
| Ok filters -> filters |> Seq.vchoose id |> List.ofSeq |> buildAnd |> Ok
141
141
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
152
161
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" )
183
162
184
163
/// 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 > = {
186
165
Name = " ObjectListFilter"
187
166
Description =
188
167
Some
189
168
" 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."
190
169
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 )
201
180
}
0 commit comments