Skip to content

Commit 3c2a25f

Browse files
xperiandriViktor Tochonov
authored andcommitted
Migrated ObjectListFilter to voption
1 parent 3bf509e commit 3c2a25f

File tree

23 files changed

+252
-225
lines changed

23 files changed

+252
-225
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ type ObjectListFilter =
399399
| FilterField of FieldFilter<ObjectListFilter>
400400
```
401401

402-
And the value recovered by the filter in the query is usable in the `ResolveFieldContext` of the resolve function of the field. To easily access it, you can use the extension method `Filter`, wich returns an `ObjectListFilter option` (it does not have a value if the object doesn't implement a list with the middleware generic definition, or if the user didn't provide a filter input).
402+
And the value recovered by the filter in the query is usable in the `ResolveFieldContext` of the resolve function of the field. To easily access it, you can use the extension method `Filter`, which returns an `ObjectListFilter voption` (it does not have a value if the object doesn't implement a list with the middleware generic definition, or if the user didn't provide a filter input).
403403

404404
```fsharp
405405
Define.Field("friends", ListOf (Nullable CharacterType),

samples/relay-book-store/Domain.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module BookCursor =
2020
Title = get.Required.Field "t" Decode.string
2121
})
2222

23-
let tryDecode (x : string) : BookCursor option = option {
23+
let tryDecode (x : string) : BookCursor voption = voption {
2424
let! bytes = Base64.tryDecode x
2525
let! json = Utf8.tryDecode bytes
2626

samples/relay-book-store/Prelude.fs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ namespace FSharp.Data.GraphQL.Samples.RelayBookStore
33
[<AutoOpen>]
44
module internal Prelude =
55

6-
let vopt =
7-
function
8-
| Some x -> ValueSome x
9-
| None -> ValueNone
10-
116
[<RequireQualifiedAccess>]
127
module Base64 =
138

samples/relay-book-store/Schema.fs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,34 +53,34 @@ let booksField =
5353

5454
let after =
5555
ctx.TryArg ("after")
56-
|> Option.map (fun s ->
56+
|> ValueOption.map (fun s ->
5757
match BookCursor.tryDecode s with
58-
| Some c -> c
59-
| None -> raise (GQLMessageException ("Invalid cursor value for after")))
58+
| ValueSome c -> c
59+
| ValueNone -> raise (GQLMessageException ("Invalid cursor value for after")))
6060

6161
let last = ctx.TryArg ("last")
6262

6363
let before =
6464
ctx.TryArg ("before")
65-
|> Option.map (fun s ->
65+
|> ValueOption.map (fun s ->
6666
match BookCursor.tryDecode s with
67-
| Some c -> c
68-
| None -> raise (GQLMessageException ("Invalid cursor value for before")))
67+
| ValueSome c -> c
68+
| ValueNone -> raise (GQLMessageException ("Invalid cursor value for before")))
6969

7070
match first, after, last, before with
71-
| Some first, _, None, None ->
71+
| ValueSome first, _, ValueNone, ValueNone ->
7272
if first < 0 then
7373
raise (GQLMessageException ($"first must be at least 0"))
7474

75-
Forward (first, vopt after)
76-
| None, None, Some last, _ ->
75+
Forward (first, after)
76+
| ValueNone, ValueNone, ValueSome last, _ ->
7777
if last < 0 then
7878
raise (GQLMessageException ($"last must be at least 0"))
7979

80-
Backward (last, vopt before)
81-
| None, _, None, _ -> raise (GQLMessageException ($"Must specify first or last"))
82-
| Some _, _, _, _ -> raise (GQLMessageException ($"Must not combine first with last or before"))
83-
| _, _, Some _, _ -> raise (GQLMessageException ($"Must not combine last with first or after"))
80+
Backward (last, before)
81+
| ValueNone, _, ValueNone, _ -> raise (GQLMessageException ($"Must specify first or last"))
82+
| ValueSome _, _, _, _ -> raise (GQLMessageException ($"Must not combine first with last or before"))
83+
| _, _, ValueSome _, _ -> raise (GQLMessageException ($"Must not combine last with first or after"))
8484

8585
// The total number of edges in the data-store, not the number of edges in the page!
8686
let totalCount = async {

src/FSharp.Data.GraphQL.Server.Middleware/MiddlewareDefinitions.fs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
namespace FSharp.Data.GraphQL.Server.Middleware
22

3+
open System.Collections.Generic
4+
open System.Collections.Immutable
35
open FsToolkit.ErrorHandling
6+
47
open FSharp.Data.GraphQL
58
open FSharp.Data.GraphQL.Types.Patterns
69
open FSharp.Data.GraphQL.Types
@@ -14,8 +17,8 @@ type internal QueryWeightMiddleware(threshold : float, reportToMetadata : bool)
1417
then 0.0
1518
else
1619
match f.Definition.Metadata.TryFind<float>("queryWeight") with
17-
| Some w -> w
18-
| None -> 0.0
20+
| ValueSome w -> w
21+
| ValueNone -> 0.0
1922
// let rec getFields = function
2023
// | ResolveValue -> []
2124
// | SelectFields fields -> fields
@@ -82,7 +85,7 @@ type internal ObjectListFilterMiddleware<'ObjectType, 'ListType>(reportToMetadat
8285
next ctx
8386

8487
let reportMiddleware (ctx : ExecutionContext) (next : ExecutionContext -> AsyncVal<GQLExecutionResult>) =
85-
let rec collectArgs (acc : (string * ObjectListFilter) list) (fields : ExecutionInfo list) =
88+
let rec collectArgs (acc : KeyValuePair<string, ObjectListFilter> list) (fields : ExecutionInfo list) =
8689
let fieldArgs field =
8790
let filterResults =
8891
field.Ast.Arguments
@@ -96,7 +99,7 @@ type internal ObjectListFilterMiddleware<'ObjectType, 'ListType>(reportToMetadat
9699
| Ok filters ->
97100
filters
98101
|> removeNoFilter
99-
|> Seq.map (fun x -> field.Ast.AliasOrName, x)
102+
|> Seq.map (fun x -> KeyValuePair (field.Ast.AliasOrName, x))
100103
|> Seq.toList
101104
|> Ok
102105
match fields with
@@ -119,7 +122,8 @@ type internal ObjectListFilterMiddleware<'ObjectType, 'ListType>(reportToMetadat
119122
match reportToMetadata with
120123
| true ->
121124
let! args = collectArgs [] ctx.ExecutionPlan.Fields
122-
return { ctx with Metadata = ctx.Metadata.Add("filters", args) }
125+
let filters = ImmutableDictionary.CreateRange args
126+
return { ctx with Metadata = ctx.Metadata.Add("filters", filters) }
123127
| false -> return ctx
124128
}
125129
match ctxResult with

src/FSharp.Data.GraphQL.Server.Middleware/TypeSystemExtensions.fs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
namespace FSharp.Data.GraphQL.Server.Middleware
22

3+
open System
4+
open System.Collections.Immutable
5+
open FsToolkit.ErrorHandling
6+
37
open FSharp.Data.GraphQL.Types
48

59
/// Contains extensions for the type system.
@@ -16,13 +20,23 @@ module TypeSystemExtensions =
1620
/// <param name="weight">A float value representing the weight that this field have on the query.</param>
1721
member this.WithQueryWeight (weight : float) : FieldDef<'Val> = this.WithMetadata (this.Metadata.Add ("queryWeight", weight))
1822

23+
type ObjectListFilters = ImmutableDictionary<string, ObjectListFilter>
24+
25+
type ExecutionContext with
26+
27+
/// <summary>
28+
/// Gets the filters applied to the lists.
29+
/// </summary>
30+
member this.Filters = this.Metadata.TryFind<ObjectListFilters> "filters"
31+
1932
type ResolveFieldContext with
2033

2134
/// <summary>
2235
/// Gets the filter argument value for this field, if it does have one.
2336
/// Field argument is defined by the ObjectFilterMiddleware.
2437
/// </summary>
2538
member this.Filter =
26-
match this.Args.TryFind ("filter") with
27-
| Some (:? ObjectListFilter as f) -> Some f
28-
| _ -> None
39+
match this.Args.TryGetValue "filter" with
40+
| true, (:? ObjectListFilter as f) -> ValueSome f
41+
| false, _ -> ValueNone
42+
| true, _ -> raise (InvalidOperationException "Invalid filter argument type.")

src/FSharp.Data.GraphQL.Server.Relay/Connections.fs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,17 @@ module Cursor =
8585
[<AutoOpen>]
8686
module Definitions =
8787

88-
let private vopt =
89-
function
90-
| Some x -> ValueSome x
91-
| None -> ValueNone
92-
9388
/// Active pattern used to match context arguments in order
9489
/// to construct Relay slice information.
9590
[<return: Struct>]
9691
let (|SliceInfo|_|) (ctx : ResolveFieldContext) =
9792
match ctx.TryArg "first", ctx.TryArg "after" with
98-
| Some (first), None -> ValueSome (Forward (first, ValueNone))
99-
| Some (first), (after) -> ValueSome (Forward (first, vopt after))
100-
| None, _ ->
93+
| ValueSome (first), ValueNone -> ValueSome (Forward (first, ValueNone))
94+
| ValueSome (first), (after) -> ValueSome (Forward (first, after))
95+
| ValueNone, _ ->
10196
match ctx.TryArg "last", ctx.TryArg "before" with
102-
| Some (last), None -> ValueSome (Backward (last, ValueNone))
103-
| Some (last), (before) -> ValueSome (Backward (last, vopt before))
97+
| ValueSome (last), ValueNone -> ValueSome (Backward (last, ValueNone))
98+
| ValueSome (last), (before) -> ValueSome (Backward (last, before))
10499
| _, _ -> ValueNone
105100

106101
/// Object defintion representing information about pagination in context of Relay connection

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ let rec private abstractionInfo (ctx : PlanningContext) (parentDef : AbstractDef
115115
| None -> Map.empty
116116
| None ->
117117
match ctx.Schema.TryFindType typeName with
118-
| Some (Abstract abstractDef) ->
118+
| ValueSome (Abstract abstractDef) ->
119119
abstractionInfo ctx abstractDef field ValueNone includer
120120
| _ ->
121121
let pname = parentDef :?> NamedDef
@@ -153,9 +153,9 @@ let private doesFragmentTypeApply (schema: ISchema) fragment (objectType: Object
153153
| ValueNone -> true
154154
| ValueSome typeCondition ->
155155
match schema.TryFindType typeCondition with
156-
| None -> false
157-
| Some conditionalType when conditionalType.Name = objectType.Name -> true
158-
| Some (Abstract conditionalType) -> schema.IsPossibleType conditionalType objectType
156+
| ValueNone -> false
157+
| ValueSome conditionalType when conditionalType.Name = objectType.Name -> true
158+
| ValueSome (Abstract conditionalType) -> schema.IsPossibleType conditionalType objectType
159159
| _ -> false
160160

161161
let private isDeferredField (field: Field) =
@@ -342,16 +342,14 @@ let private planVariables (schema: ISchema) (operation: OperationDefinition) =
342342
|> List.map (fun vdef ->
343343
let vname = vdef.VariableName
344344
match Values.tryConvertAst schema vdef.Type with
345-
| None ->
345+
| ValueNone ->
346346
Debug.Fail "Must be prevented by validation"
347347
raise (MalformedGQLQueryException $"GraphQL query defined variable '$%s{vname}' of type '%s{vdef.Type.ToString()}' which is not known in the current schema")
348-
| Some tdef ->
349-
match tdef with
350-
| :? InputDef as idef ->
351-
{ VarDef.Name = vname; TypeDef = idef; DefaultValue = vdef.DefaultValue }
352-
| _ ->
353-
Debug.Fail "Must be prevented by validation"
354-
raise (MalformedGQLQueryException $"GraphQL query defined variable '$%s{vname}' of type '%s{tdef.ToString()}' which is not an input type definition"))
348+
| ValueSome (:? InputDef as idef) ->
349+
{ VarDef.Name = vname; TypeDef = idef; DefaultValue = vdef.DefaultValue }
350+
| ValueSome tdef ->
351+
Debug.Fail "Must be prevented by validation"
352+
raise (MalformedGQLQueryException $"GraphQL query defined variable '$%s{vname}' of type '%s{tdef.ToString()}' which is not an input type definition"))
355353

356354
let internal planOperation (ctx: PlanningContext) : ExecutionPlan =
357355
// Create artificial plan info to start with

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,19 @@ let private normalizeOptional (outputType : Type) value =
7373

7474
/// Tries to convert type defined in AST into one of the type defs known in schema.
7575
let inline tryConvertAst schema ast =
76-
let rec convert isNullable (schema : ISchema) (ast : InputType) : TypeDef option =
76+
let rec convert isNullable (schema : ISchema) (ast : InputType) : TypeDef voption =
7777
match ast with
7878
| NamedType name ->
79-
match schema.TryFindType name with
80-
| Some namedDef ->
81-
Some (
82-
if isNullable then
83-
upcast namedDef.MakeNullable ()
84-
else
85-
upcast namedDef
86-
)
87-
| None -> None
79+
schema.TryFindType name
80+
|> ValueOption.map (fun namedDef ->
81+
if isNullable then
82+
upcast namedDef.MakeNullable ()
83+
else
84+
upcast namedDef
85+
)
8886
| ListType inner ->
8987
convert true schema inner
90-
|> Option.map (fun i ->
88+
|> ValueOption.map (fun i ->
9189
if isNullable then
9290
upcast i.MakeList().MakeNullable ()
9391
else
@@ -121,7 +119,7 @@ let rec internal compileByType
121119
(fun (allParameters : _ ResizeArray) param ->
122120
match
123121
objDef.Fields
124-
// TODO: Improve parameter name matching logic
122+
// TODO: Improve parameter name matching logic
125123
|> Array.tryFind (fun field -> String.Equals (field.Name, param.Name, StringComparison.InvariantCultureIgnoreCase))
126124
with
127125
| Some field ->

src/FSharp.Data.GraphQL.Shared/Helpers/ObjAndStructConversions.fs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace rec FSharp.Data.GraphQL
22

3+
open System.Linq
34
open FsToolkit.ErrorHandling
45

56
module internal ValueOption =
@@ -24,10 +25,25 @@ module internal Seq =
2425
|> Seq.where ValueOption.isSome
2526
|> Seq.map ValueOption.get
2627

28+
let vtryFind predicate seq =
29+
seq
30+
|> Seq.where predicate
31+
|> Seq.map ValueSome
32+
|> _.FirstOrDefault()
33+
2734
module internal List =
2835

29-
let vchoose mapping list = list |> Seq.vchoose mapping |> List.ofSeq
36+
let vchoose mapping list = list |> Seq.ofList |> Seq.vchoose mapping |> List.ofSeq
37+
38+
let vtryFind predicate list = list |> Seq.ofList |> Seq.vtryFind predicate
3039

3140
module internal Array =
3241

3342
let vchoose mapping array = array |> Seq.vchoose mapping |> Array.ofSeq
43+
44+
module internal Map =
45+
46+
let vtryFind key (map : Map<_, _>) =
47+
match map.TryGetValue key with
48+
| true, value -> ValueSome value
49+
| false, _ -> ValueNone

0 commit comments

Comments
 (0)