Khan / genqlient

a truly type-safe Go GraphQL client
MIT License
1.03k stars 99 forks source link

Inline fragments not working with `use_struct_references: true` and `pointer: optional` #278

Open partounian opened 1 year ago

partounian commented 1 year ago

Describe the bug Seems like turning on use_struct_references and setting pointer: optional breaks the ability to read from inline fragments.

To Reproduce Problem happens at runtime. Setting use_struct_references: true and pointer: optional leads to the removal of the interface(?) that is supposed to be usable for grabbing data from inline fragments.

In the docs design.md, there is a block of code similar to

if pm, ok := transaction.PaymentMethod.GetDetails().(destination.ChargeCreditCardChargeCreditCardTransactionPayloadTransactionPaymentMethodDetails); ok {
}

While this code doesn't throw a compiler error with the default config, when you adjust the config vars mentioned above, doesn't seem like there is a way to get the inline fragment data. Messages similar to invalid operation: transaction.PaymentMethod.GetDetails() (value of type *destination.ChargeCreditCardChargeCreditCardTransactionPayloadTransactionPaymentMethodDetails) is not an interface pop up.

I am using this library to query/send mutations to Braintree. The reason I set the config vars above is primarily because Braintree's API doesn't handle Golang default values for Braintree's GraphQL inputs.

Here's what this mutation looks like:

mutation ChargeCreditCard(
  $input: ChargeCreditCardInput!) {
  chargeCreditCard(input: $input) {
    transaction {
      id
      legacyId
      status
      createdAt
      paymentMethod {
        id
        details {
          __typename
          ... on CreditCardDetails {
            cardholderName
            last4
            brandCode
            expirationMonth
            expirationYear
          }
        }
      }
    }
  }
}

Expected behavior Generating code in such a way that this behavior works. Unless I'm doing something incorrectly/sub-optimally?

genqlient version main

Additional context Add any other context about the problem here.

partounian commented 1 year ago

Is it possible to just apply the optional: pointer and/or the use_struct_references: true just for inputs, not outputs?

benjaminjkraft commented 5 months ago

Apologies for the delay in responding, this issue got buried. This may be useful input to how we tune these options (optional: pointer is probably the one at issue), but in the meantime you can deref the pointer and then type-assert.

partounian commented 5 months ago

Oh interesting, I didn't know that was possible. Thanks for the info!

partounian commented 5 months ago

I'll leave up to you to close if you desire :) @benjaminjkraft