Skip to content

[Meta] Document and improve support for Hasura & Dgraph schemas #272

Open
@benjaminjkraft

Description

@benjaminjkraft

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:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or requestneeds designIssues where we don't know exactly what we need yet; discuss on the issue before implementing

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions