c6d087c29b
## Summary:
One common use of fragment spreads is as the entirety of a field's
selection, e.g.
```graphql
query MyQuery {
myField {
...MyFragment
}
}
```
In this case, by default, genqlient generates a wrapper type
`MyQueryMyFieldMyType`, which just embeds `MyFragment`. This makes
sense if you later want to add more fields in addition to the fragment
spread. But if you don't -- and you did the fragment because you want
to share types, it's an extra layer of indirection. (Which becomes
especially onerous if `myField` has list type (`[MyType!]`), such that
it's not just an extra attribute-access to get to `MyFragment`.)
The new option `# @genqlient(flatten: true)` simplifies this situation:
if applied to `myField` is skips the wrapper type;
`MyQueryResponse.MyField` will simply have type `MyFragment` (or
`[]MyFragment`, or whatever). This should hopefully make the `typename`
option, which has more limitations, less necessary.
Note that in #30 the initial idea was to support this for fields as
well. This would require significant additional complexity in the
JSON-(un)marshaling code, and has proven less necessary, so I
implemented this option only for fragment-spreads for now. With that
restriction, it was shockingly simple; we have to hook into a bunch of
different places, but they're all quite simple, since the structure of
the Go types still matches the structure in GraphQL.
Issue: https://github.com/Khan/genqlient/issues/30
## Test plan:
make check
Author: benjaminjkraft
Reviewers: csilvers, dnerdy, aberkan, jvoll, mahtabsabet, MiguelCastillo, StevenACoffman
Required Reviewers:
Approved By: csilvers, dnerdy
Checks: ✅ Test (1.17), ✅ Test (1.16), ✅ Test (1.15), ✅ Test (1.14), ✅ Lint, ✅ Test (1.17), ✅ Test (1.16), ✅ Test (1.15), ✅ Test (1.14), ✅ Lint
Pull Request URL: https://github.com/Khan/genqlient/pull/121
49 lines
830 B
GraphQL
49 lines
830 B
GraphQL
scalar Date
|
|
|
|
type Query {
|
|
me: User
|
|
user(id: ID): User
|
|
being(id: ID!): Being
|
|
beings(ids: [ID!]!): [Being]!
|
|
lotteryWinner(number: Int!): Lucky
|
|
usersBornOn(date: Date!): [User!]!
|
|
usersBornOnDates(dates: [Date!]!): [User!]!
|
|
userSearch(birthdate: Date, id: ID): [User]
|
|
fail: Boolean
|
|
}
|
|
|
|
type User implements Being & Lucky {
|
|
id: ID!
|
|
name: String!
|
|
luckyNumber: Int
|
|
hair: Hair
|
|
birthdate: Date
|
|
friends: [User!]!
|
|
}
|
|
|
|
type Hair { color: String } # silly name to confuse the name-generator
|
|
|
|
type Animal implements Being {
|
|
id: ID!
|
|
name: String!
|
|
species: Species!
|
|
owner: Being
|
|
hair: BeingsHair
|
|
}
|
|
|
|
type BeingsHair { hasHair: Boolean! } # silly name to confuse the name-generator
|
|
|
|
enum Species {
|
|
DOG
|
|
COELACANTH
|
|
}
|
|
|
|
interface Being {
|
|
id: ID!
|
|
name: String!
|
|
}
|
|
|
|
interface Lucky {
|
|
luckyNumber: Int
|
|
}
|