Add support for calling fields with arguments #301
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
GraphQL supports fields at arbitrary depths that take arguments. We already support passing args at the base-most level of a query, like with:
but, GraphQL supports sending args at any depth at all! For example, you might want to fetch a filtered list of widgets, and their child gizmos, and filter the list of gizmos for each widget as well! In GraphQL, this looks like:
We don't currently support this in the JS client, even though our GraphQL schema supports it fine. The main use case is adjusting how many child records you get back for each parent on a nested fetch, as well as filtering those child records, and asks in discord have cropped up a bunch for this. In this code snippet, where do you put arguments for gizmos?:
This adds a thing to do this just this! There's two parts to it: knowing which fields take arguments, which we currently don't really describe, and then adding a JS-land syntax for passing calls at an arbitrary place in the selection. I chose to do this with a new primitive that looks like this:
What I like about this is that it isn't a breaking change, and you only have to deal with it once you start caring about calling fields -- selections remain nice and simple in the general case. I don't love it though, its a bit weird to mix objects into the tree like this, and it sucks that you still need to care about edges and nodes for connections, which I think will be the lion's share of the use case.
Also tricky is making this typesafe. Args like this don't really affect the output type, but ideally, the arguments you did pass are typechecked too. Currently, the
Select<>
type helper traverses aSchema
type that looks like this:which doesn't describe the type of the arguments. We need to get them in somehow. We could make a breaking change to this type, but in case anyone is importing it, and to lower the risk we accidentally break something, I would love to keep the structure of this schema type largely the same. Open to other ideas, but I propose we change the generated type Gadget side to look like this:
Field Identifiers starting with
$
are illegal in GraphQL, so we know there will never be a field named$args
, and can thusly stash the types there. Then, theSelect<>
type gets a bit smarter and starts looking forCall
objects, and inspecting for args if there are any.PR Checklist