1- namespace FSharp.Data.GraphQL.Server.Middleware
1+ /// Contains customized schema definitions for extensibility features.
2+ [<AutoOpen>]
3+ module FSharp.Data.GraphQL.Server.Middleware.SchemaDefinitions
24
35open System
46open System.Collections .Generic
@@ -7,138 +9,155 @@ open System.Text.Json
79open FSharp.Data .GraphQL
810open FSharp.Data .GraphQL .Types
911open FSharp.Data .GraphQL .Ast
10- open FSharp.Data .GraphQL .Errors
11-
12- /// Contains customized schema definitions for extensibility features.
13- [<AutoOpen>]
14- module SchemaDefinitions =
1512
16- let internal removeNoFilter = Seq.where ( fun filter -> filter <> NoFilter)
13+ let internal removeNoFilter = Seq.where ( fun filter -> filter <> NoFilter)
1714
18- let rec private coerceObjectListFilterInput x : Result < ObjectListFilter , IGQLError list > =
15+ let rec private coerceObjectListFilterInput x : Result < ObjectListFilter , IGQLError list > =
1916
20- let (| EndsWith | StartsWith | GreaterThan | LessThan | Contains | Equals |) ( s : string ) =
21- let s = s.ToLowerInvariant()
22- let prefix ( suffix : string ) ( s : string ) = s.Substring( 0 , s.Length - suffix.Length)
23- match s with
24- | s when s.EndsWith( " _ends_with" ) && s.Length > " _ends_with" .Length -> EndsWith ( prefix " _ends_with" s)
25- | s when s.EndsWith( " _ew" ) && s.Length > " _ew" .Length -> EndsWith ( prefix " _ew" s)
26- | s when s.EndsWith( " _starts_with" ) && s.Length > " _starts_with" .Length -> StartsWith ( prefix " _starts_with" s)
27- | s when s.EndsWith( " _sw" ) && s.Length > " _sw" .Length -> StartsWith ( prefix " _sw" s)
28- | s when s.EndsWith( " _greater_than" ) && s.Length > " _greater_than" .Length -> GreaterThan ( prefix " _greater_than" s)
29- | s when s.EndsWith( " _gt" ) && s.Length > " _gt" .Length -> GreaterThan ( prefix " _gt" s)
30- | s when s.EndsWith( " _less_than" ) && s.Length > " _less_than" .Length -> LessThan ( prefix " _less_than" s)
31- | s when s.EndsWith( " _lt" ) && s.Length > " _lt" .Length -> LessThan ( prefix " _lt" s)
32- | s when s.EndsWith( " _contains" ) && s.Length > " _contains" .Length -> Contains ( prefix " _contains" s)
33- | s -> Equals s
17+ let (| EndsWith | StartsWith | GreaterThan | LessThan | Contains | Equals |) ( s : string ) =
18+ let s = s.ToLowerInvariant ()
19+ let prefix ( suffix : string ) ( s : string ) = s.Substring ( 0 , s.Length - suffix.Length)
20+ match s with
21+ | s when s.EndsWith ( " _ends_with" ) && s.Length > " _ends_with" .Length -> EndsWith ( prefix " _ends_with" s)
22+ | s when s.EndsWith ( " _ew" ) && s.Length > " _ew" .Length -> EndsWith ( prefix " _ew" s)
23+ | s when s.EndsWith ( " _starts_with" ) && s.Length > " _starts_with" .Length -> StartsWith ( prefix " _starts_with" s)
24+ | s when s.EndsWith ( " _sw" ) && s.Length > " _sw" .Length -> StartsWith ( prefix " _sw" s)
25+ | s when s.EndsWith ( " _greater_than" ) && s.Length > " _greater_than" .Length -> GreaterThan ( prefix " _greater_than" s)
26+ | s when s.EndsWith ( " _gt" ) && s.Length > " _gt" .Length -> GreaterThan ( prefix " _gt" s)
27+ | s when s.EndsWith ( " _less_than" ) && s.Length > " _less_than" .Length -> LessThan ( prefix " _less_than" s)
28+ | s when s.EndsWith ( " _lt" ) && s.Length > " _lt" .Length -> LessThan ( prefix " _lt" s)
29+ | s when s.EndsWith ( " _contains" ) && s.Length > " _contains" .Length -> Contains ( prefix " _contains" s)
30+ | s -> Equals s
3431
35- let (| EquatableValue | Other |) v =
36- match v with
37- | IntValue v -> EquatableValue ( v :> System.IComparable)
38- | FloatValue v -> EquatableValue ( v :> System.IComparable)
39- | BooleanValue v -> EquatableValue ( v :> System.IComparable)
40- | StringValue v -> EquatableValue ( v :> System.IComparable)
41- | EnumValue v -> EquatableValue ( v :> System.IComparable)
42- | v -> Other v
32+ let (| EquatableValue | Other |) v =
33+ match v with
34+ | IntValue v -> EquatableValue ( v :> System.IComparable)
35+ | FloatValue v -> EquatableValue ( v :> System.IComparable)
36+ | BooleanValue v -> EquatableValue ( v :> System.IComparable)
37+ | StringValue v -> EquatableValue ( v :> System.IComparable)
38+ | EnumValue v -> EquatableValue ( v :> System.IComparable)
39+ | v -> Other v
4340
44- let (| ComparableValue | Other |) v =
45- match v with
46- | IntValue v -> ComparableValue ( v :> System.IComparable)
47- | FloatValue v -> ComparableValue ( v :> System.IComparable)
48- | BooleanValue v -> ComparableValue ( v :> System.IComparable)
49- | StringValue v -> ComparableValue ( v :> System.IComparable)
50- | v -> Other v
41+ let (| ComparableValue | Other |) v =
42+ match v with
43+ | IntValue v -> ComparableValue ( v :> System.IComparable)
44+ | FloatValue v -> ComparableValue ( v :> System.IComparable)
45+ | BooleanValue v -> ComparableValue ( v :> System.IComparable)
46+ | StringValue v -> ComparableValue ( v :> System.IComparable)
47+ | v -> Other v
5148
52- let buildAnd x =
53- let rec build acc x =
54- match x with
55- | [] -> acc
56- | x :: xs ->
57- match acc with
58- | NoFilter -> build ( x) xs
59- | acc -> build (( And ( acc, x))) xs
60- build NoFilter x
49+ let buildAnd x =
50+ let rec build acc x =
51+ match x with
52+ | [] -> acc
53+ | x :: xs ->
54+ match acc with
55+ | NoFilter -> build ( x) xs
56+ | acc -> build (( And ( acc, x))) xs
57+ build NoFilter x
6158
62- let buildOr x =
63- let rec build acc x =
64- match x with
65- | [] -> acc
66- | x :: xs ->
67- match acc with
68- | NoFilter -> build ( x) xs
69- | acc -> build (( Or ( acc, x))) xs
70- build NoFilter x
59+ let buildOr x =
60+ let rec build acc x =
61+ match x with
62+ | [] -> acc
63+ | x :: xs ->
64+ match acc with
65+ | NoFilter -> build ( x) xs
66+ | acc -> build (( Or ( acc, x))) xs
67+ build NoFilter x
7168
72- let rec mapFilter ( name : string , value : InputValue ) =
73- let mapFilters fields =
74- let coerceResults =
75- fields |> Seq.map coerceObjectListFilterInput |> Seq.toList |> splitSeqErrorsList
76- match coerceResults with
77- | Error errs -> Error errs
78- | Ok coerced -> coerced |> removeNoFilter |> Seq.toList |> Ok
79- match name, value with
80- | Equals " and" , ListValue fields -> fields |> mapFilters |> Result.map buildAnd
81- | Equals " or" , ListValue fields -> fields |> mapFilters |> Result.map buildOr
82- | Equals " not" , ObjectValue value ->
83- match mapInput value with
84- | Error errs -> Error errs
85- | Ok NoFilter -> Ok NoFilter
86- | Ok filter -> Ok ( Not filter)
87- | EndsWith fname, StringValue value -> Ok ( EndsWith { FieldName = fname; Value = value })
88- | StartsWith fname, StringValue value -> Ok ( StartsWith { FieldName = fname; Value = value })
89- | Contains fname, StringValue value -> Ok ( Contains { FieldName = fname; Value = value })
90- | Equals fname, ObjectValue value ->
91- match mapInput value with
92- | Error errs -> Error errs
93- | Ok NoFilter -> Ok NoFilter
94- | Ok filter -> Ok ( FilterField { FieldName = fname; Value = filter })
95- | Equals fname, EquatableValue value -> Ok ( Equals { FieldName = fname; Value = value })
96- | GreaterThan fname, ComparableValue value -> Ok ( GreaterThan { FieldName = fname; Value = value })
97- | LessThan fname, ComparableValue value -> Ok ( LessThan { FieldName = fname; Value = value })
98- | _ -> Ok NoFilter
99-
100- and mapInput value =
101- let filterResults =
102- value |> Map.toSeq |> Seq.map mapFilter |> Seq.toList |> splitSeqErrorsList
103- match filterResults with
69+ let rec mapFilter ( name : string , value : InputValue ) =
70+ let mapFilters fields =
71+ let coerceResults =
72+ fields
73+ |> Seq.map coerceObjectListFilterInput
74+ |> Seq.toList
75+ |> splitSeqErrorsList
76+ match coerceResults with
77+ | Error errs -> Error errs
78+ | Ok coerced -> coerced |> removeNoFilter |> Seq.toList |> Ok
79+ match name, value with
80+ | Equals " and" , ListValue fields -> fields |> mapFilters |> Result.map buildAnd
81+ | Equals " or" , ListValue fields -> fields |> mapFilters |> Result.map buildOr
82+ | Equals " not" , ObjectValue value ->
83+ match mapInput value with
10484 | Error errs -> Error errs
105- | Ok filters ->
106- filters |> removeNoFilter |> List.ofSeq |> buildAnd |> Ok
107- match x with
108- | ObjectValue x -> mapInput x
109- | NullValue -> NoFilter |> Ok
110- // TODO: Get union case
111- | _ -> Error [{ new IGQLError with member _.Message = $" 'ObjectListFilter' must be defined as object but got '{x.GetType ()}'" }]
85+ | Ok NoFilter -> Ok NoFilter
86+ | Ok filter -> Ok ( Not filter)
87+ | EndsWith fname, StringValue value -> Ok ( EndsWith { FieldName = fname; Value = value })
88+ | StartsWith fname, StringValue value -> Ok ( StartsWith { FieldName = fname; Value = value })
89+ | Contains fname, StringValue value -> Ok ( Contains { FieldName = fname; Value = value })
90+ | Equals fname, ObjectValue value ->
91+ match mapInput value with
92+ | Error errs -> Error errs
93+ | Ok NoFilter -> Ok NoFilter
94+ | Ok filter -> Ok ( FilterField { FieldName = fname; Value = filter })
95+ | Equals fname, EquatableValue value -> Ok ( Equals { FieldName = fname; Value = value })
96+ | GreaterThan fname, ComparableValue value -> Ok ( GreaterThan { FieldName = fname; Value = value })
97+ | LessThan fname, ComparableValue value -> Ok ( LessThan { FieldName = fname; Value = value })
98+ | _ -> Ok NoFilter
99+
100+ and mapInput value =
101+ let filterResults =
102+ value
103+ |> Map.toSeq
104+ |> Seq.map mapFilter
105+ |> Seq.toList
106+ |> splitSeqErrorsList
107+ match filterResults with
108+ | Error errs -> Error errs
109+ | Ok filters -> filters |> removeNoFilter |> List.ofSeq |> buildAnd |> Ok
110+ match x with
111+ | ObjectValue x -> mapInput x
112+ | NullValue -> NoFilter |> Ok
113+ // TODO: Get union case
114+ | _ ->
115+ Error [
116+ { new IGQLError with
117+ member _.Message = $" 'ObjectListFilter' must be defined as object but got '{x.GetType ()}'"
118+ }
119+ ]
112120
113- let private coerceObjectListFilterValue ( x : obj ) : ObjectListFilter option =
114- match x with
115- | :? ObjectListFilter as x -> Some x
116- | _ -> None
117- //let private coerceObjectListFilterValue (x : obj) =
118- // match x with
119- // | :? ObjectListFilter as x -> Ok x
120- // | _ -> Error [{ new IGQLError with member _.Message = $"Cannot coerce ObjectListFilter output. '%s{x.GetType().FullName}' is not 'ObjectListFilter'" }]
121+ let private coerceObjectListFilterValue ( x : obj ) : ObjectListFilter option =
122+ match x with
123+ | :? ObjectListFilter as x -> Some x
124+ | _ -> None
125+ //let private coerceObjectListFilterValue (x : obj) =
126+ // match x with
127+ // | :? ObjectListFilter as x -> Ok x
128+ // | _ -> Error [{ new IGQLError with member _.Message = $"Cannot coerce ObjectListFilter output. '%s{x.GetType().FullName}' is not 'ObjectListFilter'" }]
121129
122- // TODO: Move to shared and make public
123- let rec private jsonElementToInputValue ( element : JsonElement ) =
124- match element.ValueKind with
125- | JsonValueKind.Null -> NullValue
126- | JsonValueKind.True -> BooleanValue true
127- | JsonValueKind.False -> BooleanValue false
128- | JsonValueKind.String -> StringValue ( element.GetString ())
129- | JsonValueKind.Number -> FloatValue ( element.GetDouble ())
130- | JsonValueKind.Array -> ListValue ( element.EnumerateArray () |> Seq.map jsonElementToInputValue |> List.ofSeq)
131- | JsonValueKind.Object -> ObjectValue ( element.EnumerateObject () |> Seq.map ( fun p -> p.Name, jsonElementToInputValue p.Value) |> Map.ofSeq)
132- | _ -> raise ( NotSupportedException " Unsupported JSON element type" )
130+ // TODO: Move to shared and make public
131+ let rec private jsonElementToInputValue ( element : JsonElement ) =
132+ match element.ValueKind with
133+ | JsonValueKind.Null -> NullValue
134+ | JsonValueKind.True -> BooleanValue true
135+ | JsonValueKind.False -> BooleanValue false
136+ | JsonValueKind.String -> StringValue ( element.GetString ())
137+ | JsonValueKind.Number -> FloatValue ( element.GetDouble ())
138+ | JsonValueKind.Array ->
139+ ListValue (
140+ element.EnumerateArray ()
141+ |> Seq.map jsonElementToInputValue
142+ |> List.ofSeq
143+ )
144+ | JsonValueKind.Object ->
145+ ObjectValue (
146+ element.EnumerateObject ()
147+ |> Seq.map ( fun p -> p.Name, jsonElementToInputValue p.Value)
148+ |> Map.ofSeq
149+ )
150+ | _ -> raise ( NotSupportedException " Unsupported JSON element type" )
133151
134- /// Defines an object list filter for use as an argument for filter list of object fields.
135- let ObjectListFilter : ScalarDefinition < ObjectListFilter > =
136- { Name = " ObjectListFilter"
137- Description =
138- Some
139- " 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."
140- CoerceInput =
141- ( function
142- | InlineConstant c -> coerceObjectListFilterInput c
143- | Variable json -> json |> jsonElementToInputValue |> coerceObjectListFilterInput)
144- CoerceOutput = coerceObjectListFilterValue }
152+ /// Defines an object list filter for use as an argument for filter list of object fields.
153+ let ObjectListFilter : ScalarDefinition < ObjectListFilter > = {
154+ Name = " ObjectListFilter"
155+ Description =
156+ Some
157+ " 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."
158+ CoerceInput =
159+ ( function
160+ | InlineConstant c -> coerceObjectListFilterInput c
161+ | Variable json -> json |> jsonElementToInputValue |> coerceObjectListFilterInput)
162+ CoerceOutput = coerceObjectListFilterValue
163+ }
0 commit comments