Add support for binding with a custom marshal/unmarshal function (#104)
## Summary: This is useful if you want to bind to a type you don't control (or use for other things) but need different serialization than its default. This is a feature gqlgen has and we've found it very useful. For example, in webapp we want to bind `DateTime` to `time.Time`, but its default serialization is not compatible with Python, so currently we have to bind to a wrapper type and cast all over the place, which is exactly the sort of boilerplate genqlient is supposed to avoid. For unmarshaling, the implementation basically just follows the existing support for abstract types; instead of calling our own generated helper, we now call your specified function. This required some refactoring to abstract the handling of custom unmarshalers generally from abstract types specifically, and to wire in not only the unmarshaler-name but also the `generator` (in order to compute the right import alias). For marshaling, I had to implement all that stuff over again; it's mostly parallel to unmarshaling (and I made a few minor changes to unmarshaling to make the two more parallel). Luckily, after #103 I at least only had to do it once, rather than implementing the same functionality for arguments and for input-type fields. It was still quite a bit of code; I didn't try to be quite as completionist about the tests as with unmarshal but still had to add a few. Issue: https://github.com/Khan/genqlient/issues/38 ## Test plan: make check Author: benjaminjkraft Reviewers: StevenACoffman, dnerdy, benjaminjkraft, aberkan, jvoll, mahtabsabet, MiguelCastillo Required Reviewers: Approved By: StevenACoffman, 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/104
This commit is contained in:
@@ -6,8 +6,10 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
"github.com/Khan/genqlient/internal/testutil"
|
||||
)
|
||||
|
||||
// AnimalFields includes the GraphQL fields of Animal requested by the fragment AnimalFields.
|
||||
@@ -19,6 +21,10 @@ type AnimalFields struct {
|
||||
|
||||
func (v *AnimalFields) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*AnimalFields
|
||||
Owner json.RawMessage `json:"owner"`
|
||||
@@ -32,10 +38,10 @@ func (v *AnimalFields) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Owner
|
||||
raw := firstPass.Owner
|
||||
dst := &v.Owner
|
||||
src := firstPass.Owner
|
||||
err = __unmarshalAnimalFieldsOwnerBeing(
|
||||
target, raw)
|
||||
src, dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Unable to unmarshal AnimalFields.Owner: %w", err)
|
||||
@@ -84,15 +90,15 @@ func (v *AnimalFieldsOwnerAnimal) GetTypename() string { return v.Typename }
|
||||
// GetId is a part of, and documented with, the interface AnimalFieldsOwnerBeing.
|
||||
func (v *AnimalFieldsOwnerAnimal) GetId() string { return v.Id }
|
||||
|
||||
func __unmarshalAnimalFieldsOwnerBeing(v *AnimalFieldsOwnerBeing, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
func __unmarshalAnimalFieldsOwnerBeing(b []byte, v *AnimalFieldsOwnerBeing) error {
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
err := json.Unmarshal(b, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -100,10 +106,10 @@ func __unmarshalAnimalFieldsOwnerBeing(v *AnimalFieldsOwnerBeing, m json.RawMess
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(AnimalFieldsOwnerUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "Animal":
|
||||
*v = new(AnimalFieldsOwnerAnimal)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "":
|
||||
return fmt.Errorf(
|
||||
"Response was missing Being.__typename")
|
||||
@@ -123,6 +129,10 @@ type AnimalFieldsOwnerUser struct {
|
||||
|
||||
func (v *AnimalFieldsOwnerUser) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*AnimalFieldsOwnerUser
|
||||
graphql.NoUnmarshalJSON
|
||||
@@ -162,15 +172,15 @@ func (v *LuckyFieldsUser) implementsGraphQLInterfaceLuckyFields() {}
|
||||
// GetLuckyNumber is a part of, and documented with, the interface LuckyFields.
|
||||
func (v *LuckyFieldsUser) GetLuckyNumber() int { return v.LuckyNumber }
|
||||
|
||||
func __unmarshalLuckyFields(v *LuckyFields, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
func __unmarshalLuckyFields(b []byte, v *LuckyFields) error {
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
err := json.Unmarshal(b, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -178,7 +188,7 @@ func __unmarshalLuckyFields(v *LuckyFields, m json.RawMessage) error {
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(LuckyFieldsUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "":
|
||||
return fmt.Errorf(
|
||||
"Response was missing Lucky.__typename")
|
||||
@@ -196,6 +206,10 @@ type LuckyFieldsUser struct {
|
||||
|
||||
func (v *LuckyFieldsUser) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*LuckyFieldsUser
|
||||
graphql.NoUnmarshalJSON
|
||||
@@ -242,6 +256,10 @@ type UserFields struct {
|
||||
|
||||
func (v *UserFields) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*UserFields
|
||||
graphql.NoUnmarshalJSON
|
||||
@@ -266,6 +284,72 @@ func (v *UserFields) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// __queryWithCustomMarshalInput is used internally by genqlient
|
||||
type __queryWithCustomMarshalInput struct {
|
||||
Date time.Time `json:"-"`
|
||||
}
|
||||
|
||||
func (v *__queryWithCustomMarshalInput) MarshalJSON() ([]byte, error) {
|
||||
|
||||
var fullObject struct {
|
||||
*__queryWithCustomMarshalInput
|
||||
Date json.RawMessage `json:"date"`
|
||||
graphql.NoMarshalJSON
|
||||
}
|
||||
fullObject.__queryWithCustomMarshalInput = v
|
||||
|
||||
{
|
||||
|
||||
dst := &fullObject.Date
|
||||
src := v.Date
|
||||
var err error
|
||||
*dst, err = testutil.MarshalDate(
|
||||
&src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"Unable to marshal __queryWithCustomMarshalInput.Date: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return json.Marshal(&fullObject)
|
||||
}
|
||||
|
||||
// __queryWithCustomMarshalSliceInput is used internally by genqlient
|
||||
type __queryWithCustomMarshalSliceInput struct {
|
||||
Dates []time.Time `json:"-"`
|
||||
}
|
||||
|
||||
func (v *__queryWithCustomMarshalSliceInput) MarshalJSON() ([]byte, error) {
|
||||
|
||||
var fullObject struct {
|
||||
*__queryWithCustomMarshalSliceInput
|
||||
Dates []json.RawMessage `json:"dates"`
|
||||
graphql.NoMarshalJSON
|
||||
}
|
||||
fullObject.__queryWithCustomMarshalSliceInput = v
|
||||
|
||||
{
|
||||
|
||||
dst := &fullObject.Dates
|
||||
src := v.Dates
|
||||
*dst = make(
|
||||
[]json.RawMessage,
|
||||
len(src))
|
||||
for i, src := range src {
|
||||
dst := &(*dst)[i]
|
||||
var err error
|
||||
*dst, err = testutil.MarshalDate(
|
||||
&src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"Unable to marshal __queryWithCustomMarshalSliceInput.Dates: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json.Marshal(&fullObject)
|
||||
}
|
||||
|
||||
// __queryWithFragmentsInput is used internally by genqlient
|
||||
type __queryWithFragmentsInput struct {
|
||||
Ids []string `json:"ids"`
|
||||
@@ -312,6 +396,92 @@ type failingQueryResponse struct {
|
||||
Me failingQueryMeUser `json:"me"`
|
||||
}
|
||||
|
||||
// queryWithCustomMarshalResponse is returned by queryWithCustomMarshal on success.
|
||||
type queryWithCustomMarshalResponse struct {
|
||||
UsersBornOn []queryWithCustomMarshalUsersBornOnUser `json:"usersBornOn"`
|
||||
}
|
||||
|
||||
// queryWithCustomMarshalSliceResponse is returned by queryWithCustomMarshalSlice on success.
|
||||
type queryWithCustomMarshalSliceResponse struct {
|
||||
UsersBornOnDates []queryWithCustomMarshalSliceUsersBornOnDatesUser `json:"usersBornOnDates"`
|
||||
}
|
||||
|
||||
// queryWithCustomMarshalSliceUsersBornOnDatesUser includes the requested fields of the GraphQL type User.
|
||||
type queryWithCustomMarshalSliceUsersBornOnDatesUser struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Birthdate time.Time `json:"-"`
|
||||
}
|
||||
|
||||
func (v *queryWithCustomMarshalSliceUsersBornOnDatesUser) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithCustomMarshalSliceUsersBornOnDatesUser
|
||||
Birthdate json.RawMessage `json:"birthdate"`
|
||||
graphql.NoUnmarshalJSON
|
||||
}
|
||||
firstPass.queryWithCustomMarshalSliceUsersBornOnDatesUser = v
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{
|
||||
dst := &v.Birthdate
|
||||
src := firstPass.Birthdate
|
||||
err = testutil.UnmarshalDate(
|
||||
src, dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Unable to unmarshal queryWithCustomMarshalSliceUsersBornOnDatesUser.Birthdate: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryWithCustomMarshalUsersBornOnUser includes the requested fields of the GraphQL type User.
|
||||
type queryWithCustomMarshalUsersBornOnUser struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Birthdate time.Time `json:"-"`
|
||||
}
|
||||
|
||||
func (v *queryWithCustomMarshalUsersBornOnUser) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithCustomMarshalUsersBornOnUser
|
||||
Birthdate json.RawMessage `json:"birthdate"`
|
||||
graphql.NoUnmarshalJSON
|
||||
}
|
||||
firstPass.queryWithCustomMarshalUsersBornOnUser = v
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{
|
||||
dst := &v.Birthdate
|
||||
src := firstPass.Birthdate
|
||||
err = testutil.UnmarshalDate(
|
||||
src, dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Unable to unmarshal queryWithCustomMarshalUsersBornOnUser.Birthdate: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryWithFragmentsBeingsAnimal includes the requested fields of the GraphQL type Animal.
|
||||
type queryWithFragmentsBeingsAnimal struct {
|
||||
Typename string `json:"__typename"`
|
||||
@@ -324,6 +494,10 @@ type queryWithFragmentsBeingsAnimal struct {
|
||||
|
||||
func (v *queryWithFragmentsBeingsAnimal) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithFragmentsBeingsAnimal
|
||||
Owner json.RawMessage `json:"owner"`
|
||||
@@ -337,10 +511,10 @@ func (v *queryWithFragmentsBeingsAnimal) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Owner
|
||||
raw := firstPass.Owner
|
||||
dst := &v.Owner
|
||||
src := firstPass.Owner
|
||||
err = __unmarshalqueryWithFragmentsBeingsAnimalOwnerBeing(
|
||||
target, raw)
|
||||
src, dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Unable to unmarshal queryWithFragmentsBeingsAnimal.Owner: %w", err)
|
||||
@@ -400,15 +574,15 @@ func (v *queryWithFragmentsBeingsAnimalOwnerAnimal) GetId() string { return v.Id
|
||||
// GetName is a part of, and documented with, the interface queryWithFragmentsBeingsAnimalOwnerBeing.
|
||||
func (v *queryWithFragmentsBeingsAnimalOwnerAnimal) GetName() string { return v.Name }
|
||||
|
||||
func __unmarshalqueryWithFragmentsBeingsAnimalOwnerBeing(v *queryWithFragmentsBeingsAnimalOwnerBeing, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
func __unmarshalqueryWithFragmentsBeingsAnimalOwnerBeing(b []byte, v *queryWithFragmentsBeingsAnimalOwnerBeing) error {
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
err := json.Unmarshal(b, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -416,10 +590,10 @@ func __unmarshalqueryWithFragmentsBeingsAnimalOwnerBeing(v *queryWithFragmentsBe
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(queryWithFragmentsBeingsAnimalOwnerUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "Animal":
|
||||
*v = new(queryWithFragmentsBeingsAnimalOwnerAnimal)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "":
|
||||
return fmt.Errorf(
|
||||
"Response was missing Being.__typename")
|
||||
@@ -474,15 +648,15 @@ func (v *queryWithFragmentsBeingsAnimal) GetId() string { return v.Id }
|
||||
// GetName is a part of, and documented with, the interface queryWithFragmentsBeingsBeing.
|
||||
func (v *queryWithFragmentsBeingsAnimal) GetName() string { return v.Name }
|
||||
|
||||
func __unmarshalqueryWithFragmentsBeingsBeing(v *queryWithFragmentsBeingsBeing, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
func __unmarshalqueryWithFragmentsBeingsBeing(b []byte, v *queryWithFragmentsBeingsBeing) error {
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
err := json.Unmarshal(b, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -490,10 +664,10 @@ func __unmarshalqueryWithFragmentsBeingsBeing(v *queryWithFragmentsBeingsBeing,
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(queryWithFragmentsBeingsUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "Animal":
|
||||
*v = new(queryWithFragmentsBeingsAnimal)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "":
|
||||
return fmt.Errorf(
|
||||
"Response was missing Being.__typename")
|
||||
@@ -524,6 +698,10 @@ type queryWithFragmentsResponse struct {
|
||||
|
||||
func (v *queryWithFragmentsResponse) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithFragmentsResponse
|
||||
Beings []json.RawMessage `json:"beings"`
|
||||
@@ -537,15 +715,15 @@ func (v *queryWithFragmentsResponse) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Beings
|
||||
raw := firstPass.Beings
|
||||
*target = make(
|
||||
dst := &v.Beings
|
||||
src := firstPass.Beings
|
||||
*dst = make(
|
||||
[]queryWithFragmentsBeingsBeing,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
len(src))
|
||||
for i, src := range src {
|
||||
dst := &(*dst)[i]
|
||||
err = __unmarshalqueryWithFragmentsBeingsBeing(
|
||||
target, raw)
|
||||
src, dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Unable to unmarshal queryWithFragmentsResponse.Beings: %w", err)
|
||||
@@ -601,15 +779,15 @@ func (v *queryWithInterfaceListFieldBeingsAnimal) GetId() string { return v.Id }
|
||||
// GetName is a part of, and documented with, the interface queryWithInterfaceListFieldBeingsBeing.
|
||||
func (v *queryWithInterfaceListFieldBeingsAnimal) GetName() string { return v.Name }
|
||||
|
||||
func __unmarshalqueryWithInterfaceListFieldBeingsBeing(v *queryWithInterfaceListFieldBeingsBeing, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
func __unmarshalqueryWithInterfaceListFieldBeingsBeing(b []byte, v *queryWithInterfaceListFieldBeingsBeing) error {
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
err := json.Unmarshal(b, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -617,10 +795,10 @@ func __unmarshalqueryWithInterfaceListFieldBeingsBeing(v *queryWithInterfaceList
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(queryWithInterfaceListFieldBeingsUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "Animal":
|
||||
*v = new(queryWithInterfaceListFieldBeingsAnimal)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "":
|
||||
return fmt.Errorf(
|
||||
"Response was missing Being.__typename")
|
||||
@@ -644,6 +822,10 @@ type queryWithInterfaceListFieldResponse struct {
|
||||
|
||||
func (v *queryWithInterfaceListFieldResponse) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithInterfaceListFieldResponse
|
||||
Beings []json.RawMessage `json:"beings"`
|
||||
@@ -657,15 +839,15 @@ func (v *queryWithInterfaceListFieldResponse) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Beings
|
||||
raw := firstPass.Beings
|
||||
*target = make(
|
||||
dst := &v.Beings
|
||||
src := firstPass.Beings
|
||||
*dst = make(
|
||||
[]queryWithInterfaceListFieldBeingsBeing,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
len(src))
|
||||
for i, src := range src {
|
||||
dst := &(*dst)[i]
|
||||
err = __unmarshalqueryWithInterfaceListFieldBeingsBeing(
|
||||
target, raw)
|
||||
src, dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Unable to unmarshal queryWithInterfaceListFieldResponse.Beings: %w", err)
|
||||
@@ -721,15 +903,15 @@ func (v *queryWithInterfaceListPointerFieldBeingsAnimal) GetId() string { return
|
||||
// GetName is a part of, and documented with, the interface queryWithInterfaceListPointerFieldBeingsBeing.
|
||||
func (v *queryWithInterfaceListPointerFieldBeingsAnimal) GetName() string { return v.Name }
|
||||
|
||||
func __unmarshalqueryWithInterfaceListPointerFieldBeingsBeing(v *queryWithInterfaceListPointerFieldBeingsBeing, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
func __unmarshalqueryWithInterfaceListPointerFieldBeingsBeing(b []byte, v *queryWithInterfaceListPointerFieldBeingsBeing) error {
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
err := json.Unmarshal(b, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -737,10 +919,10 @@ func __unmarshalqueryWithInterfaceListPointerFieldBeingsBeing(v *queryWithInterf
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(queryWithInterfaceListPointerFieldBeingsUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "Animal":
|
||||
*v = new(queryWithInterfaceListPointerFieldBeingsAnimal)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "":
|
||||
return fmt.Errorf(
|
||||
"Response was missing Being.__typename")
|
||||
@@ -764,6 +946,10 @@ type queryWithInterfaceListPointerFieldResponse struct {
|
||||
|
||||
func (v *queryWithInterfaceListPointerFieldResponse) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithInterfaceListPointerFieldResponse
|
||||
Beings []json.RawMessage `json:"beings"`
|
||||
@@ -777,16 +963,16 @@ func (v *queryWithInterfaceListPointerFieldResponse) UnmarshalJSON(b []byte) err
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Beings
|
||||
raw := firstPass.Beings
|
||||
*target = make(
|
||||
dst := &v.Beings
|
||||
src := firstPass.Beings
|
||||
*dst = make(
|
||||
[]*queryWithInterfaceListPointerFieldBeingsBeing,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
*target = new(queryWithInterfaceListPointerFieldBeingsBeing)
|
||||
len(src))
|
||||
for i, src := range src {
|
||||
dst := &(*dst)[i]
|
||||
*dst = new(queryWithInterfaceListPointerFieldBeingsBeing)
|
||||
err = __unmarshalqueryWithInterfaceListPointerFieldBeingsBeing(
|
||||
*target, raw)
|
||||
src, *dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Unable to unmarshal queryWithInterfaceListPointerFieldResponse.Beings: %w", err)
|
||||
@@ -835,15 +1021,15 @@ func (v *queryWithInterfaceNoFragmentsBeingAnimal) GetId() string { return v.Id
|
||||
// GetName is a part of, and documented with, the interface queryWithInterfaceNoFragmentsBeing.
|
||||
func (v *queryWithInterfaceNoFragmentsBeingAnimal) GetName() string { return v.Name }
|
||||
|
||||
func __unmarshalqueryWithInterfaceNoFragmentsBeing(v *queryWithInterfaceNoFragmentsBeing, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
func __unmarshalqueryWithInterfaceNoFragmentsBeing(b []byte, v *queryWithInterfaceNoFragmentsBeing) error {
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
err := json.Unmarshal(b, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -851,10 +1037,10 @@ func __unmarshalqueryWithInterfaceNoFragmentsBeing(v *queryWithInterfaceNoFragme
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(queryWithInterfaceNoFragmentsBeingUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "Animal":
|
||||
*v = new(queryWithInterfaceNoFragmentsBeingAnimal)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "":
|
||||
return fmt.Errorf(
|
||||
"Response was missing Being.__typename")
|
||||
@@ -892,6 +1078,10 @@ type queryWithInterfaceNoFragmentsResponse struct {
|
||||
|
||||
func (v *queryWithInterfaceNoFragmentsResponse) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithInterfaceNoFragmentsResponse
|
||||
Being json.RawMessage `json:"being"`
|
||||
@@ -905,10 +1095,10 @@ func (v *queryWithInterfaceNoFragmentsResponse) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Being
|
||||
raw := firstPass.Being
|
||||
dst := &v.Being
|
||||
src := firstPass.Being
|
||||
err = __unmarshalqueryWithInterfaceNoFragmentsBeing(
|
||||
target, raw)
|
||||
src, dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Unable to unmarshal queryWithInterfaceNoFragmentsResponse.Being: %w", err)
|
||||
@@ -926,6 +1116,10 @@ type queryWithNamedFragmentsBeingsAnimal struct {
|
||||
|
||||
func (v *queryWithNamedFragmentsBeingsAnimal) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithNamedFragmentsBeingsAnimal
|
||||
graphql.NoUnmarshalJSON
|
||||
@@ -976,15 +1170,15 @@ func (v *queryWithNamedFragmentsBeingsAnimal) GetTypename() string { return v.Ty
|
||||
// GetId is a part of, and documented with, the interface queryWithNamedFragmentsBeingsBeing.
|
||||
func (v *queryWithNamedFragmentsBeingsAnimal) GetId() string { return v.Id }
|
||||
|
||||
func __unmarshalqueryWithNamedFragmentsBeingsBeing(v *queryWithNamedFragmentsBeingsBeing, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
func __unmarshalqueryWithNamedFragmentsBeingsBeing(b []byte, v *queryWithNamedFragmentsBeingsBeing) error {
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
err := json.Unmarshal(b, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -992,10 +1186,10 @@ func __unmarshalqueryWithNamedFragmentsBeingsBeing(v *queryWithNamedFragmentsBei
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(queryWithNamedFragmentsBeingsUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "Animal":
|
||||
*v = new(queryWithNamedFragmentsBeingsAnimal)
|
||||
return json.Unmarshal(m, *v)
|
||||
return json.Unmarshal(b, *v)
|
||||
case "":
|
||||
return fmt.Errorf(
|
||||
"Response was missing Being.__typename")
|
||||
@@ -1014,6 +1208,10 @@ type queryWithNamedFragmentsBeingsUser struct {
|
||||
|
||||
func (v *queryWithNamedFragmentsBeingsUser) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithNamedFragmentsBeingsUser
|
||||
graphql.NoUnmarshalJSON
|
||||
@@ -1040,6 +1238,10 @@ type queryWithNamedFragmentsResponse struct {
|
||||
|
||||
func (v *queryWithNamedFragmentsResponse) UnmarshalJSON(b []byte) error {
|
||||
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithNamedFragmentsResponse
|
||||
Beings []json.RawMessage `json:"beings"`
|
||||
@@ -1053,15 +1255,15 @@ func (v *queryWithNamedFragmentsResponse) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Beings
|
||||
raw := firstPass.Beings
|
||||
*target = make(
|
||||
dst := &v.Beings
|
||||
src := firstPass.Beings
|
||||
*dst = make(
|
||||
[]queryWithNamedFragmentsBeingsBeing,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
len(src))
|
||||
for i, src := range src {
|
||||
dst := &(*dst)[i]
|
||||
err = __unmarshalqueryWithNamedFragmentsBeingsBeing(
|
||||
target, raw)
|
||||
src, dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Unable to unmarshal queryWithNamedFragmentsResponse.Beings: %w", err)
|
||||
@@ -1214,6 +1416,64 @@ query queryWithOmitempty ($id: ID) {
|
||||
return &retval, err
|
||||
}
|
||||
|
||||
func queryWithCustomMarshal(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
date time.Time,
|
||||
) (*queryWithCustomMarshalResponse, error) {
|
||||
__input := __queryWithCustomMarshalInput{
|
||||
Date: date,
|
||||
}
|
||||
var err error
|
||||
|
||||
var retval queryWithCustomMarshalResponse
|
||||
err = client.MakeRequest(
|
||||
ctx,
|
||||
"queryWithCustomMarshal",
|
||||
`
|
||||
query queryWithCustomMarshal ($date: Date!) {
|
||||
usersBornOn(date: $date) {
|
||||
id
|
||||
name
|
||||
birthdate
|
||||
}
|
||||
}
|
||||
`,
|
||||
&retval,
|
||||
&__input,
|
||||
)
|
||||
return &retval, err
|
||||
}
|
||||
|
||||
func queryWithCustomMarshalSlice(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
dates []time.Time,
|
||||
) (*queryWithCustomMarshalSliceResponse, error) {
|
||||
__input := __queryWithCustomMarshalSliceInput{
|
||||
Dates: dates,
|
||||
}
|
||||
var err error
|
||||
|
||||
var retval queryWithCustomMarshalSliceResponse
|
||||
err = client.MakeRequest(
|
||||
ctx,
|
||||
"queryWithCustomMarshalSlice",
|
||||
`
|
||||
query queryWithCustomMarshalSlice ($dates: [Date!]!) {
|
||||
usersBornOnDates(dates: $dates) {
|
||||
id
|
||||
name
|
||||
birthdate
|
||||
}
|
||||
}
|
||||
`,
|
||||
&retval,
|
||||
&__input,
|
||||
)
|
||||
return &retval, err
|
||||
}
|
||||
|
||||
func queryWithInterfaceNoFragments(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
|
||||
@@ -3,3 +3,8 @@ operations:
|
||||
- "*_test.go"
|
||||
generated: generated.go
|
||||
allow_broken_features: true
|
||||
bindings:
|
||||
Date:
|
||||
type: time.Time
|
||||
marshaler: "github.com/Khan/genqlient/internal/testutil.MarshalDate"
|
||||
unmarshaler: "github.com/Khan/genqlient/internal/testutil.UnmarshalDate"
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -116,6 +117,64 @@ func TestOmitempty(t *testing.T) {
|
||||
assert.Equal(t, 17, resp.User.LuckyNumber)
|
||||
}
|
||||
|
||||
func TestCustomMarshal(t *testing.T) {
|
||||
_ = `# @genqlient
|
||||
query queryWithCustomMarshal($date: Date!) {
|
||||
usersBornOn(date: $date) { id name birthdate }
|
||||
}`
|
||||
|
||||
ctx := context.Background()
|
||||
server := server.RunServer()
|
||||
defer server.Close()
|
||||
client := graphql.NewClient(server.URL, http.DefaultClient)
|
||||
|
||||
resp, err := queryWithCustomMarshal(ctx, client,
|
||||
time.Date(2025, time.January, 1, 12, 34, 56, 789, time.UTC))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Len(t, resp.UsersBornOn, 1)
|
||||
user := resp.UsersBornOn[0]
|
||||
assert.Equal(t, "1", user.Id)
|
||||
assert.Equal(t, "Yours Truly", user.Name)
|
||||
assert.Equal(t,
|
||||
time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
user.Birthdate)
|
||||
|
||||
resp, err = queryWithCustomMarshal(ctx, client,
|
||||
time.Date(2021, time.January, 1, 12, 34, 56, 789, time.UTC))
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, resp.UsersBornOn, 0)
|
||||
}
|
||||
|
||||
func TestCustomMarshalSlice(t *testing.T) {
|
||||
_ = `# @genqlient
|
||||
query queryWithCustomMarshalSlice($dates: [Date!]!) {
|
||||
usersBornOnDates(dates: $dates) { id name birthdate }
|
||||
}`
|
||||
|
||||
ctx := context.Background()
|
||||
server := server.RunServer()
|
||||
defer server.Close()
|
||||
client := graphql.NewClient(server.URL, http.DefaultClient)
|
||||
|
||||
resp, err := queryWithCustomMarshalSlice(ctx, client,
|
||||
[]time.Time{time.Date(2025, time.January, 1, 12, 34, 56, 789, time.UTC)})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Len(t, resp.UsersBornOnDates, 1)
|
||||
user := resp.UsersBornOnDates[0]
|
||||
assert.Equal(t, "1", user.Id)
|
||||
assert.Equal(t, "Yours Truly", user.Name)
|
||||
assert.Equal(t,
|
||||
time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
user.Birthdate)
|
||||
|
||||
resp, err = queryWithCustomMarshalSlice(ctx, client,
|
||||
[]time.Time{time.Date(2021, time.January, 1, 12, 34, 56, 789, time.UTC)})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, resp.UsersBornOnDates, 0)
|
||||
}
|
||||
|
||||
func TestInterfaceNoFragments(t *testing.T) {
|
||||
_ = `# @genqlient
|
||||
query queryWithInterfaceNoFragments($id: ID!) {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
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!]!
|
||||
fail: Boolean
|
||||
}
|
||||
|
||||
@@ -12,6 +16,7 @@ type User implements Being & Lucky {
|
||||
name: String!
|
||||
luckyNumber: Int
|
||||
hair: Hair
|
||||
birthdate: Date
|
||||
}
|
||||
|
||||
type Hair { color: String } # silly name to confuse the name-generator
|
||||
|
||||
@@ -59,15 +59,18 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Query struct {
|
||||
Being func(childComplexity int, id string) int
|
||||
Beings func(childComplexity int, ids []string) int
|
||||
Fail func(childComplexity int) int
|
||||
LotteryWinner func(childComplexity int, number int) int
|
||||
Me func(childComplexity int) int
|
||||
User func(childComplexity int, id *string) int
|
||||
Being func(childComplexity int, id string) int
|
||||
Beings func(childComplexity int, ids []string) int
|
||||
Fail func(childComplexity int) int
|
||||
LotteryWinner func(childComplexity int, number int) int
|
||||
Me func(childComplexity int) int
|
||||
User func(childComplexity int, id *string) int
|
||||
UsersBornOn func(childComplexity int, date string) int
|
||||
UsersBornOnDates func(childComplexity int, dates []string) int
|
||||
}
|
||||
|
||||
User struct {
|
||||
Birthdate func(childComplexity int) int
|
||||
Hair func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
LuckyNumber func(childComplexity int) int
|
||||
@@ -81,6 +84,8 @@ type QueryResolver interface {
|
||||
Being(ctx context.Context, id string) (Being, error)
|
||||
Beings(ctx context.Context, ids []string) ([]Being, error)
|
||||
LotteryWinner(ctx context.Context, number int) (Lucky, error)
|
||||
UsersBornOn(ctx context.Context, date string) ([]*User, error)
|
||||
UsersBornOnDates(ctx context.Context, dates []string) ([]*User, error)
|
||||
Fail(ctx context.Context) (*bool, error)
|
||||
}
|
||||
|
||||
@@ -210,6 +215,37 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Query.User(childComplexity, args["id"].(*string)), true
|
||||
|
||||
case "Query.usersBornOn":
|
||||
if e.complexity.Query.UsersBornOn == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Query_usersBornOn_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Query.UsersBornOn(childComplexity, args["date"].(string)), true
|
||||
|
||||
case "Query.usersBornOnDates":
|
||||
if e.complexity.Query.UsersBornOnDates == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Query_usersBornOnDates_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Query.UsersBornOnDates(childComplexity, args["dates"].([]string)), true
|
||||
|
||||
case "User.birthdate":
|
||||
if e.complexity.User.Birthdate == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.User.Birthdate(childComplexity), true
|
||||
|
||||
case "User.hair":
|
||||
if e.complexity.User.Hair == nil {
|
||||
break
|
||||
@@ -288,12 +324,16 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er
|
||||
}
|
||||
|
||||
var sources = []*ast.Source{
|
||||
{Name: "../schema.graphql", Input: `type Query {
|
||||
{Name: "../schema.graphql", Input: `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!]!
|
||||
fail: Boolean
|
||||
}
|
||||
|
||||
@@ -302,6 +342,7 @@ type User implements Being & Lucky {
|
||||
name: String!
|
||||
luckyNumber: Int
|
||||
hair: Hair
|
||||
birthdate: Date
|
||||
}
|
||||
|
||||
type Hair { color: String } # silly name to confuse the name-generator
|
||||
@@ -412,6 +453,36 @@ func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs m
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Query_usersBornOnDates_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
var arg0 []string
|
||||
if tmp, ok := rawArgs["dates"]; ok {
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("dates"))
|
||||
arg0, err = ec.unmarshalNDate2ᚕstringᚄ(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args["dates"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Query_usersBornOn_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
var arg0 string
|
||||
if tmp, ok := rawArgs["date"]; ok {
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("date"))
|
||||
arg0, err = ec.unmarshalNDate2string(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args["date"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
@@ -877,6 +948,90 @@ func (ec *executionContext) _Query_lotteryWinner(ctx context.Context, field grap
|
||||
return ec.marshalOLucky2githubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐLucky(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_usersBornOn(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Query",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.field_Query_usersBornOn_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
fc.Args = args
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Query().UsersBornOn(rctx, args["date"].(string))
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]*User)
|
||||
fc.Result = res
|
||||
return ec.marshalNUser2ᚕᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUserᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_usersBornOnDates(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Query",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.field_Query_usersBornOnDates_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
fc.Args = args
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Query().UsersBornOnDates(rctx, args["dates"].([]string))
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]*User)
|
||||
fc.Result = res
|
||||
return ec.marshalNUser2ᚕᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUserᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_fail(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -1114,6 +1269,38 @@ func (ec *executionContext) _User_hair(ctx context.Context, field graphql.Collec
|
||||
return ec.marshalOHair2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐHair(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _User_birthdate(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "User",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Birthdate, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalODate2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -2413,6 +2600,34 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||
res = ec._Query_lotteryWinner(ctx, field)
|
||||
return res
|
||||
})
|
||||
case "usersBornOn":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Query_usersBornOn(ctx, field)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
return res
|
||||
})
|
||||
case "usersBornOnDates":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Query_usersBornOnDates(ctx, field)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
return res
|
||||
})
|
||||
case "fail":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
@@ -2464,6 +2679,8 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj
|
||||
out.Values[i] = ec._User_luckyNumber(ctx, field, obj)
|
||||
case "hair":
|
||||
out.Values[i] = ec._User_hair(ctx, field, obj)
|
||||
case "birthdate":
|
||||
out.Values[i] = ec._User_birthdate(ctx, field, obj)
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
@@ -2772,6 +2989,51 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNDate2string(ctx context.Context, v interface{}) (string, error) {
|
||||
res, err := graphql.UnmarshalString(v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNDate2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {
|
||||
res := graphql.MarshalString(v)
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNDate2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {
|
||||
var vSlice []interface{}
|
||||
if v != nil {
|
||||
if tmp1, ok := v.([]interface{}); ok {
|
||||
vSlice = tmp1
|
||||
} else {
|
||||
vSlice = []interface{}{v}
|
||||
}
|
||||
}
|
||||
var err error
|
||||
res := make([]string, len(vSlice))
|
||||
for i := range vSlice {
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i))
|
||||
res[i], err = ec.unmarshalNDate2string(ctx, vSlice[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNDate2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
for i := range v {
|
||||
ret[i] = ec.marshalNDate2string(ctx, sel, v[i])
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) {
|
||||
res, err := graphql.UnmarshalID(v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
@@ -2857,6 +3119,53 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNUser2ᚕᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUserᚄ(ctx context.Context, sel ast.SelectionSet, v []*User) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
var wg sync.WaitGroup
|
||||
isLen1 := len(v) == 1
|
||||
if !isLen1 {
|
||||
wg.Add(len(v))
|
||||
}
|
||||
for i := range v {
|
||||
i := i
|
||||
fc := &graphql.FieldContext{
|
||||
Index: &i,
|
||||
Result: &v[i],
|
||||
}
|
||||
ctx := graphql.WithFieldContext(ctx, fc)
|
||||
f := func(i int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
if !isLen1 {
|
||||
defer wg.Done()
|
||||
}
|
||||
ret[i] = ec.marshalNUser2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUser(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
} else {
|
||||
go f(i)
|
||||
}
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNUser2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUser(ctx context.Context, sel ast.SelectionSet, v *User) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._User(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {
|
||||
return ec.___Directive(ctx, sel, &v)
|
||||
}
|
||||
@@ -3124,6 +3433,21 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast
|
||||
return graphql.MarshalBoolean(*v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalODate2ᚖstring(ctx context.Context, v interface{}) (*string, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
res, err := graphql.UnmarshalString(v)
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalODate2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
return graphql.MarshalString(*v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOHair2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐHair(ctx context.Context, sel ast.SelectionSet, v *Hair) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
|
||||
@@ -35,10 +35,11 @@ type Hair struct {
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
LuckyNumber *int `json:"luckyNumber"`
|
||||
Hair *Hair `json:"hair"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
LuckyNumber *int `json:"luckyNumber"`
|
||||
Hair *Hair `json:"hair"`
|
||||
Birthdate *string `json:"birthdate"`
|
||||
}
|
||||
|
||||
func (User) IsBeing() {}
|
||||
|
||||
@@ -15,7 +15,8 @@ func intptr(v int) *int { return &v }
|
||||
var users = []*User{
|
||||
{
|
||||
ID: "1", Name: "Yours Truly", LuckyNumber: intptr(17),
|
||||
Hair: &Hair{Color: strptr("Black")},
|
||||
Birthdate: strptr("2025-01-01"),
|
||||
Hair: &Hair{Color: strptr("Black")},
|
||||
},
|
||||
{ID: "2", Name: "Raven", LuckyNumber: intptr(-1), Hair: nil},
|
||||
}
|
||||
@@ -40,6 +41,18 @@ func userByID(id string) *User {
|
||||
return nil
|
||||
}
|
||||
|
||||
func usersByBirthdates(dates []string) []*User {
|
||||
var retval []*User
|
||||
for _, date := range dates {
|
||||
for _, user := range users {
|
||||
if user.Birthdate != nil && *user.Birthdate == date {
|
||||
retval = append(retval, user)
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval
|
||||
}
|
||||
|
||||
func beingByID(id string) Being {
|
||||
for _, user := range users {
|
||||
if id == user.ID {
|
||||
@@ -86,6 +99,14 @@ func (r *queryResolver) LotteryWinner(ctx context.Context, number int) (Lucky, e
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) UsersBornOn(ctx context.Context, date string) ([]*User, error) {
|
||||
return usersByBirthdates([]string{date}), nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) UsersBornOnDates(ctx context.Context, dates []string) ([]*User, error) {
|
||||
return usersByBirthdates(dates), nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) Fail(ctx context.Context) (*bool, error) {
|
||||
f := true
|
||||
return &f, fmt.Errorf("oh no")
|
||||
|
||||
@@ -2,6 +2,7 @@ package testutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
)
|
||||
@@ -26,3 +27,20 @@ type MyContext interface {
|
||||
func GetClientFromNowhere() (graphql.Client, error) { return nil, nil }
|
||||
func GetClientFromContext(ctx context.Context) (graphql.Client, error) { return nil, nil }
|
||||
func GetClientFromMyContext(ctx MyContext) (graphql.Client, error) { return nil, nil }
|
||||
|
||||
const dateFormat = "2006-01-02"
|
||||
|
||||
func MarshalDate(t *time.Time) ([]byte, error) {
|
||||
return []byte(`"` + t.Format(dateFormat) + `"`), nil
|
||||
}
|
||||
|
||||
func UnmarshalDate(b []byte, t *time.Time) error {
|
||||
// (modified from time.Time.UnmarshalJSON)
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
*t, err = time.Parse(`"`+dateFormat+`"`, string(b))
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user