Directive chooser middleware#192
Directive chooser middleware#192ivelten wants to merge 11 commits intofsprojects:devfrom ivelten:defer-ext
Conversation
| [ DirectiveChooser.fallbackDefer; DirectiveChooser.fallbackStream; DirectiveChooser.fallbackLive ] | ||
| |> DirectiveChooser.fromSeq | ||
| |> DirectiveChooser.merge (DirectiveChooser.fallbackWhen (fun _ -> fallbackDirectives)) | ||
| Metadata.WithDirectiveChooser(chooser) |
There was a problem hiding this comment.
Here we can use DirectiveChooser module to quickly build and compose choosers. In this example, I'm fallbacking defer, stream and live directives when fallbackDirectives is true - in other words, they will be returned directly.
| open FSharp.Data.GraphQL.Ast | ||
|
|
||
| /// A function that checks if a directive should be used in the exection of a query, or changed to a new directive. | ||
| type DirectiveChooser = Directive -> Directive option |
There was a problem hiding this comment.
This function will be used to choose Directives. We can opt to transform them into a new Directive, or remove them from the operation. For example, if we remove a defer directive by returning None, all deferred fields will be returned directly. This is also implemented in helper functions of DirectiveChooser module, like fallbackByName, fallbackDefer, etc.
| type DirectiveChooser = Directive -> Directive option | ||
|
|
||
| /// Basic operations on DirectiveChoosers. | ||
| module DirectiveChooser = |
There was a problem hiding this comment.
DirectiveChooser has a module to help composing choosers. We can easily build choosers based on other choosers, or diverse conditions.
| | None -> raise (GraphQLException (sprintf "Expected 'if' argument of directive '@%s' to have boolean value but got %A" directive.Name other)) | ||
|
|
||
| let private incl: Includer = fun _ -> true | ||
| let private excl: Includer = fun _ -> false |
There was a problem hiding this comment.
Just removed this function as it is not referenced anywhere in the code.
| printfn "Received variables: %A" variables | ||
| let query = query |> removeSpacesAndNewLines | ||
| let result = Schema.executor.AsyncExecute(query, variables = variables, data = Schema.root) |> Async.RunSynchronously | ||
| let result = Schema.executor.AsyncExecute(query, variables = variables, data = Schema.root, meta = buildMetadata true) |> Async.RunSynchronously |
There was a problem hiding this comment.
We can define our choosers on a per request basis, as they are sent into the Metadata object of the AsyncExecute last param.
|
|
||
| /// Builds a chooser that, given a Directive x, if x.Name is 'defer', returns None. | ||
| /// Otherwise, returns Some x. | ||
| let fallbackDefer = fallbackByName "defer" |
There was a problem hiding this comment.
On a second thought, I'm not sure if we need all of those helpers on the DirectiveChooser module. Can be useful to make readable code, but things can be much simpler if we just apply the chooser function directly.
|
And this |
With this Pull Request, I'm proposing an operation planning middleware that changes the current operation based on directives present in the query. The user can choose directives with a chooser function(
Directive -> Directive option) by placing it in theMetadataobject ofexecutor.AsyncExecutemethod. If the middleware is present in the pipeline, it will look for this chooser function and apply it to the operation.