genqlient icon indicating copy to clipboard operation
genqlient copied to clipboard

Support gqlgen marshalling

Open johnmaguire opened this issue 2 years ago • 5 comments

Is your feature request related to a problem? Please describe. Custom scalars require marshal and unmarshal functions to tell genqlient how they work.

I already have marshal and unmarshal functions written for gqlgen. I don't want to have to write them a second time or add a layer of indirection to support both gqlgen and genqlient.

Describe the solution you'd like I would love for genqlient to respect the interfaces prescribed by gqlgen - specifically looking for MarshalGQL / UnmarshalGQL on custom types and supporting the UnmarshalX(v interface{}) (X, error) / MarshalX(v X) graphql.Marshaler APIs.

Describe alternatives you've considered Currently, I need to write functions that satisfy both the gqlgen and genqlient interfaces, both of which call into generic functions. This is particularly annoying when dealing with scalar types built-in to gqlgen.

Additional context

  • https://gqlgen.com/reference/scalars/
  • https://github.com/99designs/gqlgen/blob/master/graphql/time.go

johnmaguire avatar Oct 27 '21 17:10 johnmaguire

Oh interesting idea! You can use UnmarshalX/MarshalX functions via genqlient's binding option, you'll just have to configure them manually. Looking for those automatically would be a neat idea, we'd have to add new code to use go/types to look at your source but I suspect that's going to be necessary sooner or later anyway.

benjaminjkraft avatar Oct 27 '21 22:10 benjaminjkraft

@benjaminjkraft I have a similar problem. I would like to use this type https://github.com/99designs/gqlgen/blob/master/graphql/upload.go but to be honest I don't know how to convert this for genqlient.

zreigz avatar Jul 13 '22 13:07 zreigz

To be more specific about the configuration, it looks like gqlgen uses a slightly different API for marshaling, but if you only need to unmarshal (i.e. the type is only used as an output), you can add to your config for example:

bindings:
  Time:
    type: github.com/99designs/gqlgen/graphql.Time
    unmarshaler: github.com/99designs/gqlgen/graphql.UnmarshalTime

If you want to marshal, you could define your own wrapper function matching genqlient's API, and use that. We could try supporting the gqlgen-style marshalers, perhaps as a different option gqlgenmarshaler: ..., if it's not too complex to add. (Pull requests welcome!)

But for Upload specifically, that won't help you: uploads are specially implemented in gqlgen and would need to be specially implemented in genqlient because they're not just a type we can unmarshal; they require the entire request to have a different structure. Issue #139 tracks implementing that (again PRs welcome; the issue has some details as to what the spec looks like and what the genqlient API might look like).

benjaminjkraft avatar Jul 13 '22 17:07 benjaminjkraft

@benjaminjkraft thanks a lot I will take a look

zreigz avatar Jul 13 '22 19:07 zreigz