Description
We seem to have a lot of users using genqlient to query a Hasura-generated schema, and they aren't having a great time of it; a lot of bugs and feature requests have come up over time. It would be good for us to take the time to do something a little more holistic, to see what support should look like. We can then document that, fix any gaps, etc. Similar issues may apply to Dgraph, and other tools with large generated schemas.
Specific feature requests can go in specific issues, this is more of a meta-issue to think about how we should support hasura, and to document the same.
The Problems
From reading all the issues mentioning Hasura, it seems like the main thing is the query syntax which has several interesting properties (discussed in #149 and #260):
- it generates complex and often self-referential types
- you usually only want to set a few fields of the very large input objects
- it distinguishes implicit and explicit null (example)
These conflict badly with genqlient's defaults, and arguably with mapping the types to Go itself. (Some of these issues also apply to mutation inputs, but those are a bit closer to normal mutation inputs, and you probably use them in fewer places. Some of them also apply to other styles of input objects too, but hasura's are the most complex by far.)
There are also some other specific problems, which are more orthogonal but any documentation should mention too:
- hasura type names (both input and output) are non-idiomatic: Field name tranformations #206
And some other things to document:
- a list of good bindings for hasura types
From #206, the lunasec folks have a decently large example schema as an example. There's also a schema in #149. It could be interesting to have some tests against full hasura-generated schemas, or even integration tests against a hasura backend, to see how this looks.
What should we generate?
Some thinking out loud.
First of all, one theory -- already very possible -- is to say you just want to write your input object in the query. This is obviously less flexible, which in the common case is arguably good but doesn't scale well if you want to construct your queries with arbitrary Go logic, and doesn't handle certain cases like arbitrary-length lists of objects (although short of jsonb and arbitrary-length boolean it's not clear those really exist -- this is SQL after all). LunaSec is using this in several places (example).
Another theory is to just look at what (existing or plausible) options make hasura work better. I think use_struct_references
is kinda close already; but that doesn't handle builtins. Global omitempty
is a way out, but kinda a foot-gun for things like booleans. (LunaSec is doing that, via a fork.) Global omitempty
-and-pointer
is also an option -- hasura seems to now consider explicit null an error at least for all inputs if I'm understanding right? although on updates you might need it -- but that's annoying for builtins too. The problem is Go doesn't give us a lot to work with here for a "one-of" where you can't necessarily assume the go zero value is unused!
If we think a bit farther afield, I wonder about an API where we have separate constructors for each field you might want to set? It looks like you never per se need to set more than one (you can use an _and
instead). So it would look something like
function QueryAuthorInputWhereNameEquals(string) QueryAuthorInput
function QueryAuthorInputAnd(...QueryAuthorInput) QueryAuthorInput
And then the particulars of how we implement QueryAuthorInput
aren't as important. That's not the most composable -- the and syntax in particular is a bit ugly -- but maybe that's ok. You could always go back to the old way for special cases.
How should we configure?
Depending what we end up generating, we can look at how to configure genqlient to do so. One option is to figure out what a plugin would look like (#237). Another option is to have a special hasura: true
config that does what you want, but probably better is to just document "here's a good set of defaults for hasura". We can see based on what it makes sense to generate.
Your feedback is welcome!
Hasura users, please let us know which of these ideas sound good to you, whether you have any other problems, etc.! And if your schema/queries are open source, posting those would help me see what you're trying to do.