GraphQLSwift / Graphiti

The Swift GraphQL Schema framework for macOS and Linux
MIT License
532 stars 67 forks source link

Drops Encodable requirement on GraphQL types #129

Closed NeedleInAJayStack closed 11 months ago

NeedleInAJayStack commented 11 months ago

This drops unnecessary Codable conformance from GraphQL-injected types. More specifically, output types are never encoded or decoded - only the resulting leaf Scalars are encoded. While this PR removes the restriction that all output types are codable, it still requires Encodability on Scalars and Decodability on Arguments. Decodable conformance is technically removed from Input objects, but typically still enforced through the decodable Argument requirement.

This change is useful if you have a complex, non-codable type that you would like to pass through resolver chains.

NeedleInAJayStack commented 11 months ago

Changing to draft. It turns out that the Encodable conformance was the only thing differentiating SyncResolve and SimpleAsyncResolve. Without it, resolvers that return futures match both signatures, meaning that the Field init is ambiguous.

cshadek commented 11 months ago

Would this make connections of interfaces/unions possible?

NeedleInAJayStack commented 11 months ago

Would this make connections of interfaces/unions possible?

I don't think so. I think that's more a limitation in how the GraphQL type system is implemented than a Swift codability restriction.

cshadek commented 11 months ago

My understanding is the only reason connections of interfaces/ unions doesn't work is that node needs to be encodable. I've created custom connections where the a swift protocol is the node.

paulofaria commented 11 months ago

@NeedleInAJayStack have you tried @_disfavoredOverload?

NeedleInAJayStack commented 11 months ago

@NeedleInAJayStack have you tried @_disfavoredOverload?

@paulofaria OMG, you're a genius! I had no idea that existed and it totally fixed the problem. Thanks!

NeedleInAJayStack commented 11 months ago

My understanding is the only reason connections of interfaces/ unions doesn't work is that node needs to be encodable. I've created custom connections where the a swift protocol is the node.

@cshadek Oh okay! Yeah, if that's the case, then this probably will fix it!

NeedleInAJayStack commented 11 months ago

This is super awesome! I'm just curious as to why a type would not be able to conform to Codable. 😄

😆 It's a good question... My primary use case is that I have an object with a property that contains existentials, which makes it pretty hard to decode without a huge typeswitch. I don't really want to expose this property in GraphQL, but I do want to expose things derived from it. For example:

struct A {
  let b: [any B] // Not exposed in GraphQL, but important to keep around.
  var bDescription: String { // Exposed in GraphQL
    return b.map { $0.description }
  }
}
paulofaria commented 11 months ago

Gotcha, makes sense! Just out of curiosity, 😄. Are you using an existential because the array is not homogeneous so generics wouldn't work?

NeedleInAJayStack commented 11 months ago

Yeah, exactly. It's a heterogeneous array.