teamwalnut / graphql-ppx

GraphQL language primitives for ReScript/ReasonML written in ReasonML
https://graphql-ppx.com
MIT License
258 stars 53 forks source link

Possible to omit optional fields from a @bsRecord? #137

Closed Phylodome closed 4 years ago

Phylodome commented 4 years ago

At the moment, trying to do something like the following:

type person = {
  email: string,
  ssn: option(string)
}

module GetPerson = [%graphql 
  {|
  query ($email: String!) {
    person(email: $email) @bsRecord { email }
  }  
|}
];

Produces the error: Some record fields are undefined: ssn.

I'd love to omit optional field names from queries but retain the capacity to parse responses to records wherein all unspecified record fields are mapped to None so long as they are optional in the associated type. The associated type would then, of course, require explicit specification.

Usage might look something like:

module GetPerson = [%graphql 
  {|
  query ($email: String!) {
    person(email: $email) @bsRecord(type: "person") { email }
  }  
|}
];

// Returns record of type `person`, like:
{
  email: "hello@email.com",
  ssn: None
}

And only sends a GraphQL query with the requested fields.

Would this be possible?

As one might imagine, the requirement that one include all record fields when using @bsRecord forces many other difficult constraints, such as:

If possible, the ability to decompose nested GraphQL queries directly to records, while taking the omission of a field as an implicit None within the return type, would dramatically improve the usability of this library by reducing the current workload associated w/ decomposing the Js.t response into records w/ the appropriate None-valued fields.

jfrolich commented 4 years ago

@bsRecord will be soft-deprecated as 1.0-beta generates record types automatically!

jfrolich commented 4 years ago

I think btw something like this is possible with @bsDecoder

Phylodome commented 4 years ago

@jfrolich Thanks for your quick reply!

Taking your comments in reverse order:

I think btw something like this is possible with @bsDecoder

Yes, I can presently use @bsDecoder for this provided I'm not trying to do so with a non-scalar value, as this results in an error regarding mandatory inclusion of sub-fields. Unfortunately, essentially all my types reference other types, as I'm working w/ a graph database as the primary store, and in most cases non-scalars comprise part of the field set I wish to omit.

@bsRecord will be soft-deprecated as 1.0-beta generates record types automatically!

Very cool that 1.0 will auto-generate record types! I looked over the documentation on the 1.0 branch, and am still wondering how I'll use this improved library to solve my specific use case (with the caveat that the purpose of this library is not, of course, to solve my specific problems).

This is because, as I understand it, a divergent set of queries will generate a divergent set of types, and I'd ideally like to use this tool to produce a result in which regardless of query diversity, all queries convergently project upon a user-defined set of record types. As far as I can tell, and perhaps I am misunderstanding the new documentation, this would still appear to involve an intermediate step of mapping the record types produced by queries into my fixed set of fundamental entity types.

I would be very happy if I'd misunderstood the capabilities of 1.0, so if I have, I'd be grateful if you could help me understand how the above might be possible using this tool.

jfrolich commented 4 years ago

It's possible now with recursive modules and ppxCustom. Still have to write the documentation, but if you have questions you can DM me on the discord.