-
Notifications
You must be signed in to change notification settings - Fork 76
Directive chooser middleware #192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
|
||
/// 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DirectiveChooser
has a module to help composing choosers. We can easily build choosers based on other choosers, or diverse conditions.
@@ -126,7 +126,7 @@ let private directiveIncluder (directive: Directive) : Includer = | |||
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just removed this function as it is not referenced anywhere in the code.
match query, variables with | ||
| Some query, Some variables -> | ||
printfn "Received query: %s" query | ||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 theMetadata
object ofexecutor.AsyncExecute
method. If the middleware is present in the pipeline, it will look for this chooser function and apply it to the operation.