-
Notifications
You must be signed in to change notification settings - Fork 2k
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
consider changing the type-signature of parse and validate functions to return a MaybePromise #3421
Comments
I think I'm convinced 🤔 if we'll start this change from graphql-js it might easier to align to it in other libraries. I guess that would require a major release? |
We could potentially start this approach even in a non-breaking way (at least in type GraphQLParseFn = MaybePromise<typeof parse>; And encourage servers that allow overriding parse to change to that type signature for the parse function. Servers could use that type even without changing the actual type signature of the |
Do you actually mean the following? import * as gql from "graphql"
type ParseType = typeof gql.parse
type MaybPromise<T> = T | Promise<T>
type GraphQLParse = (...args: Parameters<ParseType>) => MaybPromise<ReturnType<ParseType>> Example on TypeScript Playground I cannot see why the following would help: type GraphQLParseFn = MaybePromise<typeof parse>; |
I do! |
If we add this, I'd encourage also adding Lines 82 to 91 in da57238
graphql-js/src/execution/execute.ts Lines 223 to 232 in da57238
There's simplicity in knowing that I've gone back and forth on this, but in the end I'm in favour of this change for parse. @n1ru4l's example of a parser cache is a good one. The overhead of this change would be extremely minimal (an For validate it's less clear, on top of caching I can think of rate-limiting and query-cost examples that may require async logic, but I would typically only perform these after the normal validation has passed (or maybe do them before even the parsing takes place...). I also wonder what making |
Both
parse
andvalidate
do 100% sync logic, so this request might seem obscure. Please let me try to break this down and propose why we might want to consider changing theparse
andvalidate
return types.Today all major GraphQL.js server and frameworks built on
graphql-js
wrap the functionsparse
,validate
,execute
andsubscribe
.execute
andsubscribe
both already return aMaybePromise
as the underlying logic can either be resolved sync or async, depending on the resolvers called or the errors occurring.Many GraphQL servers allow overwriting the
parse
,validate
,execute
, andsubscribe
functions. In user-land functionality of those functions can be customized by wrapping the originalgraphql-js
functions and then forwarding them to the server configuration as parameters.For example, caching for parse could be simply achieved in the following way:
parse in memory cache
For very big operations and GraphQL server replicas or serverless/edge worker environments, we might want to use a shared cache between our GraphQL handlers. E.g. we want to store our parsed operations or validation results within Redis instead of simply in memory.
async validate cache using redis
We can easily build this function, however, if passed to a server those libraries will not expect
validate
to return a Promise and usually raise an error or cause other unexpected behavior.This leads me to the following conclusion:
If the
parse
andvalidate
functions return aMaybePromise
instead of "only" a sync value, graphql-js enforces that server framework implementors ensure aPromise
returned fromparse
andvalidate
is correctly handled.Today adopters of different server frameworks have to convince the framework maintainers individually to allow a
validate
orparse
functions to return aPromise
.As a result, each framework comes up with a different way of hooking into those phases. An example for this is
mercurius
which has its own custom API for hooking into the graphql lifecycle.With envelop, The Guild started a project that gives people a common interface for adding caching and other features to the
parse
,validate
,execute
, andsubscribe
functions, while preserving the original function signature in order to be compatible with ANY high-level GraphQL framework. Adopters keep asking why they can not run async logic in the pre and post-validate/parse hooks and our answer to this is that we want to have 100% API compatibility withgraphql-js
, which limits people from innovating the plugin eco-system (n1ru4l/envelop#497).This led me to think about whether it might make sense to change the types of
parse
andvalidate
. This would have no impact on the current implementation of the functions. It would, however, be a breaking TypeScript change and graphql-js libraries would be forced to adapt to that change (usually by just adding aawait
in front ofvalidate
orparse
(which ib probably 99.99% of the use-cases is already happening inside an async context).The text was updated successfully, but these errors were encountered: