diff --git a/_examples/chat/chat_test.go b/_examples/chat/chat_test.go index 6f546dc0f6..0217ee7466 100644 --- a/_examples/chat/chat_test.go +++ b/_examples/chat/chat_test.go @@ -2,13 +2,14 @@ package chat import ( "fmt" + "runtime" + "sync" + "testing" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "runtime" - "sync" - "testing" ) func TestChatSubscriptions(t *testing.T) { @@ -68,7 +69,8 @@ func TestChatSubscriptions(t *testing.T) { } wg.Wait() - // 1 for the main thread, 1 for the testing package and remainder is reserved for the HTTP server threads + // 1 for the main thread, 1 for the testing package and remainder is reserved for the HTTP + // server threads // TODO: use something like runtime.Stack to filter out HTTP server threads, // TODO: which is required for proper concurrency and leaks testing require.Less(t, runtime.NumGoroutine(), 1+1+batchSize*2, "goroutine leak") diff --git a/_examples/chat/resolvers.go b/_examples/chat/resolvers.go index f466fb299e..872427a1aa 100644 --- a/_examples/chat/resolvers.go +++ b/_examples/chat/resolvers.go @@ -62,7 +62,12 @@ type Chatroom struct { type mutationResolver struct{ *resolver } -func (r *mutationResolver) Post(ctx context.Context, text string, username string, roomName string) (*Message, error) { +func (r *mutationResolver) Post( + ctx context.Context, + text string, + username string, + roomName string, +) (*Message, error) { room := r.getRoom(roomName) message := &Message{ @@ -99,7 +104,10 @@ func (r *queryResolver) Room(ctx context.Context, name string) (*Chatroom, error type subscriptionResolver struct{ *resolver } -func (r *subscriptionResolver) MessageAdded(ctx context.Context, roomName string) (<-chan *Message, error) { +func (r *subscriptionResolver) MessageAdded( + ctx context.Context, + roomName string, +) (<-chan *Message, error) { room := r.getRoom(roomName) id := randString(8) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index fcdb18dc7c..c2ba146edf 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -34,5 +34,7 @@ func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } // Query returns QueryResolver implementation. func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } -type mutationResolver struct{ *Resolver } -type queryResolver struct{ *Resolver } +type ( + mutationResolver struct{ *Resolver } + queryResolver struct{ *Resolver } +) diff --git a/_examples/dataloader/dataloader_test.go b/_examples/dataloader/dataloader_test.go index c70b45b95a..bf04e9c127 100644 --- a/_examples/dataloader/dataloader_test.go +++ b/_examples/dataloader/dataloader_test.go @@ -10,7 +10,11 @@ import ( ) func TestTodo(t *testing.T) { - c := client.New(LoaderMiddleware(handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: &Resolver{}})))) + c := client.New( + LoaderMiddleware( + handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: &Resolver{}})), + ), + ) t.Run("create a new todo", func(t *testing.T) { var resp interface{} @@ -44,7 +48,8 @@ func TestTodo(t *testing.T) { }, resp.Torture2d) }) - // Input coercion on arrays should convert non array values into an array of the appropriate depth + // Input coercion on arrays should convert non array values into an array of the appropriate + // depth // http://facebook.github.io/graphql/June2018/#sec-Type-System.List t.Run("array coercion", func(t *testing.T) { t.Run("1d", func(t *testing.T) { @@ -82,6 +87,10 @@ func TestTodo(t *testing.T) { } err := c.Post(`{ torture2d(customerIds:{}) { id name } }`, &resp) - require.EqualError(t, err, "[{\"message\":\"map[string]interface {} is not an int\",\"path\":[\"torture2d\",\"customerIds\",0,0]}]") + require.EqualError( + t, + err, + "[{\"message\":\"map[string]interface {} is not an int\",\"path\":[\"torture2d\",\"customerIds\",0,0]}]", + ) }) } diff --git a/_examples/dataloader/dataloaders.go b/_examples/dataloader/dataloaders.go index f8c27569ba..abc80f733f 100644 --- a/_examples/dataloader/dataloaders.go +++ b/_examples/dataloader/dataloaders.go @@ -48,7 +48,10 @@ func LoaderMiddleware(next http.Handler) http.Handler { addresses := make([]*Address, len(keys)) errors := make([]error, len(keys)) for i, key := range keys { - addresses[i] = &Address{Street: "home street", Country: "hometon " + strconv.Itoa(key)} + addresses[i] = &Address{ + Street: "home street", + Country: "hometon " + strconv.Itoa(key), + } } return addresses, errors }, @@ -64,7 +67,10 @@ func LoaderMiddleware(next http.Handler) http.Handler { keySql = append(keySql, strconv.Itoa(key)) } - fmt.Printf("SELECT * FROM orders WHERE customer_id IN (%s)\n", strings.Join(keySql, ",")) + fmt.Printf( + "SELECT * FROM orders WHERE customer_id IN (%s)\n", + strings.Join(keySql, ","), + ) time.Sleep(5 * time.Millisecond) orders := make([][]*Order, len(keys)) @@ -72,8 +78,16 @@ func LoaderMiddleware(next http.Handler) http.Handler { for i, key := range keys { id := 10 + rand.Int()%3 orders[i] = []*Order{ - {ID: id, Amount: rand.Float64(), Date: time.Now().Add(-time.Duration(key) * time.Hour)}, - {ID: id + 1, Amount: rand.Float64(), Date: time.Now().Add(-time.Duration(key) * time.Hour)}, + { + ID: id, + Amount: rand.Float64(), + Date: time.Now().Add(-time.Duration(key) * time.Hour), + }, + { + ID: id + 1, + Amount: rand.Float64(), + Date: time.Now().Add(-time.Duration(key) * time.Hour), + }, } // if you had another customer loader you would prime its cache here @@ -94,7 +108,10 @@ func LoaderMiddleware(next http.Handler) http.Handler { keySql = append(keySql, strconv.Itoa(key)) } - fmt.Printf("SELECT * FROM items JOIN item_order WHERE item_order.order_id IN (%s)\n", strings.Join(keySql, ",")) + fmt.Printf( + "SELECT * FROM items JOIN item_order WHERE item_order.order_id IN (%s)\n", + strings.Join(keySql, ","), + ) time.Sleep(5 * time.Millisecond) items := make([][]*Item, len(keys)) diff --git a/_examples/dataloader/resolvers.go b/_examples/dataloader/resolvers.go index 759f88c114..10515a21c0 100644 --- a/_examples/dataloader/resolvers.go +++ b/_examples/dataloader/resolvers.go @@ -82,7 +82,11 @@ func (r *queryResolver) Torture2d(ctx context.Context, customerIds [][]int) ([][ for i := range customerIds { inner := make([]*Customer, len(customerIds[i])) for j := range customerIds[i] { - inner[j] = &Customer{ID: customerIds[i][j], Name: fmt.Sprintf("%d %d", i, j), AddressID: rand.Int() % 10} + inner[j] = &Customer{ + ID: customerIds[i][j], + Name: fmt.Sprintf("%d %d", i, j), + AddressID: rand.Int() % 10, + } } result[i] = inner } diff --git a/_examples/embedding/subdir/embedding_test.go b/_examples/embedding/subdir/embedding_test.go index d779455236..9783593cd4 100644 --- a/_examples/embedding/subdir/embedding_test.go +++ b/_examples/embedding/subdir/embedding_test.go @@ -29,7 +29,11 @@ func TestEmbeddingWorks(t *testing.T) { } func TestEmbeddingWorksInGendir(t *testing.T) { - c := client.New(handler.NewDefaultServer(gendir.NewExecutableSchema(gendir.Config{Resolvers: &GendirResolver{}}))) + c := client.New( + handler.NewDefaultServer( + gendir.NewExecutableSchema(gendir.Config{Resolvers: &GendirResolver{}}), + ), + ) var resp struct { InSchemadir string Parentdir string diff --git a/_examples/embedding/subdir/resolvers.go b/_examples/embedding/subdir/resolvers.go index dfd2c8acbe..188272975a 100644 --- a/_examples/embedding/subdir/resolvers.go +++ b/_examples/embedding/subdir/resolvers.go @@ -14,12 +14,15 @@ type Resolver struct{ *Resolver } func (q *Resolver) Query() QueryResolver { return q } + func (q *Resolver) InSchemadir(ctx context.Context) (string, error) { return "example", nil } + func (q *Resolver) Parentdir(ctx context.Context) (string, error) { return "example", nil } + func (q *Resolver) Subdir(ctx context.Context) (string, error) { return "example", nil } diff --git a/_examples/federation/accounts/server.go b/_examples/federation/accounts/server.go index dbbc5070de..4fe6b8349e 100644 --- a/_examples/federation/accounts/server.go +++ b/_examples/federation/accounts/server.go @@ -21,7 +21,9 @@ func main() { port = defaultPort } - srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}})) + srv := handler.NewDefaultServer( + generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}}), + ) srv.Use(&debug.Tracer{}) http.Handle("/", playground.Handler("GraphQL playground", "/query")) diff --git a/_examples/federation/products/server.go b/_examples/federation/products/server.go index df80eceab1..51bbe858e4 100644 --- a/_examples/federation/products/server.go +++ b/_examples/federation/products/server.go @@ -21,7 +21,9 @@ func main() { port = defaultPort } - srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}})) + srv := handler.NewDefaultServer( + generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}}), + ) srv.Use(&debug.Tracer{}) http.Handle("/", playground.Handler("GraphQL playground", "/query")) diff --git a/_examples/federation/reviews/server.go b/_examples/federation/reviews/server.go index 2403d23ea5..c4d6beeb09 100644 --- a/_examples/federation/reviews/server.go +++ b/_examples/federation/reviews/server.go @@ -21,7 +21,9 @@ func main() { port = defaultPort } - srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}})) + srv := handler.NewDefaultServer( + generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}}), + ) srv.Use(&debug.Tracer{}) http.Handle("/", playground.Handler("GraphQL playground", "/query")) diff --git a/_examples/fileupload/fileupload_test.go b/_examples/fileupload/fileupload_test.go index 29ef9dc3fb..e860b029f5 100644 --- a/_examples/fileupload/fileupload_test.go +++ b/_examples/fileupload/fileupload_test.go @@ -18,7 +18,9 @@ import ( func TestFileUpload(t *testing.T) { resolver := &Stub{} - srv := httptest.NewServer(handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver}))) + srv := httptest.NewServer( + handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver})), + ) defer srv.Close() gql := gqlclient.New(srv.Config.Handler, gqlclient.Path("/graphql")) @@ -98,7 +100,12 @@ func TestFileUpload(t *testing.T) { SingleUploadWithPayload *model.File } - err := gql.Post(mutation, &result, gqlclient.Var("req", map[string]interface{}{"id": 1, "file": aTxtFile}), gqlclient.WithFiles()) + err := gql.Post( + mutation, + &result, + gqlclient.Var("req", map[string]interface{}{"id": 1, "file": aTxtFile}), + gqlclient.WithFiles(), + ) require.Nil(t, err) require.Equal(t, 1, result.SingleUploadWithPayload.ID) require.Contains(t, result.SingleUploadWithPayload.Name, "a.txt") @@ -139,7 +146,12 @@ func TestFileUpload(t *testing.T) { MultipleUpload []*model.File } - err := gql.Post(mutation, &result, gqlclient.Var("files", []*os.File{a1TxtFile, b1TxtFile}), gqlclient.WithFiles()) + err := gql.Post( + mutation, + &result, + gqlclient.Var("files", []*os.File{a1TxtFile, b1TxtFile}), + gqlclient.WithFiles(), + ) require.Nil(t, err) require.Equal(t, 1, result.MultipleUpload[0].ID) require.Equal(t, 2, result.MultipleUpload[1].ID) @@ -274,11 +286,19 @@ func TestFileUpload(t *testing.T) { require.Equal(t, 1, result.MultipleUploadWithPayload[0].ID) require.Contains(t, result.MultipleUploadWithPayload[0].Name, "a.txt") require.Equal(t, "test1", result.MultipleUploadWithPayload[0].Content) - require.Equal(t, "text/plain; charset=utf-8", result.MultipleUploadWithPayload[0].ContentType) + require.Equal( + t, + "text/plain; charset=utf-8", + result.MultipleUploadWithPayload[0].ContentType, + ) require.Equal(t, 2, result.MultipleUploadWithPayload[1].ID) require.Contains(t, result.MultipleUploadWithPayload[1].Name, "a.txt") require.Equal(t, "test1", result.MultipleUploadWithPayload[1].Content) - require.Equal(t, "text/plain; charset=utf-8", result.MultipleUploadWithPayload[1].ContentType) + require.Equal( + t, + "text/plain; charset=utf-8", + result.MultipleUploadWithPayload[1].ContentType, + ) } t.Run("payload smaller than UploadMaxMemory, stored in memory", func(t *testing.T) { diff --git a/_examples/fileupload/server/server.go b/_examples/fileupload/server/server.go index 75a47b73b6..8b55acfe49 100644 --- a/_examples/fileupload/server/server.go +++ b/_examples/fileupload/server/server.go @@ -24,7 +24,9 @@ func main() { var mb int64 = 1 << 20 - srv := handler.NewDefaultServer(fileupload.NewExecutableSchema(fileupload.Config{Resolvers: resolver})) + srv := handler.NewDefaultServer( + fileupload.NewExecutableSchema(fileupload.Config{Resolvers: resolver}), + ) srv.AddTransport(transport.POST{}) srv.AddTransport(transport.MultipartForm{ MaxMemory: 32 * mb, diff --git a/_examples/go.mod b/_examples/go.mod index 5f87adc514..a0debb38d1 100644 --- a/_examples/go.mod +++ b/_examples/go.mod @@ -23,6 +23,6 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect - golang.org/x/text v0.3.7 + golang.org/x/text v0.3.8 sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 // indirect ) diff --git a/_examples/go.sum b/_examples/go.sum index 58cd0bb709..d57ef21925 100644 --- a/_examples/go.sum +++ b/_examples/go.sum @@ -133,8 +133,9 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= diff --git a/_examples/scalars/model/model.go b/_examples/scalars/model/model.go index f9d239deac..2535d99705 100644 --- a/_examples/scalars/model/model.go +++ b/_examples/scalars/model/model.go @@ -80,7 +80,8 @@ func (p Point) MarshalGQL(w io.Writer) { fmt.Fprintf(w, `"%d,%d"`, p.X, p.Y) } -// if the type referenced in .gqlgen.yml is a function that returns a marshaller we can use it to encode and decode +// if the type referenced in .gqlgen.yml is a function that returns a marshaller we can use it to +// encode and decode // onto any existing go type. func MarshalTimestamp(t time.Time) graphql.Marshaler { return graphql.WriterFunc(func(w io.Writer) { @@ -88,7 +89,8 @@ func MarshalTimestamp(t time.Time) graphql.Marshaler { }) } -// Unmarshal{Typename} is only required if the scalar appears as an input. The raw values have already been decoded +// Unmarshal{Typename} is only required if the scalar appears as an input. The raw values have +// already been decoded // from json into int/float64/bool/nil/map[string]interface/[]interface func UnmarshalTimestamp(v interface{}) (time.Time, error) { if tmpStr, ok := v.(int64); ok { @@ -120,7 +122,8 @@ type SearchArgs struct { IsBanned Banned } -// A custom enum that uses integers to represent the values in memory but serialize as string for graphql +// A custom enum that uses integers to represent the values in memory but serialize as string for +// graphql type Tier uint const ( diff --git a/_examples/scalars/resolvers.go b/_examples/scalars/resolvers.go index ad9be003b1..de3d6161ce 100644 --- a/_examples/scalars/resolvers.go +++ b/_examples/scalars/resolvers.go @@ -23,7 +23,11 @@ func (r *Resolver) User() UserResolver { type queryResolver struct{ *Resolver } -func (r *queryResolver) UserByTier(ctx context.Context, tier model.Tier, darkMode *model.Prefs) ([]*model.User, error) { +func (r *queryResolver) UserByTier( + ctx context.Context, + tier model.Tier, + darkMode *model.Prefs, +) ([]*model.User, error) { panic("implement me") } @@ -37,7 +41,10 @@ func (r *queryResolver) User(ctx context.Context, id external.ObjectID) (*model. }, nil } -func (r *queryResolver) Search(ctx context.Context, input *model.SearchArgs) ([]*model.User, error) { +func (r *queryResolver) Search( + ctx context.Context, + input *model.SearchArgs, +) ([]*model.User, error) { location := model.Point{X: 1, Y: 2} if input.Location != nil { location = *input.Location diff --git a/_examples/scalars/scalar_test.go b/_examples/scalars/scalar_test.go index f9ca2b1dd1..0766919cbd 100644 --- a/_examples/scalars/scalar_test.go +++ b/_examples/scalars/scalar_test.go @@ -59,7 +59,11 @@ func TestScalars(t *testing.T) { var resp struct{ Search []RawUser } err := c.Post(`{ search(input:{createdAfter:"2014"}) { id } }`, &resp) - require.EqualError(t, err, `[{"message":"time should be a unix timestamp","path":["search","input","createdAfter"]}]`) + require.EqualError( + t, + err, + `[{"message":"time should be a unix timestamp","path":["search","input","createdAfter"]}]`, + ) }) t.Run("scalar resolver methods", func(t *testing.T) { diff --git a/_examples/scalars/server/server.go b/_examples/scalars/server/server.go index 4c2cf7c12a..52e6882b2b 100644 --- a/_examples/scalars/server/server.go +++ b/_examples/scalars/server/server.go @@ -11,7 +11,12 @@ import ( func main() { http.Handle("/", playground.Handler("Starwars", "/query")) - http.Handle("/query", handler.NewDefaultServer(scalars.NewExecutableSchema(scalars.Config{Resolvers: &scalars.Resolver{}}))) + http.Handle( + "/query", + handler.NewDefaultServer( + scalars.NewExecutableSchema(scalars.Config{Resolvers: &scalars.Resolver{}}), + ), + ) log.Fatal(http.ListenAndServe(":8084", nil)) } diff --git a/_examples/selection/server/server.go b/_examples/selection/server/server.go index 3cf77711e3..fd5b1810b5 100644 --- a/_examples/selection/server/server.go +++ b/_examples/selection/server/server.go @@ -11,6 +11,11 @@ import ( func main() { http.Handle("/", playground.Handler("Selection Demo", "/query")) - http.Handle("/query", handler.NewDefaultServer(selection.NewExecutableSchema(selection.Config{Resolvers: &selection.Resolver{}}))) + http.Handle( + "/query", + handler.NewDefaultServer( + selection.NewExecutableSchema(selection.Config{Resolvers: &selection.Resolver{}}), + ), + ) log.Fatal(http.ListenAndServe(":8086", nil)) } diff --git a/_examples/starwars/models/model.go b/_examples/starwars/models/model.go index 3729753b15..4077d574a2 100644 --- a/_examples/starwars/models/model.go +++ b/_examples/starwars/models/model.go @@ -13,9 +13,10 @@ type CharacterFields struct { AppearsIn []Episode } -func (cf CharacterFields) GetID() string { return cf.ID } -func (cf CharacterFields) GetName() string { return cf.Name } -func (cf CharacterFields) GetAppearsIn() []Episode { return cf.AppearsIn } +func (cf CharacterFields) GetID() string { return cf.ID } +func (cf CharacterFields) GetName() string { return cf.Name } +func (cf CharacterFields) GetAppearsIn() []Episode { return cf.AppearsIn } + func (cf CharacterFields) GetFriendsConnection() *FriendsConnection { return nil } // Handled in resolver func (cf CharacterFields) GetFriends() []Character { return nil } // Handled in resolver diff --git a/_examples/starwars/resolvers.go b/_examples/starwars/resolvers.go index e7b9629d12..471dbe5161 100644 --- a/_examples/starwars/resolvers.go +++ b/_examples/starwars/resolvers.go @@ -47,7 +47,10 @@ func (r *Resolver) Starship() generated.StarshipResolver { return &starshipResolver{r} } -func (r *Resolver) resolveCharacters(ctx context.Context, ids []string) ([]models.Character, error) { +func (r *Resolver) resolveCharacters( + ctx context.Context, + ids []string, +) ([]models.Character, error) { result := make([]models.Character, len(ids)) for i, id := range ids { char, err := r.Query().Character(ctx, id) @@ -61,17 +64,30 @@ func (r *Resolver) resolveCharacters(ctx context.Context, ids []string) ([]model type droidResolver struct{ *Resolver } -func (r *droidResolver) Friends(ctx context.Context, obj *models.Droid) ([]models.Character, error) { +func (r *droidResolver) Friends( + ctx context.Context, + obj *models.Droid, +) ([]models.Character, error) { return r.resolveCharacters(ctx, obj.FriendIds) } -func (r *droidResolver) FriendsConnection(ctx context.Context, obj *models.Droid, first *int, after *string) (*models.FriendsConnection, error) { +func (r *droidResolver) FriendsConnection( + ctx context.Context, + obj *models.Droid, + first *int, + after *string, +) (*models.FriendsConnection, error) { return r.resolveFriendConnection(ctx, obj.FriendIds, first, after) } type friendsConnectionResolver struct{ *Resolver } -func (r *Resolver) resolveFriendConnection(_ context.Context, ids []string, first *int, after *string) (*models.FriendsConnection, error) { +func (r *Resolver) resolveFriendConnection( + _ context.Context, + ids []string, + first *int, + after *string, +) (*models.FriendsConnection, error) { from := 0 if after != nil { b, err := base64.StdEncoding.DecodeString(*after) @@ -100,7 +116,10 @@ func (r *Resolver) resolveFriendConnection(_ context.Context, ids []string, firs }, nil } -func (r *friendsConnectionResolver) Edges(ctx context.Context, obj *models.FriendsConnection) ([]*models.FriendsEdge, error) { +func (r *friendsConnectionResolver) Edges( + ctx context.Context, + obj *models.FriendsConnection, +) ([]*models.FriendsEdge, error) { friends, err := r.resolveCharacters(ctx, obj.Ids) if err != nil { return nil, err @@ -116,21 +135,35 @@ func (r *friendsConnectionResolver) Edges(ctx context.Context, obj *models.Frien return edges, nil } -func (r *friendsConnectionResolver) Friends(ctx context.Context, obj *models.FriendsConnection) ([]models.Character, error) { +func (r *friendsConnectionResolver) Friends( + ctx context.Context, + obj *models.FriendsConnection, +) ([]models.Character, error) { return r.resolveCharacters(ctx, obj.Ids) } type humanResolver struct{ *Resolver } -func (r *humanResolver) Friends(ctx context.Context, obj *models.Human) ([]models.Character, error) { +func (r *humanResolver) Friends( + ctx context.Context, + obj *models.Human, +) ([]models.Character, error) { return r.resolveCharacters(ctx, obj.FriendIds) } -func (r *humanResolver) FriendsConnection(ctx context.Context, obj *models.Human, first *int, after *string) (*models.FriendsConnection, error) { +func (r *humanResolver) FriendsConnection( + ctx context.Context, + obj *models.Human, + first *int, + after *string, +) (*models.FriendsConnection, error) { return r.resolveFriendConnection(ctx, obj.FriendIds, first, after) } -func (r *humanResolver) Starships(ctx context.Context, obj *models.Human) ([]*models.Starship, error) { +func (r *humanResolver) Starships( + ctx context.Context, + obj *models.Human, +) ([]*models.Starship, error) { var result []*models.Starship for _, id := range obj.StarshipIds { char, err := r.Query().Starship(ctx, id) @@ -146,7 +179,11 @@ func (r *humanResolver) Starships(ctx context.Context, obj *models.Human) ([]*mo type mutationResolver struct{ *Resolver } -func (r *mutationResolver) CreateReview(ctx context.Context, episode models.Episode, review models.Review) (*models.Review, error) { +func (r *mutationResolver) CreateReview( + ctx context.Context, + episode models.Episode, + review models.Review, +) (*models.Review, error) { review.Time = time.Now() time.Sleep(1 * time.Second) r.reviews[episode] = append(r.reviews[episode], &review) @@ -155,14 +192,21 @@ func (r *mutationResolver) CreateReview(ctx context.Context, episode models.Epis type queryResolver struct{ *Resolver } -func (r *queryResolver) Hero(ctx context.Context, episode *models.Episode) (models.Character, error) { +func (r *queryResolver) Hero( + ctx context.Context, + episode *models.Episode, +) (models.Character, error) { if *episode == models.EpisodeEmpire { return r.humans["1000"], nil } return r.droid["2001"], nil } -func (r *queryResolver) Reviews(ctx context.Context, episode models.Episode, since *time.Time) ([]*models.Review, error) { +func (r *queryResolver) Reviews( + ctx context.Context, + episode models.Episode, + since *time.Time, +) ([]*models.Review, error) { if since == nil { return r.reviews[episode], nil } @@ -229,7 +273,11 @@ func (r *queryResolver) Starship(ctx context.Context, id string) (*models.Starsh type starshipResolver struct{ *Resolver } -func (r *starshipResolver) Length(ctx context.Context, obj *models.Starship, unit *models.LengthUnit) (float64, error) { +func (r *starshipResolver) Length( + ctx context.Context, + obj *models.Starship, + unit *models.LengthUnit, +) (float64, error) { switch *unit { case models.LengthUnitMeter, "": return obj.Length, nil @@ -248,7 +296,11 @@ func NewResolver() generated.Config { ID: "1000", Name: "Luke Skywalker", FriendIds: []string{"1002", "1003", "2000", "2001"}, - AppearsIn: []models.Episode{models.EpisodeNewhope, models.EpisodeEmpire, models.EpisodeJedi}, + AppearsIn: []models.Episode{ + models.EpisodeNewhope, + models.EpisodeEmpire, + models.EpisodeJedi, + }, }, HeightMeters: 1.72, Mass: 77, @@ -259,7 +311,11 @@ func NewResolver() generated.Config { ID: "1001", Name: "Darth Vader", FriendIds: []string{"1004"}, - AppearsIn: []models.Episode{models.EpisodeNewhope, models.EpisodeEmpire, models.EpisodeJedi}, + AppearsIn: []models.Episode{ + models.EpisodeNewhope, + models.EpisodeEmpire, + models.EpisodeJedi, + }, }, HeightMeters: 2.02, Mass: 136, @@ -270,7 +326,11 @@ func NewResolver() generated.Config { ID: "1002", Name: "Han Solo", FriendIds: []string{"1000", "1003", "2001"}, - AppearsIn: []models.Episode{models.EpisodeNewhope, models.EpisodeEmpire, models.EpisodeJedi}, + AppearsIn: []models.Episode{ + models.EpisodeNewhope, + models.EpisodeEmpire, + models.EpisodeJedi, + }, }, HeightMeters: 1.8, Mass: 80, @@ -281,7 +341,11 @@ func NewResolver() generated.Config { ID: "1003", Name: "Leia Organa", FriendIds: []string{"1000", "1002", "2000", "2001"}, - AppearsIn: []models.Episode{models.EpisodeNewhope, models.EpisodeEmpire, models.EpisodeJedi}, + AppearsIn: []models.Episode{ + models.EpisodeNewhope, + models.EpisodeEmpire, + models.EpisodeJedi, + }, }, HeightMeters: 1.5, Mass: 49, @@ -304,7 +368,11 @@ func NewResolver() generated.Config { ID: "2000", Name: "C-3PO", FriendIds: []string{"1000", "1002", "1003", "2001"}, - AppearsIn: []models.Episode{models.EpisodeNewhope, models.EpisodeEmpire, models.EpisodeJedi}, + AppearsIn: []models.Episode{ + models.EpisodeNewhope, + models.EpisodeEmpire, + models.EpisodeJedi, + }, }, PrimaryFunction: "Protocol", }, @@ -313,7 +381,11 @@ func NewResolver() generated.Config { ID: "2001", Name: "R2-D2", FriendIds: []string{"1000", "1002", "1003"}, - AppearsIn: []models.Episode{models.EpisodeNewhope, models.EpisodeEmpire, models.EpisodeJedi}, + AppearsIn: []models.Episode{ + models.EpisodeNewhope, + models.EpisodeEmpire, + models.EpisodeJedi, + }, }, PrimaryFunction: "Astromech", }, diff --git a/_examples/starwars/starwars_test.go b/_examples/starwars/starwars_test.go index 8cbe861b0c..a0896bb419 100644 --- a/_examples/starwars/starwars_test.go +++ b/_examples/starwars/starwars_test.go @@ -137,7 +137,10 @@ func TestStarwars(t *testing.T) { } } } - c.MustPost(`{ droid(id:"2001") { friendsConnection { edges { cursor, node { name } } } } }`, &resp) + c.MustPost( + `{ droid(id:"2001") { friendsConnection { edges { cursor, node { name } } } } }`, + &resp, + ) require.Equal(t, "Y3Vyc29yMQ==", resp.Droid.FriendsConnection.Edges[0].Cursor) require.Equal(t, "Luke Skywalker", resp.Droid.FriendsConnection.Edges[0].Node.Name) @@ -214,7 +217,11 @@ func TestStarwars(t *testing.T) { } }`, &resp, client.Var("episode", "INVALID")) - require.EqualError(t, err, `http 422: {"errors":[{"message":"INVALID is not a valid Episode","path":["variable","episode"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`) + require.EqualError( + t, + err, + `http 422: {"errors":[{"message":"INVALID is not a valid Episode","path":["variable","episode"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + ) }) t.Run("introspection", func(t *testing.T) { diff --git a/_examples/todo/todo.go b/_examples/todo/todo.go index 479b144399..32e6a1a114 100644 --- a/_examples/todo/todo.go +++ b/_examples/todo/todo.go @@ -123,7 +123,11 @@ func (r *MutationResolver) CreateTodo(ctx context.Context, todo TodoInput) (*Tod return newTodo, nil } -func (r *MutationResolver) UpdateTodo(ctx context.Context, id int, changes map[string]interface{}) (*Todo, error) { +func (r *MutationResolver) UpdateTodo( + ctx context.Context, + id int, + changes map[string]interface{}, +) (*Todo, error) { var affectedTodo *Todo for i := 0; i < len(r.todos); i++ { diff --git a/_examples/todo/todo_test.go b/_examples/todo/todo_test.go index 7423580f8c..3cfe79cd20 100644 --- a/_examples/todo/todo_test.go +++ b/_examples/todo/todo_test.go @@ -60,7 +60,10 @@ func TestTodo(t *testing.T) { Done bool } } - c.MustPost(`mutation @user(id:2){ updateTodo(id: 3, changes:{done:true}) { text, done } }`, &resp) + c.MustPost( + `mutation @user(id:2){ updateTodo(id: 3, changes:{done:true}) { text, done } }`, + &resp, + ) require.Equal(t, "Somebody else's todo", resp.UpdateTodo.Text) }) @@ -72,7 +75,10 @@ func TestTodo(t *testing.T) { Done bool } } - c.MustPost(`mutation { updateTodo(id: 3, changes:{done:true})@user(id:2) { text, done } }`, &resp) + c.MustPost( + `mutation { updateTodo(id: 3, changes:{done:true})@user(id:2) { text, done } }`, + &resp, + ) require.Equal(t, "Somebody else's todo", resp.UpdateTodo.Text) }) @@ -85,7 +91,11 @@ func TestTodo(t *testing.T) { } } err := c.Post(`mutation { updateTodo(id: 3, changes:{done:true}) { text, done } }`, &resp) - require.EqualError(t, err, "[{\"message\":\"you dont own that\",\"path\":[\"updateTodo\",\"done\"]}]") + require.EqualError( + t, + err, + "[{\"message\":\"you dont own that\",\"path\":[\"updateTodo\",\"done\"]}]", + ) require.Nil(t, resp.UpdateTodo) }) @@ -173,7 +183,10 @@ func TestTodo(t *testing.T) { var resp struct { CreateTodo struct{ Text string } } - c.MustPost(`mutation { createTodo(todo:{text:"Completed todo", done: null}) { text } }`, &resp) + c.MustPost( + `mutation { createTodo(todo:{text:"Completed todo", done: null}) { text } }`, + &resp, + ) require.Equal(t, "Completed todo", resp.CreateTodo.Text) }) @@ -272,7 +285,10 @@ func TestSkipAndIncludeDirectives(t *testing.T) { t.Run("skip with default query argument", func(t *testing.T) { var resp map[string]interface{} - c.MustPost(`query Test($skip: Boolean = true) { todo(id: 1) @skip(if: $skip) { __typename } }`, &resp) + c.MustPost( + `query Test($skip: Boolean = true) { todo(id: 1) @skip(if: $skip) { __typename } }`, + &resp, + ) _, ok := resp["todo"] require.False(t, ok) }) diff --git a/_examples/type-system-extension/directive.go b/_examples/type-system-extension/directive.go index 2b3ff918ce..0961443242 100644 --- a/_examples/type-system-extension/directive.go +++ b/_examples/type-system-extension/directive.go @@ -7,37 +7,61 @@ import ( "github.com/99designs/gqlgen/graphql" ) -func EnumLogging(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) { +func EnumLogging( + ctx context.Context, + obj interface{}, + next graphql.Resolver, +) (res interface{}, err error) { rc := graphql.GetFieldContext(ctx) log.Printf("enum logging: %v, %s, %T, %+v", rc.Path(), rc.Field.Name, obj, obj) return next(ctx) } -func FieldLogging(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) { +func FieldLogging( + ctx context.Context, + obj interface{}, + next graphql.Resolver, +) (res interface{}, err error) { rc := graphql.GetFieldContext(ctx) log.Printf("field logging: %v, %s, %T, %+v", rc.Path(), rc.Field.Name, obj, obj) return next(ctx) } -func InputLogging(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) { +func InputLogging( + ctx context.Context, + obj interface{}, + next graphql.Resolver, +) (res interface{}, err error) { rc := graphql.GetFieldContext(ctx) log.Printf("input object logging: %v, %s, %T, %+v", rc.Path(), rc.Field.Name, obj, obj) return next(ctx) } -func ObjectLogging(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) { +func ObjectLogging( + ctx context.Context, + obj interface{}, + next graphql.Resolver, +) (res interface{}, err error) { rc := graphql.GetFieldContext(ctx) log.Printf("object logging: %v, %s, %T, %+v", rc.Path(), rc.Field.Name, obj, obj) return next(ctx) } -func ScalarLogging(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) { +func ScalarLogging( + ctx context.Context, + obj interface{}, + next graphql.Resolver, +) (res interface{}, err error) { rc := graphql.GetFieldContext(ctx) log.Printf("scalar logging: %v, %s, %T, %+v", rc.Path(), rc.Field.Name, obj, obj) return next(ctx) } -func UnionLogging(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) { +func UnionLogging( + ctx context.Context, + obj interface{}, + next graphql.Resolver, +) (res interface{}, err error) { rc := graphql.GetFieldContext(ctx) log.Printf("union logging: %v, %s, %T, %+v", rc.Path(), rc.Field.Name, obj, obj) return next(ctx) diff --git a/_examples/websocket-initfunc/server/graph/schema.resolvers.go b/_examples/websocket-initfunc/server/graph/schema.resolvers.go index dbf34d6469..705e613eee 100644 --- a/_examples/websocket-initfunc/server/graph/schema.resolvers.go +++ b/_examples/websocket-initfunc/server/graph/schema.resolvers.go @@ -11,12 +11,19 @@ import ( ) // PostMessageTo is the resolver for the postMessageTo field. -func (r *mutationResolver) PostMessageTo(ctx context.Context, subscriber string, content string) (string, error) { +func (r *mutationResolver) PostMessageTo( + ctx context.Context, + subscriber string, + content string, +) (string, error) { panic(fmt.Errorf("not implemented")) } // Subscribe is the resolver for the subscribe field. -func (r *subscriptionResolver) Subscribe(ctx context.Context, subscriber string) (<-chan string, error) { +func (r *subscriptionResolver) Subscribe( + ctx context.Context, + subscriber string, +) (<-chan string, error) { panic(fmt.Errorf("not implemented")) } @@ -26,5 +33,7 @@ func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResol // Subscription returns generated.SubscriptionResolver implementation. func (r *Resolver) Subscription() generated.SubscriptionResolver { return &subscriptionResolver{r} } -type mutationResolver struct{ *Resolver } -type subscriptionResolver struct{ *Resolver } +type ( + mutationResolver struct{ *Resolver } + subscriptionResolver struct{ *Resolver } +) diff --git a/_examples/websocket-initfunc/server/server.go b/_examples/websocket-initfunc/server/server.go index f1b0dd2cb5..0120f8ca61 100644 --- a/_examples/websocket-initfunc/server/server.go +++ b/_examples/websocket-initfunc/server/server.go @@ -19,7 +19,10 @@ import ( "github.com/rs/cors" ) -func webSocketInit(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { +func webSocketInit( + ctx context.Context, + initPayload transport.InitPayload, +) (context.Context, error) { // Get the token from payload any := initPayload["authToken"] token, ok := any.(string) @@ -54,7 +57,9 @@ func main() { Debug: false, }) - srv := handler.New(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}})) + srv := handler.New( + generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}}), + ) srv.AddTransport(transport.POST{}) srv.AddTransport(transport.Websocket{ KeepAlivePingInterval: 10 * time.Second, @@ -74,5 +79,4 @@ func main() { log.Printf("connect to http://localhost:%s/ for GraphQL playground", port) log.Fatal(http.ListenAndServe(":"+port, router)) - } diff --git a/api/generate.go b/api/generate.go index 6619dd5cd2..3bb7158c38 100644 --- a/api/generate.go +++ b/api/generate.go @@ -26,9 +26,12 @@ func Generate(cfg *config.Config, option ...Option) error { plugins = append(plugins, resolvergen.New()) if cfg.Federation.IsDefined() { if cfg.Federation.Version == 0 { // default to using the user's choice of version, but if unset, try to sort out which federation version to use - urlRegex := regexp.MustCompile(`(?s)@link.*\(.*url:.*?"(.*?)"[^)]+\)`) // regex to grab the url of a link directive, should it exist + urlRegex := regexp.MustCompile( + `(?s)@link.*\(.*url:.*?"(.*?)"[^)]+\)`, + ) // regex to grab the url of a link directive, should it exist - // check the sources, and if one is marked as federation v2, we mark the entirety to be generated using that format + // check the sources, and if one is marked as federation v2, we mark the entirety to be + // generated using that format for _, v := range cfg.Sources { cfg.Federation.Version = 1 urlString := urlRegex.FindStringSubmatch(v.Input) diff --git a/client/client.go b/client/client.go index 4c7e303a9d..4047a1e1aa 100644 --- a/client/client.go +++ b/client/client.go @@ -23,7 +23,8 @@ type ( // Option implements a visitor that mutates an outgoing GraphQL request // - // This is the Option pattern - https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis + // This is the Option pattern - + // https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis Option func(bd *Request) // Request represents an outgoing GraphQL request diff --git a/client/client_test.go b/client/client_test.go index 4064be7f1a..944da86097 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -47,10 +47,18 @@ func TestClientMultipartFormData(t *testing.T) { bodyBytes, err := io.ReadAll(r.Body) require.NoError(t, err) require.Contains(t, string(bodyBytes), `Content-Disposition: form-data; name="operations"`) - require.Contains(t, string(bodyBytes), `{"query":"mutation ($input: Input!) {}","variables":{"file":{}}`) + require.Contains( + t, + string(bodyBytes), + `{"query":"mutation ($input: Input!) {}","variables":{"file":{}}`, + ) require.Contains(t, string(bodyBytes), `Content-Disposition: form-data; name="map"`) require.Contains(t, string(bodyBytes), `{"0":["variables.file"]}`) - require.Contains(t, string(bodyBytes), `Content-Disposition: form-data; name="0"; filename="example.txt"`) + require.Contains( + t, + string(bodyBytes), + `Content-Disposition: form-data; name="0"; filename="example.txt"`, + ) require.Contains(t, string(bodyBytes), `Content-Type: text/plain`) require.Contains(t, string(bodyBytes), `Hello World`) @@ -64,7 +72,10 @@ func TestClientMultipartFormData(t *testing.T) { func(bd *client.Request) { bodyBuf := &bytes.Buffer{} bodyWriter := multipart.NewWriter(bodyBuf) - bodyWriter.WriteField("operations", `{"query":"mutation ($input: Input!) {}","variables":{"file":{}}`) + bodyWriter.WriteField( + "operations", + `{"query":"mutation ($input: Input!) {}","variables":{"file":{}}`, + ) bodyWriter.WriteField("map", `{"0":["variables.file"]}`) h := make(textproto.MIMEHeader) @@ -149,7 +160,11 @@ func TestAddExtensions(t *testing.T) { if err != nil { panic(err) } - require.Equal(t, `{"query":"user(id:1){name}","extensions":{"persistedQuery":{"sha256Hash":"ceec2897e2da519612279e63f24658c3e91194cbb2974744fa9007a7e1e9f9e7","version":1}}}`, string(b)) + require.Equal( + t, + `{"query":"user(id:1){name}","extensions":{"persistedQuery":{"sha256Hash":"ceec2897e2da519612279e63f24658c3e91194cbb2974744fa9007a7e1e9f9e7","version":1}}}`, + string(b), + ) err = json.NewEncoder(w).Encode(map[string]interface{}{ "data": map[string]interface{}{ "Name": "Bob", @@ -165,7 +180,16 @@ func TestAddExtensions(t *testing.T) { var resp struct { Name string } - c.MustPost("user(id:1){name}", &resp, - client.Extensions(map[string]interface{}{"persistedQuery": map[string]interface{}{"version": 1, "sha256Hash": "ceec2897e2da519612279e63f24658c3e91194cbb2974744fa9007a7e1e9f9e7"}}), + c.MustPost( + "user(id:1){name}", + &resp, + client.Extensions( + map[string]interface{}{ + "persistedQuery": map[string]interface{}{ + "version": 1, + "sha256Hash": "ceec2897e2da519612279e63f24658c3e91194cbb2974744fa9007a7e1e9f9e7", + }, + }, + ), ) } diff --git a/client/options.go b/client/options.go index bf4280ac71..43e24851f7 100644 --- a/client/options.go +++ b/client/options.go @@ -27,7 +27,8 @@ func Extensions(extensions map[string]interface{}) Option { } } -// Path sets the url that this request will be made against, useful if you are mounting your entire router +// Path sets the url that this request will be made against, useful if you are mounting your entire +// router // and need to specify the url to the graphql endpoint. func Path(url string) Option { return func(bd *Request) { @@ -35,7 +36,8 @@ func Path(url string) Option { } } -// AddHeader adds a header to the outgoing request. This is useful for setting expected Authentication headers for example. +// AddHeader adds a header to the outgoing request. This is useful for setting expected +// Authentication headers for example. func AddHeader(key string, value string) Option { return func(bd *Request) { bd.HTTP.Header.Add(key, value) diff --git a/client/websocket.go b/client/websocket.go index 69d263f789..832d5a9531 100644 --- a/client/websocket.go +++ b/client/websocket.go @@ -51,11 +51,15 @@ func (p *Client) WebsocketOnce(query string, resp interface{}, options ...Option if reflect.ValueOf(resp).Kind() == reflect.Ptr { return sock.Next(resp) } - //TODO: verify this is never called and remove it + // TODO: verify this is never called and remove it return sock.Next(&resp) } -func (p *Client) WebsocketWithPayload(query string, initPayload map[string]interface{}, options ...Option) *Subscription { +func (p *Client) WebsocketWithPayload( + query string, + initPayload map[string]interface{}, + options ...Option, +) *Subscription { r, err := p.newRequest(query, options...) if err != nil { return errorSubscription(fmt.Errorf("request: %w", err)) diff --git a/client/withfilesoption.go b/client/withfilesoption.go index 55742b0e92..311811ab23 100644 --- a/client/withfilesoption.go +++ b/client/withfilesoption.go @@ -91,7 +91,11 @@ func WithFiles() Option { for i, fileData := range filesGroup { mapDataFiles = append( mapDataFiles, - fmt.Sprintf(`"%d":[%s]`, i, strings.Join(collect(fileData, wrapMapKeyInQuotes), ",")), + fmt.Sprintf( + `"%d":[%s]`, + i, + strings.Join(collect(fileData, wrapMapKeyInQuotes), ","), + ), ) } @@ -107,7 +111,10 @@ func WithFiles() Option { // for i, fileData := range filesGroup { h := make(textproto.MIMEHeader) - h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%d"; filename="%s"`, i, fileData[0].file.Name())) + h.Set( + "Content-Disposition", + fmt.Sprintf(`form-data; name="%d"; filename="%s"`, i, fileData[0].file.Name()), + ) b, _ := os.ReadFile(fileData[0].file.Name()) h.Set("Content-Type", http.DetectContentType(b)) ff, _ := bodyWriter.CreatePart(h) diff --git a/client/withfilesoption_test.go b/client/withfilesoption_test.go index dbb7756cd7..f33fc4498b 100644 --- a/client/withfilesoption_test.go +++ b/client/withfilesoption_test.go @@ -50,7 +50,8 @@ func TestWithFiles(t *testing.T) { if contentDisposition == `form-data; name="map"` { require.EqualValues(t, `{"0":["variables.file"]}`, slurp) } - if regexp.MustCompile(`form-data; name="0"; filename=.*`).MatchString(contentDisposition) { + if regexp.MustCompile(`form-data; name="0"; filename=.*`). + MatchString(contentDisposition) { require.Equal(t, `text/plain; charset=utf-8`, p.Header.Get("Content-Type")) require.EqualValues(t, `The quick brown fox jumps over the lazy dog`, slurp) } @@ -87,7 +88,11 @@ func TestWithFiles(t *testing.T) { contentDisposition := p.Header.Get("Content-Disposition") if contentDisposition == `form-data; name="operations"` { - require.EqualValues(t, `{"query":"{ id }","variables":{"input":{"files":[{},{}]}}}`, slurp) + require.EqualValues( + t, + `{"query":"{ id }","variables":{"input":{"files":[{},{}]}}}`, + slurp, + ) } if contentDisposition == `form-data; name="map"` { // returns `{"0":["variables.input.files.0"],"1":["variables.input.files.1"]}` @@ -98,7 +103,8 @@ func TestWithFiles(t *testing.T) { require.Contains(t, string(slurp), `["variables.input.files.1"]`) require.Contains(t, string(slurp), `}`) } - if regexp.MustCompile(`form-data; name="[0,1]"; filename=.*`).MatchString(contentDisposition) { + if regexp.MustCompile(`form-data; name="[0,1]"; filename=.*`). + MatchString(contentDisposition) { require.Equal(t, `text/plain; charset=utf-8`, p.Header.Get("Content-Type")) require.Contains(t, []string{ `The quick brown fox jumps over the lazy dog`, @@ -140,10 +146,15 @@ func TestWithFiles(t *testing.T) { contentDisposition := p.Header.Get("Content-Disposition") if contentDisposition == `form-data; name="operations"` { - require.EqualValues(t, `{"query":"{ id }","variables":{"req":{"files":[{},{}],"foo":{"bar":{}}}}}`, slurp) + require.EqualValues( + t, + `{"query":"{ id }","variables":{"req":{"files":[{},{}],"foo":{"bar":{}}}}}`, + slurp, + ) } if contentDisposition == `form-data; name="map"` { - // returns `{"0":["variables.req.files.0"],"1":["variables.req.files.1"],"2":["variables.req.foo.bar"]}` + // returns + // `{"0":["variables.req.files.0"],"1":["variables.req.files.1"],"2":["variables.req.foo.bar"]}` // but the order of file inputs is unpredictable between different OS systems require.Contains(t, string(slurp), `{"0":`) require.Contains(t, string(slurp), `["variables.req.files.0"]`) @@ -153,7 +164,8 @@ func TestWithFiles(t *testing.T) { require.Contains(t, string(slurp), `["variables.req.foo.bar"]`) require.Contains(t, string(slurp), `}`) } - if regexp.MustCompile(`form-data; name="[0,1,2]"; filename=.*`).MatchString(contentDisposition) { + if regexp.MustCompile(`form-data; name="[0,1,2]"; filename=.*`). + MatchString(contentDisposition) { require.Equal(t, `text/plain; charset=utf-8`, p.Header.Get("Content-Type")) require.Contains(t, []string{ `The quick brown fox jumps over the lazy dog`, @@ -199,11 +211,20 @@ func TestWithFiles(t *testing.T) { contentDisposition := p.Header.Get("Content-Disposition") if contentDisposition == `form-data; name="operations"` { - require.EqualValues(t, `{"query":"{ id }","variables":{"files":[{},{},{}]}}`, slurp) + require.EqualValues( + t, + `{"query":"{ id }","variables":{"files":[{},{},{}]}}`, + slurp, + ) } if contentDisposition == `form-data; name="map"` { - require.EqualValues(t, `{"0":["variables.files.0","variables.files.2"],"1":["variables.files.1"]}`, slurp) - // returns `{"0":["variables.files.0","variables.files.2"],"1":["variables.files.1"]}` + require.EqualValues( + t, + `{"0":["variables.files.0","variables.files.2"],"1":["variables.files.1"]}`, + slurp, + ) + // returns + // `{"0":["variables.files.0","variables.files.2"],"1":["variables.files.1"]}` // but the order of file inputs is unpredictable between different OS systems require.Contains(t, string(slurp), `{"0":`) require.Contains(t, string(slurp), `["variables.files.0"`) @@ -213,14 +234,19 @@ func TestWithFiles(t *testing.T) { require.NotContains(t, string(slurp), `,"2":`) require.Contains(t, string(slurp), `}`) } - if regexp.MustCompile(`form-data; name="[0,1]"; filename=.*`).MatchString(contentDisposition) { + if regexp.MustCompile(`form-data; name="[0,1]"; filename=.*`). + MatchString(contentDisposition) { require.Equal(t, `text/plain; charset=utf-8`, p.Header.Get("Content-Type")) require.Contains(t, []string{ `The quick brown fox jumps over the lazy dog`, `hello world`, }, string(slurp)) } - require.False(t, regexp.MustCompile(`form-data; name="2"; filename=.*`).MatchString(contentDisposition)) + require.False( + t, + regexp.MustCompile(`form-data; name="2"; filename=.*`). + MatchString(contentDisposition), + ) } w.Write([]byte(`{}`)) }) diff --git a/codegen/args.go b/codegen/args.go index 0fd30fffd5..c75d04f244 100644 --- a/codegen/args.go +++ b/codegen/args.go @@ -73,7 +73,11 @@ func (b *builder) buildArg(obj *Object, arg *ast.ArgumentDefinition) (*FieldArgu return &newArg, nil } -func (b *builder) bindArgs(field *Field, sig *types.Signature, params *types.Tuple) ([]*FieldArgument, error) { +func (b *builder) bindArgs( + field *Field, + sig *types.Signature, + params *types.Tuple, +) ([]*FieldArgument, error) { n := params.Len() newArgs := make([]*FieldArgument, 0, len(field.Args)) // Accept variadic methods (i.e. have optional parameters). diff --git a/codegen/config/binder.go b/codegen/config/binder.go index 212a168652..a6c616c51c 100644 --- a/codegen/config/binder.go +++ b/codegen/config/binder.go @@ -82,7 +82,10 @@ func (b *Binder) FindType(pkgName string, typeName string) (types.Type, error) { } var ( - MapType = types.NewMap(types.Typ[types.String], types.NewInterfaceType(nil, nil).Complete()) + MapType = types.NewMap( + types.Typ[types.String], + types.NewInterfaceType(nil, nil).Complete(), + ) InterfaceType = types.NewInterfaceType(nil, nil) ) @@ -164,9 +167,10 @@ func indexDefs(pkg *packages.Package) map[string]types.Object { } if _, ok := res[astNode.Name]; !ok { - // The above check may not be really needed, it is only here to have a consistent behavior with - // previous implementation of FindObject() function which only honored the first inclusion of a def. - // If this is still needed, we can consider something like sync.Map.LoadOrStore() to avoid two lookups. + // The above check may not be really needed, it is only here to have a consistent + // behavior with previous implementation of FindObject() function which only honored the + // first inclusion of a def. If this is still needed, we can consider something like + // sync.Map.LoadOrStore() to avoid two lookups. res[astNode.Name] = def } } @@ -181,7 +185,8 @@ func (b *Binder) PointerTo(ref *TypeReference) *TypeReference { return &newRef } -// TypeReference is used by args and field types. The Definition can refer to both input and output types. +// TypeReference is used by args and field types. The Definition can refer to both input and output +// types. type TypeReference struct { Definition *ast.Definition GQL *ast.Type @@ -216,7 +221,8 @@ func (t *TypeReference) IsPtr() bool { return isPtr } -// fix for https://github.com/golang/go/issues/31103 may make it possible to remove this (may still be useful) +// fix for https://github.com/golang/go/issues/31103 may make it possible to remove this (may still +// be useful) func (t *TypeReference) IsPtrToPtr() bool { if p, isPtr := t.GO.(*types.Pointer); isPtr { _, isPtr := p.Elem().(*types.Pointer) @@ -318,7 +324,10 @@ func isIntf(t types.Type) bool { return ok } -func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret *TypeReference, err error) { +func (b *Binder) TypeReference( + schemaType *ast.Type, + bindTarget types.Type, +) (ret *TypeReference, err error) { if !isValid(bindTarget) { b.SawInvalid = true return nil, fmt.Errorf("%s has an invalid type", schemaType.Name()) @@ -376,7 +385,11 @@ func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret if fun, isFunc := obj.(*types.Func); isFunc { ref.GO = fun.Type().(*types.Signature).Params().At(0).Type() - ref.IsContext = fun.Type().(*types.Signature).Results().At(0).Type().String() == "github.com/99designs/gqlgen/graphql.ContextMarshaler" + ref.IsContext = fun.Type().(*types.Signature).Results(). + At(0). + Type(). + String() == + "github.com/99designs/gqlgen/graphql.ContextMarshaler" ref.Marshaler = fun ref.Unmarshaler = types.NewFunc(0, fun.Pkg(), "Unmarshal"+typeName, nil) } else if hasMethod(obj.Type(), "MarshalGQLContext") && hasMethod(obj.Type(), "UnmarshalGQLContext") { @@ -387,7 +400,8 @@ func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret ref.GO = obj.Type() ref.IsMarshaler = true } else if underlying := basicUnderlying(obj.Type()); def.IsLeafType() && underlying != nil && underlying.Kind() == types.String { - // TODO delete before v1. Backwards compatibility case for named types wrapping strings (see #595) + // TODO delete before v1. Backwards compatibility case for named types wrapping strings + // (see #595) ref.GO = obj.Type() ref.CastType = underlying @@ -432,7 +446,8 @@ func isValid(t types.Type) bool { func (b *Binder) CopyModifiersFromAst(t *ast.Type, base types.Type) types.Type { if t.Elem != nil { child := b.CopyModifiersFromAst(t.Elem, base) - if _, isStruct := child.Underlying().(*types.Struct); isStruct && !b.cfg.OmitSliceElementPointers { + if _, isStruct := child.Underlying().(*types.Struct); isStruct && + !b.cfg.OmitSliceElementPointers { child = types.NewPointer(child) } return types.NewSlice(child) diff --git a/codegen/config/binder_test.go b/codegen/config/binder_test.go index 55227563d8..5891ba2df7 100644 --- a/codegen/config/binder_test.go +++ b/codegen/config/binder_test.go @@ -28,7 +28,11 @@ func TestSlicePointerBinding(t *testing.T) { panic(err) } - require.Equal(t, ta.GO.String(), "[]*github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message") + require.Equal( + t, + ta.GO.String(), + "[]*github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message", + ) }) t.Run("with OmitSliceElementPointers", func(t *testing.T) { @@ -41,14 +45,20 @@ func TestSlicePointerBinding(t *testing.T) { panic(err) } - require.Equal(t, ta.GO.String(), "[]github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message") + require.Equal( + t, + ta.GO.String(), + "[]github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message", + ) }) } func createBinder(cfg Config) (*Binder, *ast.Schema) { cfg.Models = TypeMap{ "Message": TypeMapEntry{ - Model: []string{"github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message"}, + Model: []string{ + "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message", + }, }, } cfg.Packages = &code.Packages{} diff --git a/codegen/config/config.go b/codegen/config/config.go index b13ee1a120..0ea68c9807 100644 --- a/codegen/config/config.go +++ b/codegen/config/config.go @@ -69,13 +69,17 @@ func LoadDefaultConfig() (*Config, error) { return nil, fmt.Errorf("unable to open schema: %w", err) } - config.Sources = append(config.Sources, &ast.Source{Name: filename, Input: string(schemaRaw)}) + config.Sources = append( + config.Sources, + &ast.Source{Name: filename, Input: string(schemaRaw)}, + ) } return config, nil } -// LoadConfigFromDefaultLocations looks for a config file in the current directory, and all parent directories +// LoadConfigFromDefaultLocations looks for a config file in the current directory, and all parent +// directories // walking up the tree. The closest config file will be returned. func LoadConfigFromDefaultLocations() (*Config, error) { cfgFile, err := findCfg() @@ -147,7 +151,8 @@ func CompleteConfig(config *Config) error { pathParts := strings.SplitN(f, "**", 2) rest := strings.TrimPrefix(strings.TrimPrefix(pathParts[1], `\`), `/`) // turn the rest of the glob into a regex, anchored only at the end because ** allows - // for any number of dirs in between and walk will let us match against the full path name + // for any number of dirs in between and walk will let us match against the full path + // name globRe := regexp.MustCompile(path2regex.Replace(rest) + `$`) if err := filepath.Walk(pathParts[0], func(path string, info os.FileInfo, err error) error { @@ -188,7 +193,10 @@ func CompleteConfig(config *Config) error { return fmt.Errorf("unable to open schema: %w", err) } - config.Sources = append(config.Sources, &ast.Source{Name: filename, Input: string(schemaRaw)}) + config.Sources = append( + config.Sources, + &ast.Source{Name: filename, Input: string(schemaRaw)}, + ) } return nil } @@ -255,7 +263,8 @@ func (c *Config) injectTypesFromSchema() error { } for _, schemaType := range c.Schema.Types { - if schemaType == c.Schema.Query || schemaType == c.Schema.Mutation || schemaType == c.Schema.Subscription { + if schemaType == c.Schema.Query || schemaType == c.Schema.Mutation || + schemaType == c.Schema.Subscription { continue } @@ -390,34 +399,43 @@ func (c *Config) check() error { if err := c.Resolver.Check(); err != nil { return fmt.Errorf("config.resolver: %w", err) } - fileList[c.Resolver.ImportPath()] = append(fileList[c.Resolver.ImportPath()], FilenamePackage{ - Filename: c.Resolver.Filename, - Package: c.Resolver.Package, - Declaree: "resolver", - }) + fileList[c.Resolver.ImportPath()] = append( + fileList[c.Resolver.ImportPath()], + FilenamePackage{ + Filename: c.Resolver.Filename, + Package: c.Resolver.Package, + Declaree: "resolver", + }, + ) } if c.Federation.IsDefined() { if err := c.Federation.Check(); err != nil { return fmt.Errorf("config.federation: %w", err) } - fileList[c.Federation.ImportPath()] = append(fileList[c.Federation.ImportPath()], FilenamePackage{ - Filename: c.Federation.Filename, - Package: c.Federation.Package, - Declaree: "federation", - }) + fileList[c.Federation.ImportPath()] = append( + fileList[c.Federation.ImportPath()], + FilenamePackage{ + Filename: c.Federation.Filename, + Package: c.Federation.Package, + Declaree: "federation", + }, + ) if c.Federation.ImportPath() != c.Exec.ImportPath() { return fmt.Errorf("federation and exec must be in the same package") } } if c.Federated { - return fmt.Errorf("federated has been removed, instead use\nfederation:\n filename: path/to/federated.go") + return fmt.Errorf( + "federated has been removed, instead use\nfederation:\n filename: path/to/federated.go", + ) } for importPath, pkg := range fileList { for _, file1 := range pkg { for _, file2 := range pkg { if file1.Package != file2.Package { - return fmt.Errorf("%s and %s define the same import path (%s) with different package names (%s vs %s)", + return fmt.Errorf( + "%s and %s define the same import path (%s) with different package names (%s vs %s)", file1.Declaree, file2.Declaree, importPath, @@ -448,7 +466,11 @@ func (tm TypeMap) Check() error { for typeName, entry := range tm { for _, model := range entry.Model { if strings.LastIndex(model, ".") < strings.LastIndex(model, "/") { - return fmt.Errorf("model %s: invalid type specifier \"%s\" - you need to specify a struct to map to", typeName, entry.Model) + return fmt.Errorf( + "model %s: invalid type specifier \"%s\" - you need to specify a struct to map to", + typeName, + entry.Model, + ) } } } @@ -543,7 +565,10 @@ func (c *Config) autobind() error { for i, p := range ps { if p == nil || p.Module == nil { - return fmt.Errorf("unable to load %s - make sure you're using an import path to a package that exists", c.AutoBind[i]) + return fmt.Errorf( + "unable to load %s - make sure you're using an import path to a package that exists", + c.AutoBind[i], + ) } if t := p.Types.Scope().Lookup(t.Name); t != nil { c.Models.Add(t.Name(), t.Pkg().Path()+"."+t.Name()) @@ -578,17 +603,31 @@ func (c *Config) autobind() error { func (c *Config) injectBuiltins() { builtins := TypeMap{ - "__Directive": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Directive"}}, + "__Directive": { + Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Directive"}, + }, "__DirectiveLocation": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}}, - "__Type": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Type"}}, - "__TypeKind": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}}, - "__Field": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Field"}}, - "__EnumValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.EnumValue"}}, - "__InputValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.InputValue"}}, - "__Schema": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Schema"}}, - "Float": {Model: StringList{"github.com/99designs/gqlgen/graphql.FloatContext"}}, - "String": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}}, - "Boolean": {Model: StringList{"github.com/99designs/gqlgen/graphql.Boolean"}}, + "__Type": { + Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Type"}, + }, + "__TypeKind": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}}, + "__Field": { + Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Field"}, + }, + "__EnumValue": { + Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.EnumValue"}, + }, + "__InputValue": { + Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.InputValue"}, + }, + "__Schema": { + Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Schema"}, + }, + "Float": { + Model: StringList{"github.com/99designs/gqlgen/graphql.FloatContext"}, + }, + "String": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}}, + "Boolean": {Model: StringList{"github.com/99designs/gqlgen/graphql.Boolean"}}, "Int": {Model: StringList{ "github.com/99designs/gqlgen/graphql.Int", "github.com/99designs/gqlgen/graphql.Int32", @@ -617,7 +656,8 @@ func (c *Config) injectBuiltins() { } for typeName, entry := range extraBuiltins { - if t, ok := c.Schema.Types[typeName]; !c.Models.Exists(typeName) && ok && t.Kind == ast.Scalar { + if t, ok := c.Schema.Types[typeName]; !c.Models.Exists(typeName) && ok && + t.Kind == ast.Scalar { c.Models[typeName] = entry } } diff --git a/codegen/config/config_test.go b/codegen/config/config_test.go index 29f37250a7..5304dafc95 100644 --- a/codegen/config/config_test.go +++ b/codegen/config/config_test.go @@ -24,12 +24,20 @@ func TestLoadConfig(t *testing.T) { t.Run("malformed config", func(t *testing.T) { _, err := LoadConfig("testdata/cfg/malformedconfig.yml") - require.EqualError(t, err, "unable to parse config: yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `asdf` into config.Config") + require.EqualError( + t, + err, + "unable to parse config: yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `asdf` into config.Config", + ) }) t.Run("unknown keys", func(t *testing.T) { _, err := LoadConfig("testdata/cfg/unknownkeys.yml") - require.EqualError(t, err, "unable to parse config: yaml: unmarshal errors:\n line 2: field unknown not found in type config.Config") + require.EqualError( + t, + err, + "unable to parse config: yaml: unmarshal errors:\n line 2: field unknown not found in type config.Config", + ) }) t.Run("globbed filenames", func(t *testing.T) { @@ -48,7 +56,11 @@ func TestLoadConfig(t *testing.T) { t.Run("unwalkable path", func(t *testing.T) { _, err := LoadConfig("testdata/cfg/unwalkable.yml") if runtime.GOOS == "windows" { - require.EqualError(t, err, "failed to walk schema at root not_walkable/: CreateFile not_walkable/: The system cannot find the file specified.") + require.EqualError( + t, + err, + "failed to walk schema at root not_walkable/: CreateFile not_walkable/: The system cannot find the file specified.", + ) } else { require.EqualError(t, err, "failed to walk schema at root not_walkable/: lstat not_walkable/: no such file or directory") } @@ -135,38 +147,74 @@ func TestConfigCheck(t *testing.T) { t.Run(string(execLayout), func(t *testing.T) { t.Run("invalid config format due to conflicting package names", func(t *testing.T) { config := Config{ - Exec: ExecConfig{Layout: execLayout, Filename: "generated/exec.go", DirName: "generated", Package: "graphql"}, + Exec: ExecConfig{ + Layout: execLayout, + Filename: "generated/exec.go", + DirName: "generated", + Package: "graphql", + }, Model: PackageConfig{Filename: "generated/models.go"}, } - require.EqualError(t, config.check(), "exec and model define the same import path (github.com/99designs/gqlgen/codegen/config/generated) with different package names (graphql vs generated)") + require.EqualError( + t, + config.check(), + "exec and model define the same import path (github.com/99designs/gqlgen/codegen/config/generated) with different package names (graphql vs generated)", + ) }) t.Run("federation must be in exec package", func(t *testing.T) { config := Config{ - Exec: ExecConfig{Layout: execLayout, Filename: "generated/exec.go", DirName: "generated"}, + Exec: ExecConfig{ + Layout: execLayout, + Filename: "generated/exec.go", + DirName: "generated", + }, Federation: PackageConfig{Filename: "anotherpkg/federation.go"}, } - require.EqualError(t, config.check(), "federation and exec must be in the same package") + require.EqualError( + t, + config.check(), + "federation and exec must be in the same package", + ) }) t.Run("federation must have same package name as exec", func(t *testing.T) { config := Config{ - Exec: ExecConfig{Layout: execLayout, Filename: "generated/exec.go", DirName: "generated"}, - Federation: PackageConfig{Filename: "generated/federation.go", Package: "federation"}, + Exec: ExecConfig{ + Layout: execLayout, + Filename: "generated/exec.go", + DirName: "generated", + }, + Federation: PackageConfig{ + Filename: "generated/federation.go", + Package: "federation", + }, } - require.EqualError(t, config.check(), "exec and federation define the same import path (github.com/99designs/gqlgen/codegen/config/generated) with different package names (generated vs federation)") + require.EqualError( + t, + config.check(), + "exec and federation define the same import path (github.com/99designs/gqlgen/codegen/config/generated) with different package names (generated vs federation)", + ) }) t.Run("deprecated federated flag raises an error", func(t *testing.T) { config := Config{ - Exec: ExecConfig{Layout: execLayout, Filename: "generated/exec.go", DirName: "generated"}, + Exec: ExecConfig{ + Layout: execLayout, + Filename: "generated/exec.go", + DirName: "generated", + }, Federated: true, } - require.EqualError(t, config.check(), "federated has been removed, instead use\nfederation:\n filename: path/to/federated.go") + require.EqualError( + t, + config.check(), + "federated has been removed, instead use\nfederation:\n filename: path/to/federated.go", + ) }) }) } @@ -190,8 +238,16 @@ func TestAutobinding(t *testing.T) { require.NoError(t, cfg.autobind()) - require.Equal(t, "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/scalars/model.Banned", cfg.Models["Banned"].Model[0]) - require.Equal(t, "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message", cfg.Models["Message"].Model[0]) + require.Equal( + t, + "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/scalars/model.Banned", + cfg.Models["Banned"].Model[0], + ) + require.Equal( + t, + "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message", + cfg.Models["Message"].Model[0], + ) }) t.Run("with file path", func(t *testing.T) { @@ -208,6 +264,10 @@ func TestAutobinding(t *testing.T) { type Message { id: ID } `}) - require.EqualError(t, cfg.autobind(), "unable to load ../chat - make sure you're using an import path to a package that exists") + require.EqualError( + t, + cfg.autobind(), + "unable to load ../chat - make sure you're using an import path to a package that exists", + ) }) } diff --git a/codegen/config/exec.go b/codegen/config/exec.go index fe1dccd21d..8ba046442a 100644 --- a/codegen/config/exec.go +++ b/codegen/config/exec.go @@ -26,7 +26,8 @@ type ExecLayout string var ( // Write all generated code to a single file. ExecLayoutSingleFile ExecLayout = "single-file" - // Write generated code to a directory, generating one Go source file for each GraphQL schema file. + // Write generated code to a directory, generating one Go source file for each GraphQL schema + // file. ExecLayoutFollowSchema ExecLayout = "follow-schema" ) @@ -41,7 +42,9 @@ func (r *ExecConfig) Check() error { return fmt.Errorf("filename must be specified when using single-file layout") } if !strings.HasSuffix(r.Filename, ".go") { - return fmt.Errorf("filename should be path to a go source file when using single-file layout") + return fmt.Errorf( + "filename should be path to a go source file when using single-file layout", + ) } r.Filename = abs(r.Filename) case ExecLayoutFollowSchema: @@ -54,7 +57,9 @@ func (r *ExecConfig) Check() error { } if strings.ContainsAny(r.Package, "./\\") { - return fmt.Errorf("package should be the output package name only, do not include the output filename") + return fmt.Errorf( + "package should be the output package name only, do not include the output filename", + ) } if r.Package == "" && r.Dir() != "" { diff --git a/codegen/config/package.go b/codegen/config/package.go index faacd1496f..58920a7ebc 100644 --- a/codegen/config/package.go +++ b/codegen/config/package.go @@ -42,7 +42,9 @@ func (c *PackageConfig) IsDefined() bool { func (c *PackageConfig) Check() error { if strings.ContainsAny(c.Package, "./\\") { - return fmt.Errorf("package should be the output package name only, do not include the output filename") + return fmt.Errorf( + "package should be the output package name only, do not include the output filename", + ) } if c.Filename == "" { return fmt.Errorf("filename must be specified") diff --git a/codegen/config/package_test.go b/codegen/config/package_test.go index 524c5c59e4..f4ba6e50e7 100644 --- a/codegen/config/package_test.go +++ b/codegen/config/package_test.go @@ -66,6 +66,10 @@ func TestPackageConfig(t *testing.T) { p := PackageConfig{Filename: "foo.go", Package: "foo/foo.go"} require.True(t, p.IsDefined()) - require.EqualError(t, p.Check(), "package should be the output package name only, do not include the output filename") + require.EqualError( + t, + p.Check(), + "package should be the output package name only, do not include the output filename", + ) }) } diff --git a/codegen/config/resolver.go b/codegen/config/resolver.go index cd03f18872..3dbab57f16 100644 --- a/codegen/config/resolver.go +++ b/codegen/config/resolver.go @@ -39,7 +39,10 @@ func (r *ResolverConfig) Check() error { return fmt.Errorf("filename must be specified with layout=%s", r.Layout) } if !strings.HasSuffix(r.Filename, ".go") { - return fmt.Errorf("filename should be path to a go source file with layout=%s", r.Layout) + return fmt.Errorf( + "filename should be path to a go source file with layout=%s", + r.Layout, + ) } r.Filename = abs(r.Filename) case LayoutFollowSchema: @@ -53,11 +56,18 @@ func (r *ResolverConfig) Check() error { r.Filename = abs(r.Filename) } default: - return fmt.Errorf("invalid layout %s. must be %s or %s", r.Layout, LayoutSingleFile, LayoutFollowSchema) + return fmt.Errorf( + "invalid layout %s. must be %s or %s", + r.Layout, + LayoutSingleFile, + LayoutFollowSchema, + ) } if strings.ContainsAny(r.Package, "./\\") { - return fmt.Errorf("package should be the output package name only, do not include the output filename") + return fmt.Errorf( + "package should be the output package name only, do not include the output filename", + ) } if r.Package == "" && r.Dir() != "" { diff --git a/codegen/config/resolver_test.go b/codegen/config/resolver_test.go index 271bdfd630..85065147b6 100644 --- a/codegen/config/resolver_test.go +++ b/codegen/config/resolver_test.go @@ -62,14 +62,22 @@ func TestResolverConfig(t *testing.T) { p := ResolverConfig{Filename: "wololo.sql"} require.True(t, p.IsDefined()) - require.EqualError(t, p.Check(), "filename should be path to a go source file with layout=single-file") + require.EqualError( + t, + p.Check(), + "filename should be path to a go source file with layout=single-file", + ) }) t.Run("when package includes a filename", func(t *testing.T) { p := ResolverConfig{Filename: "foo.go", Package: "foo/foo.go"} require.True(t, p.IsDefined()) - require.EqualError(t, p.Check(), "package should be the output package name only, do not include the output filename") + require.EqualError( + t, + p.Check(), + "package should be the output package name only, do not include the output filename", + ) }) }) @@ -109,7 +117,11 @@ func TestResolverConfig(t *testing.T) { }) t.Run("when given a filename", func(t *testing.T) { - p := ResolverConfig{Layout: LayoutFollowSchema, DirName: "testdata", Filename: "testdata/asdf.go"} + p := ResolverConfig{ + Layout: LayoutFollowSchema, + DirName: "testdata", + Filename: "testdata/asdf.go", + } require.True(t, p.IsDefined()) require.NoError(t, p.Check()) @@ -145,6 +157,10 @@ func TestResolverConfig(t *testing.T) { p := ResolverConfig{Layout: "pies", Filename: "asdf.go"} require.True(t, p.IsDefined()) - require.EqualError(t, p.Check(), "invalid layout pies. must be single-file or follow-schema") + require.EqualError( + t, + p.Check(), + "invalid layout pies. must be single-file or follow-schema", + ) }) } diff --git a/codegen/data.go b/codegen/data.go index 592140ae6c..3cbb478a72 100644 --- a/codegen/data.go +++ b/codegen/data.go @@ -12,7 +12,8 @@ import ( "github.com/99designs/gqlgen/codegen/config" ) -// Data is a unified model of the code to be generated. Plugins may modify this structure to do things like implement +// Data is a unified model of the code to be generated. Plugins may modify this structure to do +// things like implement // resolvers or directives automatically (eg grpc, validation) type Data struct { Config *config.Config @@ -46,7 +47,8 @@ func (d *Data) HasEmbeddableSources() bool { return hasEmbeddableSources } -// AugmentedSource contains extra information about graphql schema files which is not known directly from the Config.Sources data +// AugmentedSource contains extra information about graphql schema files which is not known directly +// from the Config.Sources data type AugmentedSource struct { // path relative to Config.Exec.Filename RelativePath string @@ -168,7 +170,9 @@ func BuildData(cfg *config.Config) (*Data, error) { } // otherwise show a generic error message - return nil, fmt.Errorf("invalid types were encountered while traversing the go source code, this probably means the invalid code generated isnt correct. add try adding -v to debug") + return nil, fmt.Errorf( + "invalid types were encountered while traversing the go source code, this probably means the invalid code generated isnt correct. add try adding -v to debug", + ) } aSources := []AugmentedSource{} for _, s := range cfg.Sources { @@ -180,7 +184,12 @@ func BuildData(cfg *config.Config) (*Data, error) { sourcePath := filepath.Join(wd, s.Name) relative, err := filepath.Rel(outputDir, sourcePath) if err != nil { - return nil, fmt.Errorf("failed to compute path of %s relative to %s: %w", sourcePath, outputDir, err) + return nil, fmt.Errorf( + "failed to compute path of %s relative to %s: %w", + sourcePath, + outputDir, + err, + ) } relative = filepath.ToSlash(relative) embeddable := true diff --git a/codegen/directive.go b/codegen/directive.go index 973061129a..50f269a486 100644 --- a/codegen/directive.go +++ b/codegen/directive.go @@ -36,7 +36,10 @@ func (d *Directive) IsLocation(location ...ast.DirectiveLocation) bool { return false } -func locationDirectives(directives DirectiveList, location ...ast.DirectiveLocation) map[string]*Directive { +func locationDirectives( + directives DirectiveList, + location ...ast.DirectiveLocation, +) map[string]*Directive { mDirectives := make(map[string]*Directive) for name, d := range directives { if d.IsLocation(location...) { @@ -71,7 +74,12 @@ func (b *builder) buildDirectives() (map[string]*Directive, error) { var err error newArg.Default, err = arg.DefaultValue.Value(nil) if err != nil { - return nil, fmt.Errorf("default value for directive argument %s(%s) is not valid: %w", dir.Name, arg.Name, err) + return nil, fmt.Errorf( + "default value for directive argument %s(%s) is not valid: %w", + dir.Name, + arg.Name, + err, + ) } } args = append(args, newArg) @@ -141,7 +149,14 @@ func (d *Directive) CallArgs() string { args := []string{"ctx", "obj", "n"} for _, arg := range d.Args { - args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")") + args = append( + args, + "args["+strconv.Quote( + arg.Name, + )+"].("+templates.CurrentImports.LookupType( + arg.TypeReference.GO, + )+")", + ) } return strings.Join(args, ", ") @@ -166,7 +181,11 @@ func (d *Directive) Declaration() string { res := ucFirst(d.Name) + " func(ctx context.Context, obj interface{}, next graphql.Resolver" for _, arg := range d.Args { - res += fmt.Sprintf(", %s %s", templates.ToGoPrivate(arg.Name), templates.CurrentImports.LookupType(arg.TypeReference.GO)) + res += fmt.Sprintf( + ", %s %s", + templates.ToGoPrivate(arg.Name), + templates.CurrentImports.LookupType(arg.TypeReference.GO), + ) } res += ") (res interface{}, err error)" diff --git a/codegen/field.go b/codegen/field.go index a33cc18e5a..66509b839e 100644 --- a/codegen/field.go +++ b/codegen/field.go @@ -73,7 +73,8 @@ func (b *builder) buildField(obj *Object, field *ast.FieldDefinition) (*Field, e log.Println(err.Error()) } - if f.IsResolver && b.Config.ResolversAlwaysReturnPointers && !f.TypeReference.IsPtr() && f.TypeReference.IsStruct() { + if f.IsResolver && b.Config.ResolversAlwaysReturnPointers && !f.TypeReference.IsPtr() && + f.TypeReference.IsStruct() { f.TypeReference = b.Binder.PointerTo(f.TypeReference) } @@ -309,7 +310,11 @@ func (b *builder) findBindMethodTarget(in types.Type, name string) (types.Object return nil, nil } -func (b *builder) findBindMethoderTarget(methodFunc func(i int) *types.Func, methodCount int, name string) (types.Object, error) { +func (b *builder) findBindMethoderTarget( + methodFunc func(i int) *types.Func, + methodCount int, + name string, +) (types.Object, error) { var found types.Object for i := 0; i < methodCount; i++ { method := methodFunc(i) @@ -365,7 +370,10 @@ func (b *builder) findBindEmbedsTarget(in types.Type, name string) (types.Object return nil, nil } -func (b *builder) findBindStructEmbedsTarget(strukt *types.Struct, name string) (types.Object, error) { +func (b *builder) findBindStructEmbedsTarget( + strukt *types.Struct, + name string, +) (types.Object, error) { var found types.Object for i := 0; i < strukt.NumFields(); i++ { field := strukt.Field(i) @@ -395,7 +403,10 @@ func (b *builder) findBindStructEmbedsTarget(strukt *types.Struct, name string) return found, nil } -func (b *builder) findBindInterfaceEmbedsTarget(iface *types.Interface, name string) (types.Object, error) { +func (b *builder) findBindInterfaceEmbedsTarget( + iface *types.Interface, + name string, +) (types.Object, error) { var found types.Object for i := 0; i < iface.NumEmbeddeds(); i++ { embeddedType := iface.EmbeddedType(i) @@ -473,9 +484,18 @@ func (f *Field) GoNameUnexported() string { func (f *Field) ShortInvocation() string { caser := cases.Title(language.English, cases.NoLower) if f.Object.Kind == ast.InputObject { - return fmt.Sprintf("%s().%s(ctx, &it, data)", caser.String(f.Object.Definition.Name), f.GoFieldName) + return fmt.Sprintf( + "%s().%s(ctx, &it, data)", + caser.String(f.Object.Definition.Name), + f.GoFieldName, + ) } - return fmt.Sprintf("%s().%s(%s)", caser.String(f.Object.Definition.Name), f.GoFieldName, f.CallArgs()) + return fmt.Sprintf( + "%s().%s(%s)", + caser.String(f.Object.Definition.Name), + f.GoFieldName, + f.CallArgs(), + ) } func (f *Field) ArgsFunc() string { @@ -516,7 +536,11 @@ func (f *Field) ShortResolverDeclaration() string { res += fmt.Sprintf(", obj %s", templates.CurrentImports.LookupType(f.Object.Reference())) } for _, arg := range f.Args { - res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO)) + res += fmt.Sprintf( + ", %s %s", + arg.VarName, + templates.CurrentImports.LookupType(arg.TypeReference.GO), + ) } result := templates.CurrentImports.LookupType(f.TypeReference.GO) @@ -531,7 +555,11 @@ func (f *Field) ShortResolverDeclaration() string { func (f *Field) ComplexitySignature() string { res := "func(childComplexity int" for _, arg := range f.Args { - res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO)) + res += fmt.Sprintf( + ", %s %s", + arg.VarName, + templates.CurrentImports.LookupType(arg.TypeReference.GO), + ) } res += ") int" return res @@ -540,7 +568,11 @@ func (f *Field) ComplexitySignature() string { func (f *Field) ComplexityArgs() string { args := make([]string, len(f.Args)) for i, arg := range f.Args { - args[i] = "args[" + strconv.Quote(arg.Name) + "].(" + templates.CurrentImports.LookupType(arg.TypeReference.GO) + ")" + args[i] = "args[" + strconv.Quote( + arg.Name, + ) + "].(" + templates.CurrentImports.LookupType( + arg.TypeReference.GO, + ) + ")" } return strings.Join(args, ", ") @@ -560,7 +592,11 @@ func (f *Field) CallArgs() string { } for _, arg := range f.Args { - tmp := "fc.Args[" + strconv.Quote(arg.Name) + "].(" + templates.CurrentImports.LookupType(arg.TypeReference.GO) + ")" + tmp := "fc.Args[" + strconv.Quote( + arg.Name, + ) + "].(" + templates.CurrentImports.LookupType( + arg.TypeReference.GO, + ) + ")" if iface, ok := arg.TypeReference.GO.(*types.Interface); ok && iface.Empty() { tmp = fmt.Sprintf(` diff --git a/codegen/field_test.go b/codegen/field_test.go index 642d2d3f5c..bf9fc1f58a 100644 --- a/codegen/field_test.go +++ b/codegen/field_test.go @@ -56,9 +56,23 @@ type Embed struct { ShouldError bool }{ {"Finds a field by name with no tag", std, "name", "", "Name", false}, - {"Finds a field by name when passed tag but tag not used", std, "name", "gqlgen", "Name", false}, + { + "Finds a field by name when passed tag but tag not used", + std, + "name", + "gqlgen", + "Name", + false, + }, {"Ignores tags when not passed a tag", tags, "foo", "", "Foo", false}, - {"Picks field with tag over field name when passed a tag", tags, "foo", "gqlgen", "Bar", false}, + { + "Picks field with tag over field name when passed a tag", + tags, + "foo", + "gqlgen", + "Bar", + false, + }, {"Errors when ambigious", amb, "foo", "gqlgen", "", true}, {"Finds a field that is in embedded struct", anon, "bar", "", "Bar", false}, {"Finds field that is not in embedded struct", embed, "test", "", "Test", false}, diff --git a/codegen/interface.go b/codegen/interface.go index cdc4d4d32e..f574bec634 100644 --- a/codegen/interface.go +++ b/codegen/interface.go @@ -75,7 +75,11 @@ func (b *builder) buildInterface(typ *ast.Definition) (*Interface, error) { } if !anyValid { - return nil, fmt.Errorf("%s does not satisfy the interface %s", implementorType.String(), i.Type.String()) + return nil, fmt.Errorf( + "%s does not satisfy the interface %s", + implementorType.String(), + i.Type.String(), + ) } } diff --git a/codegen/object.go b/codegen/object.go index ed0042a61f..6c2c6899b2 100644 --- a/codegen/object.go +++ b/codegen/object.go @@ -43,8 +43,9 @@ func (b *builder) buildObject(typ *ast.Definition) (*Object, error) { } caser := cases.Title(language.English, cases.NoLower) obj := &Object{ - Definition: typ, - Root: b.Schema.Query == typ || b.Schema.Mutation == typ || b.Schema.Subscription == typ, + Definition: typ, + Root: b.Schema.Query == typ || b.Schema.Mutation == typ || + b.Schema.Subscription == typ, DisableConcurrency: typ == b.Schema.Mutation, Stream: typ == b.Schema.Subscription, Directives: dirs, diff --git a/codegen/templates/import_test.go b/codegen/templates/import_test.go index baf88b50ab..99afa546b3 100644 --- a/codegen/templates/import_test.go +++ b/codegen/templates/import_test.go @@ -29,8 +29,15 @@ func TestImports(t *testing.T) { t.Run("lookup by type", func(t *testing.T) { a := Imports{destDir: wd, packages: &code.Packages{}} - pkg := types.NewPackage("github.com/99designs/gqlgen/codegen/templates/testdata/b/bar", "bar") - typ := types.NewNamed(types.NewTypeName(0, pkg, "Boolean", types.Typ[types.Bool]), types.Typ[types.Bool], nil) + pkg := types.NewPackage( + "github.com/99designs/gqlgen/codegen/templates/testdata/b/bar", + "bar", + ) + typ := types.NewNamed( + types.NewTypeName(0, pkg, "Boolean", types.Typ[types.Bool]), + types.Typ[types.Bool], + nil, + ) require.Equal(t, "bar.Boolean", a.LookupType(typ)) }) diff --git a/codegen/templates/templates.go b/codegen/templates/templates.go index 159df77c9c..bf908ed66a 100644 --- a/codegen/templates/templates.go +++ b/codegen/templates/templates.go @@ -22,8 +22,9 @@ import ( "github.com/99designs/gqlgen/internal/imports" ) -// CurrentImports keeps track of all the import declarations that are needed during the execution of a plugin. -// this is done with a global because subtemplates currently get called in functions. Lets aim to remove this eventually. +// CurrentImports keeps track of all the import declarations that are needed during the execution of +// a plugin. this is done with a global because subtemplates currently get called in functions. Lets +// aim to remove this eventually. var CurrentImports *Imports // Options specify various parameters to rendering a template. diff --git a/codegen/templates/templates_test.go b/codegen/templates/templates_test.go index 7bb10bb44f..ac8196dc8b 100644 --- a/codegen/templates/templates_test.go +++ b/codegen/templates/templates_test.go @@ -107,19 +107,42 @@ func TestToGoModelName(t *testing.T) { expected: []string{"MyEnumNameValue", "MyEnumNameValue0"}, }, { - input: [][]string{{"MyEnumName", "Value"}, {"MyEnumName", "value"}, {"MyEnumName", "vALue"}, {"MyEnumName", "VALue"}}, - expected: []string{"MyEnumNameValue", "MyEnumNamevalue", "MyEnumNameVALue", "MyEnumNameVALue0"}, - }, - { - input: [][]string{{"MyEnumName", "TitleValue"}, {"MyEnumName", "title_value"}, {"MyEnumName", "title_Value"}, {"MyEnumName", "Title_Value"}}, - expected: []string{"MyEnumNameTitleValue", "MyEnumNametitle_value", "MyEnumNametitle_Value", "MyEnumNameTitle_Value"}, + input: [][]string{ + {"MyEnumName", "Value"}, + {"MyEnumName", "value"}, + {"MyEnumName", "vALue"}, + {"MyEnumName", "VALue"}, + }, + expected: []string{ + "MyEnumNameValue", + "MyEnumNamevalue", + "MyEnumNameVALue", + "MyEnumNameVALue0", + }, + }, + { + input: [][]string{ + {"MyEnumName", "TitleValue"}, + {"MyEnumName", "title_value"}, + {"MyEnumName", "title_Value"}, + {"MyEnumName", "Title_Value"}, + }, + expected: []string{ + "MyEnumNameTitleValue", + "MyEnumNametitle_value", + "MyEnumNametitle_Value", + "MyEnumNameTitle_Value", + }, }, { input: [][]string{{"MyEnumName", "TitleValue", "OtherValue"}}, expected: []string{"MyEnumNameTitleValueOtherValue"}, }, { - input: [][]string{{"MyEnumName", "TitleValue", "OtherValue"}, {"MyEnumName", "title_value", "OtherValue"}}, + input: [][]string{ + {"MyEnumName", "TitleValue", "OtherValue"}, + {"MyEnumName", "title_value", "OtherValue"}, + }, expected: []string{"MyEnumNameTitleValueOtherValue", "MyEnumNametitle_valueOtherValue"}, }, } @@ -167,19 +190,42 @@ func TestToGoPrivateModelName(t *testing.T) { expected: []string{"myEnumNameValue", "myEnumNameValue0"}, }, { - input: [][]string{{"MyEnumName", "Value"}, {"MyEnumName", "value"}, {"MyEnumName", "vALue"}, {"MyEnumName", "VALue"}}, - expected: []string{"myEnumNameValue", "myEnumNamevalue", "myEnumNameVALue", "myEnumNameVALue0"}, - }, - { - input: [][]string{{"MyEnumName", "TitleValue"}, {"MyEnumName", "title_value"}, {"MyEnumName", "title_Value"}, {"MyEnumName", "Title_Value"}}, - expected: []string{"myEnumNameTitleValue", "myEnumNametitle_value", "myEnumNametitle_Value", "myEnumNameTitle_Value"}, + input: [][]string{ + {"MyEnumName", "Value"}, + {"MyEnumName", "value"}, + {"MyEnumName", "vALue"}, + {"MyEnumName", "VALue"}, + }, + expected: []string{ + "myEnumNameValue", + "myEnumNamevalue", + "myEnumNameVALue", + "myEnumNameVALue0", + }, + }, + { + input: [][]string{ + {"MyEnumName", "TitleValue"}, + {"MyEnumName", "title_value"}, + {"MyEnumName", "title_Value"}, + {"MyEnumName", "Title_Value"}, + }, + expected: []string{ + "myEnumNameTitleValue", + "myEnumNametitle_value", + "myEnumNametitle_Value", + "myEnumNameTitle_Value", + }, }, { input: [][]string{{"MyEnumName", "TitleValue", "OtherValue"}}, expected: []string{"myEnumNameTitleValueOtherValue"}, }, { - input: [][]string{{"MyEnumName", "TitleValue", "OtherValue"}, {"MyEnumName", "title_value", "OtherValue"}}, + input: [][]string{ + {"MyEnumName", "TitleValue", "OtherValue"}, + {"MyEnumName", "title_value", "OtherValue"}, + }, expected: []string{"myEnumNameTitleValueOtherValue", "myEnumNametitle_valueOtherValue"}, }, } @@ -231,36 +277,60 @@ func Test_wordWalker(t *testing.T) { expected: []*wordInfo{{Word: "to"}, {WordOffset: 1, Word: "camel"}}, }, { - input: makeInput("RelatedURLs"), - expected: []*wordInfo{{Word: "Related"}, {WordOffset: 1, Word: "URLs", HasCommonInitial: true}}, + input: makeInput("RelatedURLs"), + expected: []*wordInfo{ + {Word: "Related"}, + {WordOffset: 1, Word: "URLs", HasCommonInitial: true}, + }, }, { - input: makeInput("ImageIDs"), - expected: []*wordInfo{{Word: "Image"}, {WordOffset: 1, Word: "IDs", HasCommonInitial: true}}, + input: makeInput("ImageIDs"), + expected: []*wordInfo{ + {Word: "Image"}, + {WordOffset: 1, Word: "IDs", HasCommonInitial: true}, + }, }, { - input: makeInput("FooID"), - expected: []*wordInfo{{Word: "Foo"}, {WordOffset: 1, Word: "ID", HasCommonInitial: true, MatchCommonInitial: true}}, + input: makeInput("FooID"), + expected: []*wordInfo{ + {Word: "Foo"}, + {WordOffset: 1, Word: "ID", HasCommonInitial: true, MatchCommonInitial: true}, + }, }, { - input: makeInput("IDFoo"), - expected: []*wordInfo{{Word: "ID", HasCommonInitial: true, MatchCommonInitial: true}, {WordOffset: 1, Word: "Foo"}}, + input: makeInput("IDFoo"), + expected: []*wordInfo{ + {Word: "ID", HasCommonInitial: true, MatchCommonInitial: true}, + {WordOffset: 1, Word: "Foo"}, + }, }, { - input: makeInput("FooASCII"), - expected: []*wordInfo{{Word: "Foo"}, {WordOffset: 1, Word: "ASCII", HasCommonInitial: true, MatchCommonInitial: true}}, + input: makeInput("FooASCII"), + expected: []*wordInfo{ + {Word: "Foo"}, + {WordOffset: 1, Word: "ASCII", HasCommonInitial: true, MatchCommonInitial: true}, + }, }, { - input: makeInput("ASCIIFoo"), - expected: []*wordInfo{{Word: "ASCII", HasCommonInitial: true, MatchCommonInitial: true}, {WordOffset: 1, Word: "Foo"}}, + input: makeInput("ASCIIFoo"), + expected: []*wordInfo{ + {Word: "ASCII", HasCommonInitial: true, MatchCommonInitial: true}, + {WordOffset: 1, Word: "Foo"}, + }, }, { - input: makeInput("FooUTF8"), - expected: []*wordInfo{{Word: "Foo"}, {WordOffset: 1, Word: "UTF8", HasCommonInitial: true, MatchCommonInitial: true}}, + input: makeInput("FooUTF8"), + expected: []*wordInfo{ + {Word: "Foo"}, + {WordOffset: 1, Word: "UTF8", HasCommonInitial: true, MatchCommonInitial: true}, + }, }, { - input: makeInput("UTF8Foo"), - expected: []*wordInfo{{Word: "UTF8", HasCommonInitial: true, MatchCommonInitial: true}, {WordOffset: 1, Word: "Foo"}}, + input: makeInput("UTF8Foo"), + expected: []*wordInfo{ + {Word: "UTF8", HasCommonInitial: true, MatchCommonInitial: true}, + {WordOffset: 1, Word: "Foo"}, + }, }, { input: makeInput("A"), @@ -315,7 +385,6 @@ func TestTemplateOverride(t *testing.T) { } func TestRenderFS(t *testing.T) { - tempDir := t.TempDir() outDir := filepath.Join(tempDir, "output") diff --git a/codegen/testserver/empty.go b/codegen/testserver/empty.go index e46955dab2..ebd0968021 100644 --- a/codegen/testserver/empty.go +++ b/codegen/testserver/empty.go @@ -1,3 +1,4 @@ package testserver -// Empty file to silence go build error complaining that codegen/testserver/ has no non-test Go source files. +// Empty file to silence go build error complaining that codegen/testserver/ has no non-test Go +// source files. diff --git a/codegen/testserver/followschema/complexity_test.go b/codegen/testserver/followschema/complexity_test.go index 6a91e0f000..62c75ef0ba 100644 --- a/codegen/testserver/followschema/complexity_test.go +++ b/codegen/testserver/followschema/complexity_test.go @@ -74,7 +74,11 @@ func TestComplexityFuncs(t *testing.T) { } err := c.Post(`query { overlapping { oneFoo, twoFoo, oldFoo, newFoo, new_foo } }`, &resp) - require.EqualError(t, err, `[{"message":"operation has complexity 2012, which exceeds the limit of 10","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}]`) + require.EqualError( + t, + err, + `[{"message":"operation has complexity 2012, which exceeds the limit of 10","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}]`, + ) require.False(t, ran) }) @@ -113,7 +117,11 @@ func TestComplexityFuncs(t *testing.T) { c: overlapping { newFoo }, }`, &resp) - require.EqualError(t, err, `[{"message":"operation has complexity 18, which exceeds the limit of 10","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}]`) + require.EqualError( + t, + err, + `[{"message":"operation has complexity 18, which exceeds the limit of 10","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}]`, + ) require.False(t, ran) }) } diff --git a/codegen/testserver/followschema/directive_test.go b/codegen/testserver/followschema/directive_test.go index e995b2721c..b15077e719 100644 --- a/codegen/testserver/followschema/directive_test.go +++ b/codegen/testserver/followschema/directive_test.go @@ -203,7 +203,11 @@ func TestDirectives(t *testing.T) { err := c.Post(`query { directiveArg(arg: "") }`, &resp) - require.EqualError(t, err, `[{"message":"invalid length","path":["directiveArg","arg"]}]`) + require.EqualError( + t, + err, + `[{"message":"invalid length","path":["directiveArg","arg"]}]`, + ) require.Nil(t, resp.DirectiveArg) }) t.Run("when function errors on nullable arg directives", func(t *testing.T) { @@ -213,7 +217,11 @@ func TestDirectives(t *testing.T) { err := c.Post(`query { directiveNullableArg(arg: -100) }`, &resp) - require.EqualError(t, err, `[{"message":"too small","path":["directiveNullableArg","arg"]}]`) + require.EqualError( + t, + err, + `[{"message":"too small","path":["directiveNullableArg","arg"]}]`, + ) require.Nil(t, resp.DirectiveNullableArg) }) t.Run("when function success on nullable arg directives", func(t *testing.T) { @@ -279,7 +287,11 @@ func TestDirectives(t *testing.T) { err := c.Post(`query { directiveUnimplemented }`, &resp) - require.EqualError(t, err, `[{"message":"directive unimplemented is not implemented","path":["directiveUnimplemented"]}]`) + require.EqualError( + t, + err, + `[{"message":"directive unimplemented is not implemented","path":["directiveUnimplemented"]}]`, + ) }) t.Run("ok", func(t *testing.T) { @@ -318,9 +330,16 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"invalid text",inner:{message:"123"}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"invalid text",inner:{message:"123"}}) }`, + &resp, + ) - require.EqualError(t, err, `[{"message":"not valid","path":["directiveInputNullable","arg","text"]}]`) + require.EqualError( + t, + err, + `[{"message":"not valid","path":["directiveInputNullable","arg","text"]}]`, + ) require.Nil(t, resp.DirectiveInputNullable) }) t.Run("when function errors on inner directives", func(t *testing.T) { @@ -328,9 +347,16 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"2",inner:{message:""}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"2",inner:{message:""}}) }`, + &resp, + ) - require.EqualError(t, err, `[{"message":"not valid","path":["directiveInputNullable","arg","inner","message"]}]`) + require.EqualError( + t, + err, + `[{"message":"not valid","path":["directiveInputNullable","arg","inner","message"]}]`, + ) require.Nil(t, resp.DirectiveInputNullable) }) t.Run("when function errors on nullable inner directives", func(t *testing.T) { @@ -338,9 +364,16 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"success",inner:{message:"1"},innerNullable:{message:""}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"success",inner:{message:"1"},innerNullable:{message:""}}) }`, + &resp, + ) - require.EqualError(t, err, `[{"message":"not valid","path":["directiveInputNullable","arg","innerNullable","message"]}]`) + require.EqualError( + t, + err, + `[{"message":"not valid","path":["directiveInputNullable","arg","innerNullable","message"]}]`, + ) require.Nil(t, resp.DirectiveInputNullable) }) t.Run("when function success", func(t *testing.T) { @@ -348,7 +381,10 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"23",inner:{message:"1"}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"23",inner:{message:"1"}}) }`, + &resp, + ) require.Nil(t, err) require.Equal(t, "Ok", *resp.DirectiveInputNullable) @@ -358,7 +394,10 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"23",nullableText:"23",inner:{message:"1"},innerNullable:{message:"success"}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"23",nullableText:"23",inner:{message:"1"},innerNullable:{message:"success"}}) }`, + &resp, + ) require.Nil(t, err) require.Equal(t, "Ok", *resp.DirectiveInputNullable) @@ -417,7 +456,11 @@ func TestDirectives(t *testing.T) { err := c.WebsocketOnce(`subscription { directiveArg(arg: "") }`, &resp) - require.EqualError(t, err, `[{"message":"invalid length","path":["directiveArg","arg"]}]`) + require.EqualError( + t, + err, + `[{"message":"invalid length","path":["directiveArg","arg"]}]`, + ) require.Nil(t, resp.DirectiveArg) }) t.Run("when function errors on nullable arg directives", func(t *testing.T) { @@ -427,7 +470,11 @@ func TestDirectives(t *testing.T) { err := c.WebsocketOnce(`subscription { directiveNullableArg(arg: -100) }`, &resp) - require.EqualError(t, err, `[{"message":"too small","path":["directiveNullableArg","arg"]}]`) + require.EqualError( + t, + err, + `[{"message":"too small","path":["directiveNullableArg","arg"]}]`, + ) require.Nil(t, resp.DirectiveNullableArg) }) t.Run("when function success on nullable arg directives", func(t *testing.T) { diff --git a/codegen/testserver/followschema/embedded_test.go b/codegen/testserver/followschema/embedded_test.go index b5e1575bac..ae6b31c9e6 100644 --- a/codegen/testserver/followschema/embedded_test.go +++ b/codegen/testserver/followschema/embedded_test.go @@ -39,7 +39,11 @@ func TestEmbedded(t *testing.T) { } err := c.Post(`query { embeddedCase1 { exportedEmbeddedPointerExportedMethod } }`, &resp) require.NoError(t, err) - require.Equal(t, resp.EmbeddedCase1.ExportedEmbeddedPointerExportedMethod, "ExportedEmbeddedPointerExportedMethodResponse") + require.Equal( + t, + resp.EmbeddedCase1.ExportedEmbeddedPointerExportedMethod, + "ExportedEmbeddedPointerExportedMethodResponse", + ) }) t.Run("embedded case 2", func(t *testing.T) { @@ -50,7 +54,11 @@ func TestEmbedded(t *testing.T) { } err := c.Post(`query { embeddedCase2 { unexportedEmbeddedPointerExportedMethod } }`, &resp) require.NoError(t, err) - require.Equal(t, resp.EmbeddedCase2.UnexportedEmbeddedPointerExportedMethod, "UnexportedEmbeddedPointerExportedMethodResponse") + require.Equal( + t, + resp.EmbeddedCase2.UnexportedEmbeddedPointerExportedMethod, + "UnexportedEmbeddedPointerExportedMethodResponse", + ) }) t.Run("embedded case 3", func(t *testing.T) { @@ -59,8 +67,15 @@ func TestEmbedded(t *testing.T) { UnexportedEmbeddedInterfaceExportedMethod string } } - err := c.Post(`query { embeddedCase3 { unexportedEmbeddedInterfaceExportedMethod } }`, &resp) + err := c.Post( + `query { embeddedCase3 { unexportedEmbeddedInterfaceExportedMethod } }`, + &resp, + ) require.NoError(t, err) - require.Equal(t, resp.EmbeddedCase3.UnexportedEmbeddedInterfaceExportedMethod, "UnexportedEmbeddedInterfaceExportedMethod") + require.Equal( + t, + resp.EmbeddedCase3.UnexportedEmbeddedInterfaceExportedMethod, + "UnexportedEmbeddedInterfaceExportedMethod", + ) }) } diff --git a/codegen/testserver/followschema/enums_test.go b/codegen/testserver/followschema/enums_test.go index e7c80c29d2..c88f5f376c 100644 --- a/codegen/testserver/followschema/enums_test.go +++ b/codegen/testserver/followschema/enums_test.go @@ -36,7 +36,11 @@ func TestEnumsResolver(t *testing.T) { enumInInput(input: {enum: INVALID}) } `, &resp) - require.EqualError(t, err, `http 422: {"errors":[{"message":"Value \"INVALID\" does not exist in \"EnumTest!\" enum.","locations":[{"line":2,"column":30}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`) + require.EqualError( + t, + err, + `http 422: {"errors":[{"message":"Value \"INVALID\" does not exist in \"EnumTest!\" enum.","locations":[{"line":2,"column":30}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + ) }) t.Run("input with invalid enum value via vars", func(t *testing.T) { @@ -47,6 +51,10 @@ func TestEnumsResolver(t *testing.T) { enumInInput(input: $input) } `, &resp, client.Var("input", map[string]interface{}{"enum": "INVALID"})) - require.EqualError(t, err, `http 422: {"errors":[{"message":"INVALID is not a valid EnumTest","path":["variable","input","enum"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`) + require.EqualError( + t, + err, + `http 422: {"errors":[{"message":"INVALID is not a valid EnumTest","path":["variable","input","enum"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + ) }) } diff --git a/codegen/testserver/followschema/input_test.go b/codegen/testserver/followschema/input_test.go index 5e301d2f8c..29aa170b6a 100644 --- a/codegen/testserver/followschema/input_test.go +++ b/codegen/testserver/followschema/input_test.go @@ -25,7 +25,11 @@ func TestInput(t *testing.T) { err := c.Post(`query { inputSlice(arg: ["ok", 1, 2, "ok"]) }`, &resp) - require.EqualError(t, err, `http 422: {"errors":[{"message":"String cannot represent a non string value: 1","locations":[{"line":1,"column":32}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"String cannot represent a non string value: 2","locations":[{"line":1,"column":35}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`) + require.EqualError( + t, + err, + `http 422: {"errors":[{"message":"String cannot represent a non string value: 1","locations":[{"line":1,"column":32}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"String cannot represent a non string value: 2","locations":[{"line":1,"column":35}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + ) require.Nil(t, resp.DirectiveArg) }) diff --git a/codegen/testserver/followschema/interfaces_test.go b/codegen/testserver/followschema/interfaces_test.go index 3a7820fe52..bb1c5cc044 100644 --- a/codegen/testserver/followschema/interfaces_test.go +++ b/codegen/testserver/followschema/interfaces_test.go @@ -174,7 +174,11 @@ func TestInterfaces(t *testing.T) { } } err := c.Post(`{ notAnInterface { id, thisShouldBind, thisShouldBindWithError } }`, &resp) - require.EqualError(t, err, `[{"message":"boom","path":["notAnInterface","thisShouldBindWithError"]}]`) + require.EqualError( + t, + err, + `[{"message":"boom","path":["notAnInterface","thisShouldBindWithError"]}]`, + ) }) t.Run("interfaces can implement other interfaces", func(t *testing.T) { diff --git a/codegen/testserver/followschema/introspection_test.go b/codegen/testserver/followschema/introspection_test.go index ef2bfafb53..f1fb0e426e 100644 --- a/codegen/testserver/followschema/introspection_test.go +++ b/codegen/testserver/followschema/introspection_test.go @@ -22,7 +22,11 @@ func TestIntrospection(t *testing.T) { var resp interface{} err := c.Post(introspection.Query, &resp) - require.EqualError(t, err, "[{\"message\":\"introspection disabled\",\"path\":[\"__schema\"]}]") + require.EqualError( + t, + err, + "[{\"message\":\"introspection disabled\",\"path\":[\"__schema\"]}]", + ) }) t.Run("enabled by default", func(t *testing.T) { @@ -66,14 +70,20 @@ func TestIntrospection(t *testing.T) { resolvers := &Stub{} srv := handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolvers})) - srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { - graphql.GetOperationContext(ctx).DisableIntrospection = true - return next(ctx) - }) + srv.AroundOperations( + func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + graphql.GetOperationContext(ctx).DisableIntrospection = true + return next(ctx) + }, + ) c := client.New(srv) var resp interface{} err := c.Post(introspection.Query, &resp) - require.EqualError(t, err, "[{\"message\":\"introspection disabled\",\"path\":[\"__schema\"]}]") + require.EqualError( + t, + err, + "[{\"message\":\"introspection disabled\",\"path\":[\"__schema\"]}]", + ) }) } diff --git a/codegen/testserver/followschema/maps_test.go b/codegen/testserver/followschema/maps_test.go index fe9750450f..f1661d3210 100644 --- a/codegen/testserver/followschema/maps_test.go +++ b/codegen/testserver/followschema/maps_test.go @@ -56,7 +56,10 @@ func TestMaps(t *testing.T) { var resp struct { MapNestedStringInterface map[string]interface{} } - err := c.Post(`query { mapNestedStringInterface(in: { map: { a: "a", b: null } }) { a, b } }`, &resp) + err := c.Post( + `query { mapNestedStringInterface(in: { map: { a: "a", b: null } }) { a, b } }`, + &resp, + ) require.NoError(t, err) require.Equal(t, "a", resp.MapNestedStringInterface["a"]) require.Nil(t, resp.MapNestedStringInterface["b"]) diff --git a/codegen/testserver/followschema/models-gen.go b/codegen/testserver/followschema/models-gen.go index 0cc3b4a24e..875941bef2 100644 --- a/codegen/testserver/followschema/models-gen.go +++ b/codegen/testserver/followschema/models-gen.go @@ -220,7 +220,7 @@ type ValidInput struct { Underscore string `json:"_"` } -// These things are all valid, but without care generate invalid go code +// These things are all valid, but without care generate invalid go code type ValidType struct { DifferentCase string `json:"differentCase"` DifferentCaseOld string `json:"different_case"` diff --git a/codegen/testserver/followschema/mutation_with_custom_scalar.go b/codegen/testserver/followschema/mutation_with_custom_scalar.go index 6245a5fc9b..19424a1b6d 100644 --- a/codegen/testserver/followschema/mutation_with_custom_scalar.go +++ b/codegen/testserver/followschema/mutation_with_custom_scalar.go @@ -7,7 +7,9 @@ import ( "regexp" ) -var re = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") +var re = regexp.MustCompile( + "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", +) type Email string diff --git a/codegen/testserver/followschema/mutation_with_custom_scalar_test.go b/codegen/testserver/followschema/mutation_with_custom_scalar_test.go index 2f46c3ad4d..8d9d805165 100644 --- a/codegen/testserver/followschema/mutation_with_custom_scalar_test.go +++ b/codegen/testserver/followschema/mutation_with_custom_scalar_test.go @@ -45,6 +45,10 @@ func TestErrorInsideMutationArgument(t *testing.T) { &resp, client.Var("input", input), ) - require.EqualError(t, err, `[{"message":"invalid email format","path":["updateSomething","input","nesting","field"]}]`) + require.EqualError( + t, + err, + `[{"message":"invalid email format","path":["updateSomething","input","nesting","field"]}]`, + ) }) } diff --git a/codegen/testserver/followschema/nulls_test.go b/codegen/testserver/followschema/nulls_test.go index 4375adbc1b..ab352a22bb 100644 --- a/codegen/testserver/followschema/nulls_test.go +++ b/codegen/testserver/followschema/nulls_test.go @@ -39,7 +39,11 @@ func TestNullBubbling(t *testing.T) { } err := c.Post(`query { valid, errorBubble { id, errorOnNonRequiredField } }`, &resp) - require.EqualError(t, err, `[{"message":"boom","path":["errorBubble","errorOnNonRequiredField"]}]`) + require.EqualError( + t, + err, + `[{"message":"boom","path":["errorBubble","errorOnNonRequiredField"]}]`, + ) require.Equal(t, "E1234", resp.ErrorBubble.Id) require.Nil(t, resp.ErrorBubble.ErrorOnNonRequiredField) require.Equal(t, "Ok", resp.Valid) @@ -54,7 +58,11 @@ func TestNullBubbling(t *testing.T) { } err := c.Post(`query { valid, errorBubble { id, errorOnRequiredField } }`, &resp) - require.EqualError(t, err, `[{"message":"boom","path":["errorBubble","errorOnRequiredField"]}]`) + require.EqualError( + t, + err, + `[{"message":"boom","path":["errorBubble","errorOnRequiredField"]}]`, + ) require.Nil(t, resp.ErrorBubble) require.Equal(t, "Ok", resp.Valid) }) @@ -68,7 +76,11 @@ func TestNullBubbling(t *testing.T) { } err := c.Post(`query { valid, errorBubble { id, nilOnRequiredField } }`, &resp) - require.EqualError(t, err, `[{"message":"the requested element is null which the schema does not allow","path":["errorBubble","nilOnRequiredField"]}]`) + require.EqualError( + t, + err, + `[{"message":"the requested element is null which the schema does not allow","path":["errorBubble","nilOnRequiredField"]}]`, + ) require.Nil(t, resp.ErrorBubble) require.Equal(t, "Ok", resp.Valid) }) @@ -93,8 +105,16 @@ func TestNullBubbling(t *testing.T) { } err := c.Post(`query { valid, errorBubbleList { id } }`, &resp) - require.Contains(t, err.Error(), `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",2]}`) - require.Contains(t, err.Error(), `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",1]}`) + require.Contains( + t, + err.Error(), + `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",2]}`, + ) + require.Contains( + t, + err.Error(), + `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",1]}`, + ) require.Nil(t, resp.ErrorBubbleList) require.Equal(t, "Ok", resp.Valid) }) @@ -130,6 +150,10 @@ func TestNullBubbling(t *testing.T) { } }`, &resp) require.Error(t, err) - require.Contains(t, err.Error(), "the requested element is null which the schema does not allow") + require.Contains( + t, + err.Error(), + "the requested element is null which the schema does not allow", + ) }) } diff --git a/codegen/testserver/followschema/panics_test.go b/codegen/testserver/followschema/panics_test.go index 4433aad01a..c6f7594d57 100644 --- a/codegen/testserver/followschema/panics_test.go +++ b/codegen/testserver/followschema/panics_test.go @@ -43,27 +43,43 @@ func TestPanics(t *testing.T) { var resp interface{} err := c.Post(`query { panics { fieldScalarMarshal } }`, &resp) - require.EqualError(t, err, "http 422: {\"errors\":[{\"message\":\"presented: panic: BOOM\"}],\"data\":null}") + require.EqualError( + t, + err, + "http 422: {\"errors\":[{\"message\":\"presented: panic: BOOM\"}],\"data\":null}", + ) }) t.Run("panics in unmarshalers will not kill server", func(t *testing.T) { var resp interface{} err := c.Post(`query { panics { argUnmarshal(u: ["aa", "bb"]) } }`, &resp) - require.EqualError(t, err, "[{\"message\":\"presented: input: panics.argUnmarshal panic: BOOM\",\"path\":[\"panics\",\"argUnmarshal\"]}]") + require.EqualError( + t, + err, + "[{\"message\":\"presented: input: panics.argUnmarshal panic: BOOM\",\"path\":[\"panics\",\"argUnmarshal\"]}]", + ) }) t.Run("panics in funcs unmarshal return errors", func(t *testing.T) { var resp interface{} err := c.Post(`query { panics { fieldFuncMarshal(u: ["aa", "bb"]) } }`, &resp) - require.EqualError(t, err, "[{\"message\":\"presented: input: panics.fieldFuncMarshal panic: BOOM\",\"path\":[\"panics\",\"fieldFuncMarshal\"]}]") + require.EqualError( + t, + err, + "[{\"message\":\"presented: input: panics.fieldFuncMarshal panic: BOOM\",\"path\":[\"panics\",\"fieldFuncMarshal\"]}]", + ) }) t.Run("panics in funcs marshal return errors", func(t *testing.T) { var resp interface{} err := c.Post(`query { panics { fieldFuncMarshal(u: []) } }`, &resp) - require.EqualError(t, err, "http 422: {\"errors\":[{\"message\":\"presented: panic: BOOM\"}],\"data\":null}") + require.EqualError( + t, + err, + "http 422: {\"errors\":[{\"message\":\"presented: panic: BOOM\"}],\"data\":null}", + ) }) } diff --git a/codegen/testserver/followschema/ptr_to_ptr_input_test.go b/codegen/testserver/followschema/ptr_to_ptr_input_test.go index bb644e492b..dd062acc6b 100644 --- a/codegen/testserver/followschema/ptr_to_ptr_input_test.go +++ b/codegen/testserver/followschema/ptr_to_ptr_input_test.go @@ -73,7 +73,10 @@ func TestPtrToPtr(t *testing.T) { t.Run("pointer to pointer input missing", func(t *testing.T) { var resp UpdatePtrToPtrResults - err := c.Post(`mutation { updatePtrToPtr(input: { name: "newName" }) { name, inner { key, value }, stupidInner { key, value }}}`, &resp) + err := c.Post( + `mutation { updatePtrToPtr(input: { name: "newName" }) { name, inner { key, value }, stupidInner { key, value }}}`, + &resp, + ) require.NoError(t, err) require.Equal(t, resp.UpdatedPtrToPtr.Name, "newName") @@ -113,7 +116,10 @@ func TestPtrToPtr(t *testing.T) { t.Run("pointer to pointer input null", func(t *testing.T) { var resp UpdatePtrToPtrResults - err := c.Post(`mutation { updatePtrToPtr(input: { inner: null }) { name, inner { key, value }, stupidInner { key, value }}}`, &resp) + err := c.Post( + `mutation { updatePtrToPtr(input: { inner: null }) { name, inner { key, value }, stupidInner { key, value }}}`, + &resp, + ) require.NoError(t, err) require.Equal(t, resp.UpdatedPtrToPtr.Name, "oldName") @@ -151,7 +157,10 @@ func TestPtrToPtr(t *testing.T) { t.Run("many pointers input null", func(t *testing.T) { var resp UpdatePtrToPtrResults - err := c.Post(`mutation { updatePtrToPtr(input: { stupidInner: null }) { name, inner { key, value }, stupidInner { key, value }}}`, &resp) + err := c.Post( + `mutation { updatePtrToPtr(input: { stupidInner: null }) { name, inner { key, value }, stupidInner { key, value }}}`, + &resp, + ) require.NoError(t, err) require.Equal(t, resp.UpdatedPtrToPtr.Name, "oldName") diff --git a/codegen/testserver/followschema/resolver.go b/codegen/testserver/followschema/resolver.go index 77b6eda405..9b585d4571 100644 --- a/codegen/testserver/followschema/resolver.go +++ b/codegen/testserver/followschema/resolver.go @@ -53,37 +53,59 @@ func (r *modelMethodsResolver) ResolverField(ctx context.Context, obj *ModelMeth } // // foo -func (r *mutationResolver) DefaultInput(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) { +func (r *mutationResolver) DefaultInput( + ctx context.Context, + input DefaultInput, +) (*DefaultParametersMirror, error) { panic("not implemented") } // // foo -func (r *mutationResolver) OverrideValueViaInput(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) { +func (r *mutationResolver) OverrideValueViaInput( + ctx context.Context, + input FieldsOrderInput, +) (*FieldsOrderPayload, error) { panic("not implemented") } // // foo -func (r *mutationResolver) UpdateSomething(ctx context.Context, input SpecialInput) (string, error) { +func (r *mutationResolver) UpdateSomething( + ctx context.Context, + input SpecialInput, +) (string, error) { panic("not implemented") } // // foo -func (r *mutationResolver) UpdatePtrToPtr(ctx context.Context, input UpdatePtrToPtrOuter) (*PtrToPtrOuter, error) { +func (r *mutationResolver) UpdatePtrToPtr( + ctx context.Context, + input UpdatePtrToPtrOuter, +) (*PtrToPtrOuter, error) { panic("not implemented") } // // foo -func (r *overlappingFieldsResolver) OldFoo(ctx context.Context, obj *OverlappingFields) (int, error) { +func (r *overlappingFieldsResolver) OldFoo( + ctx context.Context, + obj *OverlappingFields, +) (int, error) { panic("not implemented") } // // foo -func (r *panicsResolver) FieldScalarMarshal(ctx context.Context, obj *Panics) ([]MarshalPanic, error) { +func (r *panicsResolver) FieldScalarMarshal( + ctx context.Context, + obj *Panics, +) ([]MarshalPanic, error) { panic("not implemented") } // // foo -func (r *panicsResolver) ArgUnmarshal(ctx context.Context, obj *Panics, u []MarshalPanic) (bool, error) { +func (r *panicsResolver) ArgUnmarshal( + ctx context.Context, + obj *Panics, + u []MarshalPanic, +) (bool, error) { panic("not implemented") } @@ -108,7 +130,9 @@ func (r *primitiveStringResolver) Len(ctx context.Context, obj *PrimitiveString) } // // foo -func (r *queryResolver) InvalidIdentifier(ctx context.Context) (*invalid_packagename.InvalidIdentifier, error) { +func (r *queryResolver) InvalidIdentifier( + ctx context.Context, +) (*invalid_packagename.InvalidIdentifier, error) { panic("not implemented") } @@ -183,7 +207,11 @@ func (r *queryResolver) Overlapping(ctx context.Context) (*OverlappingFields, er } // // foo -func (r *queryResolver) DefaultParameters(ctx context.Context, falsyBoolean *bool, truthyBoolean *bool) (*DefaultParametersMirror, error) { +func (r *queryResolver) DefaultParameters( + ctx context.Context, + falsyBoolean *bool, + truthyBoolean *bool, +) (*DefaultParametersMirror, error) { panic("not implemented") } @@ -193,12 +221,20 @@ func (r *queryResolver) DirectiveArg(ctx context.Context, arg string) (*string, } // // foo -func (r *queryResolver) DirectiveNullableArg(ctx context.Context, arg *int, arg2 *int, arg3 *string) (*string, error) { +func (r *queryResolver) DirectiveNullableArg( + ctx context.Context, + arg *int, + arg2 *int, + arg3 *string, +) (*string, error) { panic("not implemented") } // // foo -func (r *queryResolver) DirectiveInputNullable(ctx context.Context, arg *InputDirectives) (*string, error) { +func (r *queryResolver) DirectiveInputNullable( + ctx context.Context, + arg *InputDirectives, +) (*string, error) { panic("not implemented") } @@ -218,7 +254,9 @@ func (r *queryResolver) DirectiveObject(ctx context.Context) (*ObjectDirectives, } // // foo -func (r *queryResolver) DirectiveObjectWithCustomGoModel(ctx context.Context) (*ObjectDirectivesWithCustomGoModel, error) { +func (r *queryResolver) DirectiveObjectWithCustomGoModel( + ctx context.Context, +) (*ObjectDirectivesWithCustomGoModel, error) { panic("not implemented") } @@ -258,7 +296,10 @@ func (r *queryResolver) EmbeddedCase3(ctx context.Context) (*EmbeddedCase3, erro } // // foo -func (r *queryResolver) EnumInInput(ctx context.Context, input *InputWithEnumValue) (EnumTest, error) { +func (r *queryResolver) EnumInInput( + ctx context.Context, + input *InputWithEnumValue, +) (EnumTest, error) { panic("not implemented") } @@ -303,12 +344,18 @@ func (r *queryResolver) Issue896a(ctx context.Context) ([]*CheckIssue896, error) } // // foo -func (r *queryResolver) MapStringInterface(ctx context.Context, in map[string]interface{}) (map[string]interface{}, error) { +func (r *queryResolver) MapStringInterface( + ctx context.Context, + in map[string]interface{}, +) (map[string]interface{}, error) { panic("not implemented") } // // foo -func (r *queryResolver) MapNestedStringInterface(ctx context.Context, in *NestedMapInput) (map[string]interface{}, error) { +func (r *queryResolver) MapNestedStringInterface( + ctx context.Context, + in *NestedMapInput, +) (map[string]interface{}, error) { panic("not implemented") } @@ -363,7 +410,9 @@ func (r *queryResolver) Infinity(ctx context.Context) (float64, error) { } // // foo -func (r *queryResolver) StringFromContextInterface(ctx context.Context) (*StringFromContextInterface, error) { +func (r *queryResolver) StringFromContextInterface( + ctx context.Context, +) (*StringFromContextInterface, error) { panic("not implemented") } @@ -388,7 +437,10 @@ func (r *queryResolver) ScalarSlice(ctx context.Context) ([]byte, error) { } // // foo -func (r *queryResolver) Fallback(ctx context.Context, arg FallbackToStringEncoding) (FallbackToStringEncoding, error) { +func (r *queryResolver) Fallback( + ctx context.Context, + arg FallbackToStringEncoding, +) (FallbackToStringEncoding, error) { panic("not implemented") } @@ -448,12 +500,20 @@ func (r *subscriptionResolver) InitPayload(ctx context.Context) (<-chan string, } // // foo -func (r *subscriptionResolver) DirectiveArg(ctx context.Context, arg string) (<-chan *string, error) { +func (r *subscriptionResolver) DirectiveArg( + ctx context.Context, + arg string, +) (<-chan *string, error) { panic("not implemented") } // // foo -func (r *subscriptionResolver) DirectiveNullableArg(ctx context.Context, arg *int, arg2 *int, arg3 *string) (<-chan *string, error) { +func (r *subscriptionResolver) DirectiveNullableArg( + ctx context.Context, + arg *int, + arg2 *int, + arg3 *string, +) (<-chan *string, error) { panic("not implemented") } @@ -546,18 +606,20 @@ func (r *Resolver) WrappedMap() WrappedMapResolver { return &wrappedMapResolver{ // WrappedSlice returns WrappedSliceResolver implementation. func (r *Resolver) WrappedSlice() WrappedSliceResolver { return &wrappedSliceResolver{r} } -type backedByInterfaceResolver struct{ *Resolver } -type errorsResolver struct{ *Resolver } -type forcedResolverResolver struct{ *Resolver } -type modelMethodsResolver struct{ *Resolver } -type mutationResolver struct{ *Resolver } -type overlappingFieldsResolver struct{ *Resolver } -type panicsResolver struct{ *Resolver } -type petResolver struct{ *Resolver } -type primitiveResolver struct{ *Resolver } -type primitiveStringResolver struct{ *Resolver } -type queryResolver struct{ *Resolver } -type subscriptionResolver struct{ *Resolver } -type userResolver struct{ *Resolver } -type wrappedMapResolver struct{ *Resolver } -type wrappedSliceResolver struct{ *Resolver } +type ( + backedByInterfaceResolver struct{ *Resolver } + errorsResolver struct{ *Resolver } + forcedResolverResolver struct{ *Resolver } + modelMethodsResolver struct{ *Resolver } + mutationResolver struct{ *Resolver } + overlappingFieldsResolver struct{ *Resolver } + panicsResolver struct{ *Resolver } + petResolver struct{ *Resolver } + primitiveResolver struct{ *Resolver } + primitiveStringResolver struct{ *Resolver } + queryResolver struct{ *Resolver } + subscriptionResolver struct{ *Resolver } + userResolver struct{ *Resolver } + wrappedMapResolver struct{ *Resolver } + wrappedSliceResolver struct{ *Resolver } +) diff --git a/codegen/testserver/followschema/time_test.go b/codegen/testserver/followschema/time_test.go index 60a098750a..cd1cf6ffb3 100644 --- a/codegen/testserver/followschema/time_test.go +++ b/codegen/testserver/followschema/time_test.go @@ -40,7 +40,11 @@ func TestTime(t *testing.T) { } err := c.Post(`query { user(id: 1) { created } }`, &resp) - require.EqualError(t, err, `[{"message":"the requested element is null which the schema does not allow","path":["user","created"]}]`) + require.EqualError( + t, + err, + `[{"message":"the requested element is null which the schema does not allow","path":["user","created"]}]`, + ) }) t.Run("with values", func(t *testing.T) { diff --git a/codegen/testserver/followschema/variadic.go b/codegen/testserver/followschema/variadic.go index 218b0d6c89..86e0ecb70d 100644 --- a/codegen/testserver/followschema/variadic.go +++ b/codegen/testserver/followschema/variadic.go @@ -9,6 +9,10 @@ type VariadicModel struct{} type VariadicModelOption func(*VariadicModel) -func (v VariadicModel) Value(ctx context.Context, rank int, opts ...VariadicModelOption) (string, error) { +func (v VariadicModel) Value( + ctx context.Context, + rank int, + opts ...VariadicModelOption, +) (string, error) { return strconv.Itoa(rank), nil } diff --git a/codegen/testserver/singlefile/complexity_test.go b/codegen/testserver/singlefile/complexity_test.go index ac8e05a8c3..fc2016c6be 100644 --- a/codegen/testserver/singlefile/complexity_test.go +++ b/codegen/testserver/singlefile/complexity_test.go @@ -74,7 +74,11 @@ func TestComplexityFuncs(t *testing.T) { } err := c.Post(`query { overlapping { oneFoo, twoFoo, oldFoo, newFoo, new_foo } }`, &resp) - require.EqualError(t, err, `[{"message":"operation has complexity 2012, which exceeds the limit of 10","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}]`) + require.EqualError( + t, + err, + `[{"message":"operation has complexity 2012, which exceeds the limit of 10","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}]`, + ) require.False(t, ran) }) @@ -113,7 +117,11 @@ func TestComplexityFuncs(t *testing.T) { c: overlapping { newFoo }, }`, &resp) - require.EqualError(t, err, `[{"message":"operation has complexity 18, which exceeds the limit of 10","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}]`) + require.EqualError( + t, + err, + `[{"message":"operation has complexity 18, which exceeds the limit of 10","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}]`, + ) require.False(t, ran) }) } diff --git a/codegen/testserver/singlefile/directive_test.go b/codegen/testserver/singlefile/directive_test.go index 0b7cb97df8..e77419dc26 100644 --- a/codegen/testserver/singlefile/directive_test.go +++ b/codegen/testserver/singlefile/directive_test.go @@ -203,7 +203,11 @@ func TestDirectives(t *testing.T) { err := c.Post(`query { directiveArg(arg: "") }`, &resp) - require.EqualError(t, err, `[{"message":"invalid length","path":["directiveArg","arg"]}]`) + require.EqualError( + t, + err, + `[{"message":"invalid length","path":["directiveArg","arg"]}]`, + ) require.Nil(t, resp.DirectiveArg) }) t.Run("when function errors on nullable arg directives", func(t *testing.T) { @@ -213,7 +217,11 @@ func TestDirectives(t *testing.T) { err := c.Post(`query { directiveNullableArg(arg: -100) }`, &resp) - require.EqualError(t, err, `[{"message":"too small","path":["directiveNullableArg","arg"]}]`) + require.EqualError( + t, + err, + `[{"message":"too small","path":["directiveNullableArg","arg"]}]`, + ) require.Nil(t, resp.DirectiveNullableArg) }) t.Run("when function success on nullable arg directives", func(t *testing.T) { @@ -279,7 +287,11 @@ func TestDirectives(t *testing.T) { err := c.Post(`query { directiveUnimplemented }`, &resp) - require.EqualError(t, err, `[{"message":"directive unimplemented is not implemented","path":["directiveUnimplemented"]}]`) + require.EqualError( + t, + err, + `[{"message":"directive unimplemented is not implemented","path":["directiveUnimplemented"]}]`, + ) }) t.Run("ok", func(t *testing.T) { @@ -318,9 +330,16 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"invalid text",inner:{message:"123"}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"invalid text",inner:{message:"123"}}) }`, + &resp, + ) - require.EqualError(t, err, `[{"message":"not valid","path":["directiveInputNullable","arg","text"]}]`) + require.EqualError( + t, + err, + `[{"message":"not valid","path":["directiveInputNullable","arg","text"]}]`, + ) require.Nil(t, resp.DirectiveInputNullable) }) t.Run("when function errors on inner directives", func(t *testing.T) { @@ -328,9 +347,16 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"2",inner:{message:""}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"2",inner:{message:""}}) }`, + &resp, + ) - require.EqualError(t, err, `[{"message":"not valid","path":["directiveInputNullable","arg","inner","message"]}]`) + require.EqualError( + t, + err, + `[{"message":"not valid","path":["directiveInputNullable","arg","inner","message"]}]`, + ) require.Nil(t, resp.DirectiveInputNullable) }) t.Run("when function errors on nullable inner directives", func(t *testing.T) { @@ -338,9 +364,16 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"success",inner:{message:"1"},innerNullable:{message:""}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"success",inner:{message:"1"},innerNullable:{message:""}}) }`, + &resp, + ) - require.EqualError(t, err, `[{"message":"not valid","path":["directiveInputNullable","arg","innerNullable","message"]}]`) + require.EqualError( + t, + err, + `[{"message":"not valid","path":["directiveInputNullable","arg","innerNullable","message"]}]`, + ) require.Nil(t, resp.DirectiveInputNullable) }) t.Run("when function success", func(t *testing.T) { @@ -348,7 +381,10 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"23",inner:{message:"1"}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"23",inner:{message:"1"}}) }`, + &resp, + ) require.NoError(t, err) require.Equal(t, "Ok", *resp.DirectiveInputNullable) @@ -358,7 +394,10 @@ func TestDirectives(t *testing.T) { DirectiveInputNullable *string } - err := c.Post(`query { directiveInputNullable(arg: {text:"23",nullableText:"23",inner:{message:"1"},innerNullable:{message:"success"}}) }`, &resp) + err := c.Post( + `query { directiveInputNullable(arg: {text:"23",nullableText:"23",inner:{message:"1"},innerNullable:{message:"success"}}) }`, + &resp, + ) require.NoError(t, err) require.Equal(t, "Ok", *resp.DirectiveInputNullable) @@ -417,7 +456,11 @@ func TestDirectives(t *testing.T) { err := c.WebsocketOnce(`subscription { directiveArg(arg: "") }`, &resp) - require.EqualError(t, err, `[{"message":"invalid length","path":["directiveArg","arg"]}]`) + require.EqualError( + t, + err, + `[{"message":"invalid length","path":["directiveArg","arg"]}]`, + ) require.Nil(t, resp.DirectiveArg) }) t.Run("when function errors on nullable arg directives", func(t *testing.T) { @@ -427,7 +470,11 @@ func TestDirectives(t *testing.T) { err := c.WebsocketOnce(`subscription { directiveNullableArg(arg: -100) }`, &resp) - require.EqualError(t, err, `[{"message":"too small","path":["directiveNullableArg","arg"]}]`) + require.EqualError( + t, + err, + `[{"message":"too small","path":["directiveNullableArg","arg"]}]`, + ) require.Nil(t, resp.DirectiveNullableArg) }) t.Run("when function success on nullable arg directives", func(t *testing.T) { diff --git a/codegen/testserver/singlefile/embedded_test.go b/codegen/testserver/singlefile/embedded_test.go index dd9ededd14..1ebcd8b269 100644 --- a/codegen/testserver/singlefile/embedded_test.go +++ b/codegen/testserver/singlefile/embedded_test.go @@ -39,7 +39,11 @@ func TestEmbedded(t *testing.T) { } err := c.Post(`query { embeddedCase1 { exportedEmbeddedPointerExportedMethod } }`, &resp) require.NoError(t, err) - require.Equal(t, resp.EmbeddedCase1.ExportedEmbeddedPointerExportedMethod, "ExportedEmbeddedPointerExportedMethodResponse") + require.Equal( + t, + resp.EmbeddedCase1.ExportedEmbeddedPointerExportedMethod, + "ExportedEmbeddedPointerExportedMethodResponse", + ) }) t.Run("embedded case 2", func(t *testing.T) { @@ -50,7 +54,11 @@ func TestEmbedded(t *testing.T) { } err := c.Post(`query { embeddedCase2 { unexportedEmbeddedPointerExportedMethod } }`, &resp) require.NoError(t, err) - require.Equal(t, resp.EmbeddedCase2.UnexportedEmbeddedPointerExportedMethod, "UnexportedEmbeddedPointerExportedMethodResponse") + require.Equal( + t, + resp.EmbeddedCase2.UnexportedEmbeddedPointerExportedMethod, + "UnexportedEmbeddedPointerExportedMethodResponse", + ) }) t.Run("embedded case 3", func(t *testing.T) { @@ -59,8 +67,15 @@ func TestEmbedded(t *testing.T) { UnexportedEmbeddedInterfaceExportedMethod string } } - err := c.Post(`query { embeddedCase3 { unexportedEmbeddedInterfaceExportedMethod } }`, &resp) + err := c.Post( + `query { embeddedCase3 { unexportedEmbeddedInterfaceExportedMethod } }`, + &resp, + ) require.NoError(t, err) - require.Equal(t, resp.EmbeddedCase3.UnexportedEmbeddedInterfaceExportedMethod, "UnexportedEmbeddedInterfaceExportedMethod") + require.Equal( + t, + resp.EmbeddedCase3.UnexportedEmbeddedInterfaceExportedMethod, + "UnexportedEmbeddedInterfaceExportedMethod", + ) }) } diff --git a/codegen/testserver/singlefile/enums_test.go b/codegen/testserver/singlefile/enums_test.go index 11ac0d1fbf..7af6c452b9 100644 --- a/codegen/testserver/singlefile/enums_test.go +++ b/codegen/testserver/singlefile/enums_test.go @@ -36,7 +36,11 @@ func TestEnumsResolver(t *testing.T) { enumInInput(input: {enum: INVALID}) } `, &resp) - require.EqualError(t, err, `http 422: {"errors":[{"message":"Value \"INVALID\" does not exist in \"EnumTest!\" enum.","locations":[{"line":2,"column":30}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`) + require.EqualError( + t, + err, + `http 422: {"errors":[{"message":"Value \"INVALID\" does not exist in \"EnumTest!\" enum.","locations":[{"line":2,"column":30}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + ) }) t.Run("input with invalid enum value via vars", func(t *testing.T) { @@ -47,6 +51,10 @@ func TestEnumsResolver(t *testing.T) { enumInInput(input: $input) } `, &resp, client.Var("input", map[string]interface{}{"enum": "INVALID"})) - require.EqualError(t, err, `http 422: {"errors":[{"message":"INVALID is not a valid EnumTest","path":["variable","input","enum"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`) + require.EqualError( + t, + err, + `http 422: {"errors":[{"message":"INVALID is not a valid EnumTest","path":["variable","input","enum"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + ) }) } diff --git a/codegen/testserver/singlefile/input_test.go b/codegen/testserver/singlefile/input_test.go index ba00a70f47..f00776763d 100644 --- a/codegen/testserver/singlefile/input_test.go +++ b/codegen/testserver/singlefile/input_test.go @@ -25,7 +25,11 @@ func TestInput(t *testing.T) { err := c.Post(`query { inputSlice(arg: ["ok", 1, 2, "ok"]) }`, &resp) - require.EqualError(t, err, `http 422: {"errors":[{"message":"String cannot represent a non string value: 1","locations":[{"line":1,"column":32}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"String cannot represent a non string value: 2","locations":[{"line":1,"column":35}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`) + require.EqualError( + t, + err, + `http 422: {"errors":[{"message":"String cannot represent a non string value: 1","locations":[{"line":1,"column":32}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"String cannot represent a non string value: 2","locations":[{"line":1,"column":35}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + ) require.Nil(t, resp.DirectiveArg) }) diff --git a/codegen/testserver/singlefile/interfaces_test.go b/codegen/testserver/singlefile/interfaces_test.go index 23b3fb0206..3c091fb38c 100644 --- a/codegen/testserver/singlefile/interfaces_test.go +++ b/codegen/testserver/singlefile/interfaces_test.go @@ -174,7 +174,11 @@ func TestInterfaces(t *testing.T) { } } err := c.Post(`{ notAnInterface { id, thisShouldBind, thisShouldBindWithError } }`, &resp) - require.EqualError(t, err, `[{"message":"boom","path":["notAnInterface","thisShouldBindWithError"]}]`) + require.EqualError( + t, + err, + `[{"message":"boom","path":["notAnInterface","thisShouldBindWithError"]}]`, + ) }) t.Run("interfaces can implement other interfaces", func(t *testing.T) { diff --git a/codegen/testserver/singlefile/introspection_test.go b/codegen/testserver/singlefile/introspection_test.go index f78a8202c1..9358c76a56 100644 --- a/codegen/testserver/singlefile/introspection_test.go +++ b/codegen/testserver/singlefile/introspection_test.go @@ -22,7 +22,11 @@ func TestIntrospection(t *testing.T) { var resp interface{} err := c.Post(introspection.Query, &resp) - require.EqualError(t, err, "[{\"message\":\"introspection disabled\",\"path\":[\"__schema\"]}]") + require.EqualError( + t, + err, + "[{\"message\":\"introspection disabled\",\"path\":[\"__schema\"]}]", + ) }) t.Run("enabled by default", func(t *testing.T) { @@ -66,14 +70,20 @@ func TestIntrospection(t *testing.T) { resolvers := &Stub{} srv := handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolvers})) - srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { - graphql.GetOperationContext(ctx).DisableIntrospection = true - return next(ctx) - }) + srv.AroundOperations( + func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + graphql.GetOperationContext(ctx).DisableIntrospection = true + return next(ctx) + }, + ) c := client.New(srv) var resp interface{} err := c.Post(introspection.Query, &resp) - require.EqualError(t, err, "[{\"message\":\"introspection disabled\",\"path\":[\"__schema\"]}]") + require.EqualError( + t, + err, + "[{\"message\":\"introspection disabled\",\"path\":[\"__schema\"]}]", + ) }) } diff --git a/codegen/testserver/singlefile/maps_test.go b/codegen/testserver/singlefile/maps_test.go index 0c7129ae61..fd61024882 100644 --- a/codegen/testserver/singlefile/maps_test.go +++ b/codegen/testserver/singlefile/maps_test.go @@ -56,7 +56,10 @@ func TestMaps(t *testing.T) { var resp struct { MapNestedStringInterface map[string]interface{} } - err := c.Post(`query { mapNestedStringInterface(in: { map: { a: "a", b: null } }) { a, b } }`, &resp) + err := c.Post( + `query { mapNestedStringInterface(in: { map: { a: "a", b: null } }) { a, b } }`, + &resp, + ) require.NoError(t, err) require.Equal(t, "a", resp.MapNestedStringInterface["a"]) require.Nil(t, resp.MapNestedStringInterface["b"]) diff --git a/codegen/testserver/singlefile/models-gen.go b/codegen/testserver/singlefile/models-gen.go index 53afbdf3fd..5ab72058e3 100644 --- a/codegen/testserver/singlefile/models-gen.go +++ b/codegen/testserver/singlefile/models-gen.go @@ -220,7 +220,7 @@ type ValidInput struct { Underscore string `json:"_"` } -// These things are all valid, but without care generate invalid go code +// These things are all valid, but without care generate invalid go code type ValidType struct { DifferentCase string `json:"differentCase"` DifferentCaseOld string `json:"different_case"` diff --git a/codegen/testserver/singlefile/mutation_with_custom_scalar.go b/codegen/testserver/singlefile/mutation_with_custom_scalar.go index 22c4586f29..c77924c696 100644 --- a/codegen/testserver/singlefile/mutation_with_custom_scalar.go +++ b/codegen/testserver/singlefile/mutation_with_custom_scalar.go @@ -7,7 +7,9 @@ import ( "regexp" ) -var re = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") +var re = regexp.MustCompile( + "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", +) type Email string diff --git a/codegen/testserver/singlefile/mutation_with_custom_scalar_test.go b/codegen/testserver/singlefile/mutation_with_custom_scalar_test.go index 3290b373e2..3f33fafaea 100644 --- a/codegen/testserver/singlefile/mutation_with_custom_scalar_test.go +++ b/codegen/testserver/singlefile/mutation_with_custom_scalar_test.go @@ -45,6 +45,10 @@ func TestErrorInsideMutationArgument(t *testing.T) { &resp, client.Var("input", input), ) - require.EqualError(t, err, `[{"message":"invalid email format","path":["updateSomething","input","nesting","field"]}]`) + require.EqualError( + t, + err, + `[{"message":"invalid email format","path":["updateSomething","input","nesting","field"]}]`, + ) }) } diff --git a/codegen/testserver/singlefile/nulls_test.go b/codegen/testserver/singlefile/nulls_test.go index e119f7c1b3..8931932804 100644 --- a/codegen/testserver/singlefile/nulls_test.go +++ b/codegen/testserver/singlefile/nulls_test.go @@ -39,7 +39,11 @@ func TestNullBubbling(t *testing.T) { } err := c.Post(`query { valid, errorBubble { id, errorOnNonRequiredField } }`, &resp) - require.EqualError(t, err, `[{"message":"boom","path":["errorBubble","errorOnNonRequiredField"]}]`) + require.EqualError( + t, + err, + `[{"message":"boom","path":["errorBubble","errorOnNonRequiredField"]}]`, + ) require.Equal(t, "E1234", resp.ErrorBubble.Id) require.Nil(t, resp.ErrorBubble.ErrorOnNonRequiredField) require.Equal(t, "Ok", resp.Valid) @@ -54,7 +58,11 @@ func TestNullBubbling(t *testing.T) { } err := c.Post(`query { valid, errorBubble { id, errorOnRequiredField } }`, &resp) - require.EqualError(t, err, `[{"message":"boom","path":["errorBubble","errorOnRequiredField"]}]`) + require.EqualError( + t, + err, + `[{"message":"boom","path":["errorBubble","errorOnRequiredField"]}]`, + ) require.Nil(t, resp.ErrorBubble) require.Equal(t, "Ok", resp.Valid) }) @@ -68,7 +76,11 @@ func TestNullBubbling(t *testing.T) { } err := c.Post(`query { valid, errorBubble { id, nilOnRequiredField } }`, &resp) - require.EqualError(t, err, `[{"message":"the requested element is null which the schema does not allow","path":["errorBubble","nilOnRequiredField"]}]`) + require.EqualError( + t, + err, + `[{"message":"the requested element is null which the schema does not allow","path":["errorBubble","nilOnRequiredField"]}]`, + ) require.Nil(t, resp.ErrorBubble) require.Equal(t, "Ok", resp.Valid) }) @@ -93,8 +105,16 @@ func TestNullBubbling(t *testing.T) { } err := c.Post(`query { valid, errorBubbleList { id } }`, &resp) - require.Contains(t, err.Error(), `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",2]}`) - require.Contains(t, err.Error(), `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",1]}`) + require.Contains( + t, + err.Error(), + `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",2]}`, + ) + require.Contains( + t, + err.Error(), + `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",1]}`, + ) require.Nil(t, resp.ErrorBubbleList) require.Equal(t, "Ok", resp.Valid) }) @@ -130,6 +150,10 @@ func TestNullBubbling(t *testing.T) { } }`, &resp) require.Error(t, err) - require.Contains(t, err.Error(), "the requested element is null which the schema does not allow") + require.Contains( + t, + err.Error(), + "the requested element is null which the schema does not allow", + ) }) } diff --git a/codegen/testserver/singlefile/panics_test.go b/codegen/testserver/singlefile/panics_test.go index 209344d79d..dfdb7991fe 100644 --- a/codegen/testserver/singlefile/panics_test.go +++ b/codegen/testserver/singlefile/panics_test.go @@ -43,27 +43,43 @@ func TestPanics(t *testing.T) { var resp interface{} err := c.Post(`query { panics { fieldScalarMarshal } }`, &resp) - require.EqualError(t, err, "http 422: {\"errors\":[{\"message\":\"presented: panic: BOOM\"}],\"data\":null}") + require.EqualError( + t, + err, + "http 422: {\"errors\":[{\"message\":\"presented: panic: BOOM\"}],\"data\":null}", + ) }) t.Run("panics in unmarshalers will not kill server", func(t *testing.T) { var resp interface{} err := c.Post(`query { panics { argUnmarshal(u: ["aa", "bb"]) } }`, &resp) - require.EqualError(t, err, "[{\"message\":\"presented: input: panics.argUnmarshal panic: BOOM\",\"path\":[\"panics\",\"argUnmarshal\"]}]") + require.EqualError( + t, + err, + "[{\"message\":\"presented: input: panics.argUnmarshal panic: BOOM\",\"path\":[\"panics\",\"argUnmarshal\"]}]", + ) }) t.Run("panics in funcs unmarshal return errors", func(t *testing.T) { var resp interface{} err := c.Post(`query { panics { fieldFuncMarshal(u: ["aa", "bb"]) } }`, &resp) - require.EqualError(t, err, "[{\"message\":\"presented: input: panics.fieldFuncMarshal panic: BOOM\",\"path\":[\"panics\",\"fieldFuncMarshal\"]}]") + require.EqualError( + t, + err, + "[{\"message\":\"presented: input: panics.fieldFuncMarshal panic: BOOM\",\"path\":[\"panics\",\"fieldFuncMarshal\"]}]", + ) }) t.Run("panics in funcs marshal return errors", func(t *testing.T) { var resp interface{} err := c.Post(`query { panics { fieldFuncMarshal(u: []) } }`, &resp) - require.EqualError(t, err, "http 422: {\"errors\":[{\"message\":\"presented: panic: BOOM\"}],\"data\":null}") + require.EqualError( + t, + err, + "http 422: {\"errors\":[{\"message\":\"presented: panic: BOOM\"}],\"data\":null}", + ) }) } diff --git a/codegen/testserver/singlefile/ptr_to_ptr_input_test.go b/codegen/testserver/singlefile/ptr_to_ptr_input_test.go index 75bed1266c..5b5a697a99 100644 --- a/codegen/testserver/singlefile/ptr_to_ptr_input_test.go +++ b/codegen/testserver/singlefile/ptr_to_ptr_input_test.go @@ -73,7 +73,10 @@ func TestPtrToPtr(t *testing.T) { t.Run("pointer to pointer input missing", func(t *testing.T) { var resp UpdatePtrToPtrResults - err := c.Post(`mutation { updatePtrToPtr(input: { name: "newName" }) { name, inner { key, value }, stupidInner { key, value }}}`, &resp) + err := c.Post( + `mutation { updatePtrToPtr(input: { name: "newName" }) { name, inner { key, value }, stupidInner { key, value }}}`, + &resp, + ) require.NoError(t, err) require.Equal(t, resp.UpdatedPtrToPtr.Name, "newName") @@ -113,7 +116,10 @@ func TestPtrToPtr(t *testing.T) { t.Run("pointer to pointer input null", func(t *testing.T) { var resp UpdatePtrToPtrResults - err := c.Post(`mutation { updatePtrToPtr(input: { inner: null }) { name, inner { key, value }, stupidInner { key, value }}}`, &resp) + err := c.Post( + `mutation { updatePtrToPtr(input: { inner: null }) { name, inner { key, value }, stupidInner { key, value }}}`, + &resp, + ) require.NoError(t, err) require.Equal(t, resp.UpdatedPtrToPtr.Name, "oldName") @@ -151,7 +157,10 @@ func TestPtrToPtr(t *testing.T) { t.Run("many pointers input null", func(t *testing.T) { var resp UpdatePtrToPtrResults - err := c.Post(`mutation { updatePtrToPtr(input: { stupidInner: null }) { name, inner { key, value }, stupidInner { key, value }}}`, &resp) + err := c.Post( + `mutation { updatePtrToPtr(input: { stupidInner: null }) { name, inner { key, value }, stupidInner { key, value }}}`, + &resp, + ) require.NoError(t, err) require.Equal(t, resp.UpdatedPtrToPtr.Name, "oldName") diff --git a/codegen/testserver/singlefile/resolver.go b/codegen/testserver/singlefile/resolver.go index fae59734b1..f8e447af28 100644 --- a/codegen/testserver/singlefile/resolver.go +++ b/codegen/testserver/singlefile/resolver.go @@ -53,37 +53,59 @@ func (r *modelMethodsResolver) ResolverField(ctx context.Context, obj *ModelMeth } // // foo -func (r *mutationResolver) DefaultInput(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) { +func (r *mutationResolver) DefaultInput( + ctx context.Context, + input DefaultInput, +) (*DefaultParametersMirror, error) { panic("not implemented") } // // foo -func (r *mutationResolver) OverrideValueViaInput(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) { +func (r *mutationResolver) OverrideValueViaInput( + ctx context.Context, + input FieldsOrderInput, +) (*FieldsOrderPayload, error) { panic("not implemented") } // // foo -func (r *mutationResolver) UpdateSomething(ctx context.Context, input SpecialInput) (string, error) { +func (r *mutationResolver) UpdateSomething( + ctx context.Context, + input SpecialInput, +) (string, error) { panic("not implemented") } // // foo -func (r *mutationResolver) UpdatePtrToPtr(ctx context.Context, input UpdatePtrToPtrOuter) (*PtrToPtrOuter, error) { +func (r *mutationResolver) UpdatePtrToPtr( + ctx context.Context, + input UpdatePtrToPtrOuter, +) (*PtrToPtrOuter, error) { panic("not implemented") } // // foo -func (r *overlappingFieldsResolver) OldFoo(ctx context.Context, obj *OverlappingFields) (int, error) { +func (r *overlappingFieldsResolver) OldFoo( + ctx context.Context, + obj *OverlappingFields, +) (int, error) { panic("not implemented") } // // foo -func (r *panicsResolver) FieldScalarMarshal(ctx context.Context, obj *Panics) ([]MarshalPanic, error) { +func (r *panicsResolver) FieldScalarMarshal( + ctx context.Context, + obj *Panics, +) ([]MarshalPanic, error) { panic("not implemented") } // // foo -func (r *panicsResolver) ArgUnmarshal(ctx context.Context, obj *Panics, u []MarshalPanic) (bool, error) { +func (r *panicsResolver) ArgUnmarshal( + ctx context.Context, + obj *Panics, + u []MarshalPanic, +) (bool, error) { panic("not implemented") } @@ -108,7 +130,9 @@ func (r *primitiveStringResolver) Len(ctx context.Context, obj *PrimitiveString) } // // foo -func (r *queryResolver) InvalidIdentifier(ctx context.Context) (*invalid_packagename.InvalidIdentifier, error) { +func (r *queryResolver) InvalidIdentifier( + ctx context.Context, +) (*invalid_packagename.InvalidIdentifier, error) { panic("not implemented") } @@ -183,7 +207,11 @@ func (r *queryResolver) Overlapping(ctx context.Context) (*OverlappingFields, er } // // foo -func (r *queryResolver) DefaultParameters(ctx context.Context, falsyBoolean *bool, truthyBoolean *bool) (*DefaultParametersMirror, error) { +func (r *queryResolver) DefaultParameters( + ctx context.Context, + falsyBoolean *bool, + truthyBoolean *bool, +) (*DefaultParametersMirror, error) { panic("not implemented") } @@ -193,12 +221,20 @@ func (r *queryResolver) DirectiveArg(ctx context.Context, arg string) (*string, } // // foo -func (r *queryResolver) DirectiveNullableArg(ctx context.Context, arg *int, arg2 *int, arg3 *string) (*string, error) { +func (r *queryResolver) DirectiveNullableArg( + ctx context.Context, + arg *int, + arg2 *int, + arg3 *string, +) (*string, error) { panic("not implemented") } // // foo -func (r *queryResolver) DirectiveInputNullable(ctx context.Context, arg *InputDirectives) (*string, error) { +func (r *queryResolver) DirectiveInputNullable( + ctx context.Context, + arg *InputDirectives, +) (*string, error) { panic("not implemented") } @@ -218,7 +254,9 @@ func (r *queryResolver) DirectiveObject(ctx context.Context) (*ObjectDirectives, } // // foo -func (r *queryResolver) DirectiveObjectWithCustomGoModel(ctx context.Context) (*ObjectDirectivesWithCustomGoModel, error) { +func (r *queryResolver) DirectiveObjectWithCustomGoModel( + ctx context.Context, +) (*ObjectDirectivesWithCustomGoModel, error) { panic("not implemented") } @@ -258,7 +296,10 @@ func (r *queryResolver) EmbeddedCase3(ctx context.Context) (*EmbeddedCase3, erro } // // foo -func (r *queryResolver) EnumInInput(ctx context.Context, input *InputWithEnumValue) (EnumTest, error) { +func (r *queryResolver) EnumInInput( + ctx context.Context, + input *InputWithEnumValue, +) (EnumTest, error) { panic("not implemented") } @@ -303,12 +344,18 @@ func (r *queryResolver) Issue896a(ctx context.Context) ([]*CheckIssue896, error) } // // foo -func (r *queryResolver) MapStringInterface(ctx context.Context, in map[string]interface{}) (map[string]interface{}, error) { +func (r *queryResolver) MapStringInterface( + ctx context.Context, + in map[string]interface{}, +) (map[string]interface{}, error) { panic("not implemented") } // // foo -func (r *queryResolver) MapNestedStringInterface(ctx context.Context, in *NestedMapInput) (map[string]interface{}, error) { +func (r *queryResolver) MapNestedStringInterface( + ctx context.Context, + in *NestedMapInput, +) (map[string]interface{}, error) { panic("not implemented") } @@ -363,7 +410,9 @@ func (r *queryResolver) Infinity(ctx context.Context) (float64, error) { } // // foo -func (r *queryResolver) StringFromContextInterface(ctx context.Context) (*StringFromContextInterface, error) { +func (r *queryResolver) StringFromContextInterface( + ctx context.Context, +) (*StringFromContextInterface, error) { panic("not implemented") } @@ -388,7 +437,10 @@ func (r *queryResolver) ScalarSlice(ctx context.Context) ([]byte, error) { } // // foo -func (r *queryResolver) Fallback(ctx context.Context, arg FallbackToStringEncoding) (FallbackToStringEncoding, error) { +func (r *queryResolver) Fallback( + ctx context.Context, + arg FallbackToStringEncoding, +) (FallbackToStringEncoding, error) { panic("not implemented") } @@ -448,12 +500,20 @@ func (r *subscriptionResolver) InitPayload(ctx context.Context) (<-chan string, } // // foo -func (r *subscriptionResolver) DirectiveArg(ctx context.Context, arg string) (<-chan *string, error) { +func (r *subscriptionResolver) DirectiveArg( + ctx context.Context, + arg string, +) (<-chan *string, error) { panic("not implemented") } // // foo -func (r *subscriptionResolver) DirectiveNullableArg(ctx context.Context, arg *int, arg2 *int, arg3 *string) (<-chan *string, error) { +func (r *subscriptionResolver) DirectiveNullableArg( + ctx context.Context, + arg *int, + arg2 *int, + arg3 *string, +) (<-chan *string, error) { panic("not implemented") } @@ -546,18 +606,20 @@ func (r *Resolver) WrappedMap() WrappedMapResolver { return &wrappedMapResolver{ // WrappedSlice returns WrappedSliceResolver implementation. func (r *Resolver) WrappedSlice() WrappedSliceResolver { return &wrappedSliceResolver{r} } -type backedByInterfaceResolver struct{ *Resolver } -type errorsResolver struct{ *Resolver } -type forcedResolverResolver struct{ *Resolver } -type modelMethodsResolver struct{ *Resolver } -type mutationResolver struct{ *Resolver } -type overlappingFieldsResolver struct{ *Resolver } -type panicsResolver struct{ *Resolver } -type petResolver struct{ *Resolver } -type primitiveResolver struct{ *Resolver } -type primitiveStringResolver struct{ *Resolver } -type queryResolver struct{ *Resolver } -type subscriptionResolver struct{ *Resolver } -type userResolver struct{ *Resolver } -type wrappedMapResolver struct{ *Resolver } -type wrappedSliceResolver struct{ *Resolver } +type ( + backedByInterfaceResolver struct{ *Resolver } + errorsResolver struct{ *Resolver } + forcedResolverResolver struct{ *Resolver } + modelMethodsResolver struct{ *Resolver } + mutationResolver struct{ *Resolver } + overlappingFieldsResolver struct{ *Resolver } + panicsResolver struct{ *Resolver } + petResolver struct{ *Resolver } + primitiveResolver struct{ *Resolver } + primitiveStringResolver struct{ *Resolver } + queryResolver struct{ *Resolver } + subscriptionResolver struct{ *Resolver } + userResolver struct{ *Resolver } + wrappedMapResolver struct{ *Resolver } + wrappedSliceResolver struct{ *Resolver } +) diff --git a/codegen/testserver/singlefile/time_test.go b/codegen/testserver/singlefile/time_test.go index 90c8a0c539..60ddc4580f 100644 --- a/codegen/testserver/singlefile/time_test.go +++ b/codegen/testserver/singlefile/time_test.go @@ -40,7 +40,11 @@ func TestTime(t *testing.T) { } err := c.Post(`query { user(id: 1) { created } }`, &resp) - require.EqualError(t, err, `[{"message":"the requested element is null which the schema does not allow","path":["user","created"]}]`) + require.EqualError( + t, + err, + `[{"message":"the requested element is null which the schema does not allow","path":["user","created"]}]`, + ) }) t.Run("with values", func(t *testing.T) { diff --git a/codegen/testserver/singlefile/variadic.go b/codegen/testserver/singlefile/variadic.go index 9313606b29..0d90f6726d 100644 --- a/codegen/testserver/singlefile/variadic.go +++ b/codegen/testserver/singlefile/variadic.go @@ -9,6 +9,10 @@ type VariadicModel struct{} type VariadicModelOption func(*VariadicModel) -func (v VariadicModel) Value(ctx context.Context, rank int, opts ...VariadicModelOption) (string, error) { +func (v VariadicModel) Value( + ctx context.Context, + rank int, + opts ...VariadicModelOption, +) (string, error) { return strconv.Itoa(rank), nil } diff --git a/codegen/type.go b/codegen/type.go index 20b09dc975..8f6d53d944 100644 --- a/codegen/type.go +++ b/codegen/type.go @@ -21,7 +21,14 @@ func processType(ret map[string]*config.TypeReference, ref *config.TypeReference existingGQL := fmt.Sprintf("%v", existing.GQL) newGQL := fmt.Sprintf("%v", ref.GQL) if existingGQL != newGQL { - panic(fmt.Sprintf("non-unique key \"%s\", trying to replace %s with %s", key, existingGQL, newGQL)) + panic( + fmt.Sprintf( + "non-unique key \"%s\", trying to replace %s with %s", + key, + existingGQL, + newGQL, + ), + ) } } ret[key] = ref diff --git a/codegen/util.go b/codegen/util.go index fa2ceed3df..680c434933 100644 --- a/codegen/util.go +++ b/codegen/util.go @@ -13,7 +13,11 @@ func findGoNamedType(def types.Type) (*types.Named, error) { namedType, ok := def.(*types.Named) if !ok { - return nil, fmt.Errorf("expected %s to be a named type, instead found %T\n", def.String(), def) + return nil, fmt.Errorf( + "expected %s to be a named type, instead found %T\n", + def.String(), + def, + ) } return namedType, nil @@ -33,7 +37,11 @@ func findGoInterface(def types.Type) (*types.Interface, error) { underlying, ok := namedType.Underlying().(*types.Interface) if !ok { - return nil, fmt.Errorf("expected %s to be a named interface, instead found %s", def.String(), namedType.String()) + return nil, fmt.Errorf( + "expected %s to be a named interface, instead found %s", + def.String(), + namedType.String(), + ) } return underlying, nil diff --git a/complexity/complexity.go b/complexity/complexity.go index e3ecf7612d..716fb4bc56 100644 --- a/complexity/complexity.go +++ b/complexity/complexity.go @@ -5,7 +5,11 @@ import ( "github.com/vektah/gqlparser/v2/ast" ) -func Calculate(es graphql.ExecutableSchema, op *ast.OperationDefinition, vars map[string]interface{}) int { +func Calculate( + es graphql.ExecutableSchema, + op *ast.OperationDefinition, + vars map[string]interface{}, +) int { walker := complexityWalker{ es: es, schema: es.Schema(), @@ -56,7 +60,12 @@ func (cw complexityWalker) selectionSetComplexity(selectionSet ast.SelectionSet) return complexity } -func (cw complexityWalker) interfaceFieldComplexity(def *ast.Definition, field string, childComplexity int, args map[string]interface{}) int { +func (cw complexityWalker) interfaceFieldComplexity( + def *ast.Definition, + field string, + childComplexity int, + args map[string]interface{}, +) int { // Interfaces don't have their own separate field costs, so they have to assume the worst case. // We iterate over all implementors and choose the most expensive one. maxComplexity := 0 @@ -70,8 +79,13 @@ func (cw complexityWalker) interfaceFieldComplexity(def *ast.Definition, field s return maxComplexity } -func (cw complexityWalker) fieldComplexity(object, field string, childComplexity int, args map[string]interface{}) int { - if customComplexity, ok := cw.es.Complexity(object, field, childComplexity, args); ok && customComplexity >= childComplexity { +func (cw complexityWalker) fieldComplexity( + object, field string, + childComplexity int, + args map[string]interface{}, +) int { + if customComplexity, ok := cw.es.Complexity(object, field, childComplexity, args); ok && + customComplexity >= childComplexity { return customComplexity } // default complexity calculation diff --git a/graphql/cache.go b/graphql/cache.go index fe86ca3502..c101ddcdfd 100644 --- a/graphql/cache.go +++ b/graphql/cache.go @@ -11,7 +11,8 @@ type Cache interface { Add(ctx context.Context, key string, value interface{}) } -// MapCache is the simplest implementation of a cache, because it can not evict it should only be used in tests +// MapCache is the simplest implementation of a cache, because it can not evict it should only be +// used in tests type MapCache map[string]interface{} // Get looks up a key's value from the cache. @@ -25,5 +26,10 @@ func (m MapCache) Add(ctx context.Context, key string, value interface{}) { m[ke type NoCache struct{} -func (n NoCache) Get(ctx context.Context, key string) (value interface{}, ok bool) { return nil, false } -func (n NoCache) Add(ctx context.Context, key string, value interface{}) {} +func (n NoCache) Get( + ctx context.Context, + key string, +) (value interface{}, ok bool) { + return nil, false +} +func (n NoCache) Add(ctx context.Context, key string, value interface{}) {} diff --git a/graphql/coercion_test.go b/graphql/coercion_test.go index 60b230cbc0..658b4c0dc7 100644 --- a/graphql/coercion_test.go +++ b/graphql/coercion_test.go @@ -8,7 +8,6 @@ import ( ) func TestCoerceList(t *testing.T) { - mapInput := map[string]interface{}{ "test": "value", "nested": map[string]interface{}{ @@ -34,5 +33,4 @@ func TestCoerceList(t *testing.T) { assert.Equal(t, []interface{}{mapInput}, CoerceList([]interface{}{mapInput})) assert.Equal(t, []interface{}{mapInput}, CoerceList([]map[string]interface{}{mapInput})) assert.Empty(t, CoerceList(nil)) - } diff --git a/graphql/context_field.go b/graphql/context_field.go index 1f9a6e88db..29ae2616d4 100644 --- a/graphql/context_field.go +++ b/graphql/context_field.go @@ -18,7 +18,8 @@ type FieldContext struct { Parent *FieldContext // The name of the type this field belongs to Object string - // These are the args after processing, they can be mutated in middleware to change what the resolver will get. + // These are the args after processing, they can be mutated in middleware to change what the + // resolver will get. Args map[string]interface{} // The raw field Field CollectedField diff --git a/graphql/context_operation.go b/graphql/context_operation.go index 0518ecc6ba..bbb1215a3d 100644 --- a/graphql/context_operation.go +++ b/graphql/context_operation.go @@ -82,8 +82,9 @@ func CollectFieldsCtx(ctx context.Context, satisfies []string) []CollectedField return CollectFields(GetOperationContext(ctx), resctx.Field.Selections, satisfies) } -// CollectAllFields returns a slice of all GraphQL field names that were selected for the current resolver context. -// The slice will contain the unique set of all field names requested regardless of fragment type conditions. +// CollectAllFields returns a slice of all GraphQL field names that were selected for the current +// resolver context. The slice will contain the unique set of all field names requested regardless +// of fragment type conditions. func CollectAllFields(ctx context.Context) []string { resctx := GetFieldContext(ctx) collected := CollectFields(GetOperationContext(ctx), resctx.Field.Selections, nil) diff --git a/graphql/context_response.go b/graphql/context_response.go index c128fdb49c..b44577738e 100644 --- a/graphql/context_response.go +++ b/graphql/context_response.go @@ -29,7 +29,11 @@ func getResponseContext(ctx context.Context) *responseContext { return val } -func WithResponseContext(ctx context.Context, presenterFunc ErrorPresenterFunc, recoverFunc RecoverFunc) context.Context { +func WithResponseContext( + ctx context.Context, + presenterFunc ErrorPresenterFunc, + recoverFunc RecoverFunc, +) context.Context { return context.WithValue(ctx, resultCtx, &responseContext{ errorPresenter: presenterFunc, recover: recoverFunc, diff --git a/graphql/context_response_test.go b/graphql/context_response_test.go index acafe95aae..51e4777b54 100644 --- a/graphql/context_response_test.go +++ b/graphql/context_response_test.go @@ -81,13 +81,18 @@ func TestAddError(t *testing.T) { } func TestGetErrorFromPresenter(t *testing.T) { - ctx := WithResponseContext(context.Background(), func(ctx context.Context, err error) *gqlerror.Error { - errs := GetErrors(ctx) + ctx := WithResponseContext( + context.Background(), + func(ctx context.Context, err error) *gqlerror.Error { + errs := GetErrors(ctx) - // because we are still presenting the error it is not expected to be returned, but this should not deadlock. - require.Len(t, errs, 0) - return DefaultErrorPresenter(ctx, err) - }, nil) + // because we are still presenting the error it is not expected to be returned, but this + // should not deadlock. + require.Len(t, errs, 0) + return DefaultErrorPresenter(ctx, err) + }, + nil, + ) ctx = WithFieldContext(ctx, &FieldContext{}) AddError(ctx, errors.New("foo1")) diff --git a/graphql/executable_schema.go b/graphql/executable_schema.go index 6189162288..70e578a1cc 100644 --- a/graphql/executable_schema.go +++ b/graphql/executable_schema.go @@ -12,18 +12,32 @@ import ( type ExecutableSchema interface { Schema() *ast.Schema - Complexity(typeName, fieldName string, childComplexity int, args map[string]interface{}) (int, bool) + Complexity( + typeName, fieldName string, + childComplexity int, + args map[string]interface{}, + ) (int, bool) Exec(ctx context.Context) ResponseHandler } -// CollectFields returns the set of fields from an ast.SelectionSet where all collected fields satisfy at least one of the GraphQL types -// passed through satisfies. Providing an empty or nil slice for satisfies will return collect all fields regardless of fragment +// CollectFields returns the set of fields from an ast.SelectionSet where all collected fields +// satisfy at least one of the GraphQL types passed through satisfies. Providing an empty or nil +// slice for satisfies will return collect all fields regardless of fragment // type conditions. -func CollectFields(reqCtx *OperationContext, selSet ast.SelectionSet, satisfies []string) []CollectedField { +func CollectFields( + reqCtx *OperationContext, + selSet ast.SelectionSet, + satisfies []string, +) []CollectedField { return collectFields(reqCtx, selSet, satisfies, map[string]bool{}) } -func collectFields(reqCtx *OperationContext, selSet ast.SelectionSet, satisfies []string, visited map[string]bool) []CollectedField { +func collectFields( + reqCtx *OperationContext, + selSet ast.SelectionSet, + satisfies []string, + visited map[string]bool, +) []CollectedField { groupedFields := make([]CollectedField, 0, len(selSet)) for _, sel := range selSet { @@ -98,7 +112,13 @@ func instanceOf(val string, satisfies []string) bool { return false } -func getOrCreateAndAppendField(c *[]CollectedField, name string, alias string, objectDefinition *ast.Definition, creator func() CollectedField) *CollectedField { +func getOrCreateAndAppendField( + c *[]CollectedField, + name string, + alias string, + objectDefinition *ast.Definition, + creator func() CollectedField, +) *CollectedField { for i, cf := range *c { if cf.Name == name && cf.Alias == alias { if cf.ObjectDefinition == objectDefinition { diff --git a/graphql/executable_schema_mock.go b/graphql/executable_schema_mock.go index 5d7433162f..5e71cb8304 100644 --- a/graphql/executable_schema_mock.go +++ b/graphql/executable_schema_mock.go @@ -15,25 +15,25 @@ var _ ExecutableSchema = &ExecutableSchemaMock{} // ExecutableSchemaMock is a mock implementation of ExecutableSchema. // -// func TestSomethingThatUsesExecutableSchema(t *testing.T) { +// func TestSomethingThatUsesExecutableSchema(t *testing.T) { // -// // make and configure a mocked ExecutableSchema -// mockedExecutableSchema := &ExecutableSchemaMock{ -// ComplexityFunc: func(typeName string, fieldName string, childComplexity int, args map[string]interface{}) (int, bool) { -// panic("mock out the Complexity method") -// }, -// ExecFunc: func(ctx context.Context) ResponseHandler { -// panic("mock out the Exec method") -// }, -// SchemaFunc: func() *ast.Schema { -// panic("mock out the Schema method") -// }, -// } +// // make and configure a mocked ExecutableSchema +// mockedExecutableSchema := &ExecutableSchemaMock{ +// ComplexityFunc: func(typeName string, fieldName string, childComplexity int, args map[string]interface{}) (int, bool) { +// panic("mock out the Complexity method") +// }, +// ExecFunc: func(ctx context.Context) ResponseHandler { +// panic("mock out the Exec method") +// }, +// SchemaFunc: func() *ast.Schema { +// panic("mock out the Schema method") +// }, +// } // -// // use mockedExecutableSchema in code that requires ExecutableSchema -// // and then make assertions. +// // use mockedExecutableSchema in code that requires ExecutableSchema +// // and then make assertions. // -// } +// } type ExecutableSchemaMock struct { // ComplexityFunc mocks the Complexity method. ComplexityFunc func(typeName string, fieldName string, childComplexity int, args map[string]interface{}) (int, bool) @@ -95,7 +95,8 @@ func (mock *ExecutableSchemaMock) Complexity(typeName string, fieldName string, // ComplexityCalls gets all the calls that were made to Complexity. // Check the length with: -// len(mockedExecutableSchema.ComplexityCalls()) +// +// len(mockedExecutableSchema.ComplexityCalls()) func (mock *ExecutableSchemaMock) ComplexityCalls() []struct { TypeName string FieldName string @@ -132,7 +133,8 @@ func (mock *ExecutableSchemaMock) Exec(ctx context.Context) ResponseHandler { // ExecCalls gets all the calls that were made to Exec. // Check the length with: -// len(mockedExecutableSchema.ExecCalls()) +// +// len(mockedExecutableSchema.ExecCalls()) func (mock *ExecutableSchemaMock) ExecCalls() []struct { Ctx context.Context } { @@ -160,7 +162,8 @@ func (mock *ExecutableSchemaMock) Schema() *ast.Schema { // SchemaCalls gets all the calls that were made to Schema. // Check the length with: -// len(mockedExecutableSchema.SchemaCalls()) +// +// len(mockedExecutableSchema.SchemaCalls()) func (mock *ExecutableSchemaMock) SchemaCalls() []struct { } { var calls []struct { diff --git a/graphql/executor/executor_test.go b/graphql/executor/executor_test.go index cf1944bd9d..cc806b74fb 100644 --- a/graphql/executor/executor_test.go +++ b/graphql/executor/executor_test.go @@ -40,14 +40,18 @@ func TestExecutor(t *testing.T) { t.Run("invokes operation middleware in order", func(t *testing.T) { var calls []string - exec.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { - calls = append(calls, "first") - return next(ctx) - }) - exec.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { - calls = append(calls, "second") - return next(ctx) - }) + exec.AroundOperations( + func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + calls = append(calls, "first") + return next(ctx) + }, + ) + exec.AroundOperations( + func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + calls = append(calls, "second") + return next(ctx) + }, + ) resp := query(exec, "", "{name}") assert.Equal(t, `{"name":"test"}`, string(resp.Data)) @@ -56,14 +60,18 @@ func TestExecutor(t *testing.T) { t.Run("invokes response middleware in order", func(t *testing.T) { var calls []string - exec.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { - calls = append(calls, "first") - return next(ctx) - }) - exec.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { - calls = append(calls, "second") - return next(ctx) - }) + exec.AroundResponses( + func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + calls = append(calls, "first") + return next(ctx) + }, + ) + exec.AroundResponses( + func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + calls = append(calls, "second") + return next(ctx) + }, + ) resp := query(exec, "", "{name}") assert.Equal(t, `{"name":"test"}`, string(resp.Data)) @@ -72,14 +80,18 @@ func TestExecutor(t *testing.T) { t.Run("invokes root field middleware in order", func(t *testing.T) { var calls []string - exec.AroundRootFields(func(ctx context.Context, next graphql.RootResolver) graphql.Marshaler { - calls = append(calls, "first") - return next(ctx) - }) - exec.AroundRootFields(func(ctx context.Context, next graphql.RootResolver) graphql.Marshaler { - calls = append(calls, "second") - return next(ctx) - }) + exec.AroundRootFields( + func(ctx context.Context, next graphql.RootResolver) graphql.Marshaler { + calls = append(calls, "first") + return next(ctx) + }, + ) + exec.AroundRootFields( + func(ctx context.Context, next graphql.RootResolver) graphql.Marshaler { + calls = append(calls, "second") + return next(ctx) + }, + ) resp := query(exec, "", "{name}") assert.Equal(t, `{"name":"test"}`, string(resp.Data)) @@ -88,14 +100,18 @@ func TestExecutor(t *testing.T) { t.Run("invokes field middleware in order", func(t *testing.T) { var calls []string - exec.AroundFields(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { - calls = append(calls, "first") - return next(ctx) - }) - exec.AroundFields(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { - calls = append(calls, "second") - return next(ctx) - }) + exec.AroundFields( + func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { + calls = append(calls, "first") + return next(ctx) + }, + ) + exec.AroundFields( + func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { + calls = append(calls, "second") + return next(ctx) + }, + ) resp := query(exec, "", "{name}") assert.Equal(t, `{"name":"test"}`, string(resp.Data)) @@ -124,12 +140,14 @@ func TestExecutor(t *testing.T) { t.Run("get query parse error in AroundResponses", func(t *testing.T) { var errors1 gqlerror.List var errors2 gqlerror.List - exec.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { - resp := next(ctx) - errors1 = graphql.GetErrors(ctx) - errors2 = resp.Errors - return resp - }) + exec.AroundResponses( + func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + resp := next(ctx) + errors1 = graphql.GetErrors(ctx) + errors2 = resp.Errors + return resp + }, + ) resp := query(exec, "", "invalid") assert.Equal(t, "", string(resp.Data)) @@ -180,7 +198,10 @@ func (m *testParamMutator) Validate(s graphql.ExecutableSchema) error { return nil } -func (m *testParamMutator) MutateOperationParameters(ctx context.Context, r *graphql.RawParams) *gqlerror.Error { +func (m *testParamMutator) MutateOperationParameters( + ctx context.Context, + r *graphql.RawParams, +) *gqlerror.Error { return m.Mutate(ctx, r) } @@ -196,7 +217,10 @@ func (m *testCtxMutator) Validate(s graphql.ExecutableSchema) error { return nil } -func (m *testCtxMutator) MutateOperationContext(ctx context.Context, rc *graphql.OperationContext) *gqlerror.Error { +func (m *testCtxMutator) MutateOperationContext( + ctx context.Context, + rc *graphql.OperationContext, +) *gqlerror.Error { return m.Mutate(ctx, rc) } @@ -206,12 +230,14 @@ func TestErrorServer(t *testing.T) { t.Run("get resolver error in AroundResponses", func(t *testing.T) { var errors1 gqlerror.List var errors2 gqlerror.List - exec.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { - resp := next(ctx) - errors1 = graphql.GetErrors(ctx) - errors2 = resp.Errors - return resp - }) + exec.AroundResponses( + func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + resp := next(ctx) + errors1 = graphql.GetErrors(ctx) + errors2 = resp.Errors + return resp + }, + ) resp := query(exec, "", "{name}") assert.Equal(t, "null", string(resp.Data)) diff --git a/graphql/executor/extensions.go b/graphql/executor/extensions.go index a8eebf110c..4eea5d09d1 100644 --- a/graphql/executor/extensions.go +++ b/graphql/executor/extensions.go @@ -28,22 +28,26 @@ func (e *Executor) Use(extension graphql.HandlerExtension) { } } -// AroundFields is a convenience method for creating an extension that only implements field middleware +// AroundFields is a convenience method for creating an extension that only implements field +// middleware func (e *Executor) AroundFields(f graphql.FieldMiddleware) { e.Use(aroundFieldFunc(f)) } -// AroundRootFields is a convenience method for creating an extension that only implements root field middleware +// AroundRootFields is a convenience method for creating an extension that only implements root +// field middleware func (e *Executor) AroundRootFields(f graphql.RootFieldMiddleware) { e.Use(aroundRootFieldFunc(f)) } -// AroundOperations is a convenience method for creating an extension that only implements operation middleware +// AroundOperations is a convenience method for creating an extension that only implements operation +// middleware func (e *Executor) AroundOperations(f graphql.OperationMiddleware) { e.Use(aroundOpFunc(f)) } -// AroundResponses is a convenience method for creating an extension that only implements response middleware +// AroundResponses is a convenience method for creating an extension that only implements response +// middleware func (e *Executor) AroundResponses(f graphql.ResponseMiddleware) { e.Use(aroundRespFunc(f)) } @@ -106,9 +110,12 @@ func processExtensions(exts []graphql.HandlerExtension) extensions { if p, ok := p.(graphql.FieldInterceptor); ok { previous := e.fieldMiddleware e.fieldMiddleware = func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { - return p.InterceptField(ctx, func(ctx context.Context) (res interface{}, err error) { - return previous(ctx, next) - }) + return p.InterceptField( + ctx, + func(ctx context.Context) (res interface{}, err error) { + return previous(ctx, next) + }, + ) } } } @@ -139,7 +146,10 @@ func (r aroundOpFunc) Validate(schema graphql.ExecutableSchema) error { return nil } -func (r aroundOpFunc) InterceptOperation(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { +func (r aroundOpFunc) InterceptOperation( + ctx context.Context, + next graphql.OperationHandler, +) graphql.ResponseHandler { return r(ctx, next) } @@ -156,7 +166,10 @@ func (r aroundRespFunc) Validate(schema graphql.ExecutableSchema) error { return nil } -func (r aroundRespFunc) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { +func (r aroundRespFunc) InterceptResponse( + ctx context.Context, + next graphql.ResponseHandler, +) *graphql.Response { return r(ctx, next) } @@ -173,7 +186,10 @@ func (f aroundFieldFunc) Validate(schema graphql.ExecutableSchema) error { return nil } -func (f aroundFieldFunc) InterceptField(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { +func (f aroundFieldFunc) InterceptField( + ctx context.Context, + next graphql.Resolver, +) (res interface{}, err error) { return f(ctx, next) } @@ -190,6 +206,9 @@ func (f aroundRootFieldFunc) Validate(schema graphql.ExecutableSchema) error { return nil } -func (f aroundRootFieldFunc) InterceptRootField(ctx context.Context, next graphql.RootResolver) graphql.Marshaler { +func (f aroundRootFieldFunc) InterceptRootField( + ctx context.Context, + next graphql.RootResolver, +) graphql.Marshaler { return f(ctx, next) } diff --git a/graphql/executor/testexecutor/testexecutor.go b/graphql/executor/testexecutor/testexecutor.go index bf8fd9850f..9190ac4d02 100644 --- a/graphql/executor/testexecutor/testexecutor.go +++ b/graphql/executor/testexecutor/testexecutor.go @@ -34,8 +34,9 @@ func (mr *MockResponse) MarshalGQL(w io.Writer) { fmt.Fprint(w, ba) } -// New provides a server for use in tests that isn't relying on generated code. It isnt a perfect reproduction of -// a generated server, but it aims to be good enough to test the handler package without relying on codegen. +// New provides a server for use in tests that isn't relying on generated code. It isnt a perfect +// reproduction of a generated server, but it aims to be good enough to test the handler package +// without relying on codegen. func New() *TestExecutor { next := make(chan struct{}) @@ -78,17 +79,20 @@ func New() *TestExecutor { }, }, }) - data := graphql.GetOperationContext(ctx).RootResolverMiddleware(ctx, func(ctx context.Context) graphql.Marshaler { - res, err := graphql.GetOperationContext(ctx).ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) { - // return &graphql.Response{Data: []byte(`{"name":"test"}`)}, nil - return &MockResponse{Name: "test"}, nil + data := graphql.GetOperationContext(ctx). + RootResolverMiddleware(ctx, func(ctx context.Context) graphql.Marshaler { + res, err := graphql.GetOperationContext(ctx). + ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) { + // return &graphql.Response{Data: []byte(`{"name":"test"}`)}, + // nil + return &MockResponse{Name: "test"}, nil + }) + if err != nil { + panic(err) + } + + return res.(*MockResponse) }) - if err != nil { - panic(err) - } - - return res.(*MockResponse) - }) var buf bytes.Buffer data.MarshalGQL(&buf) @@ -124,8 +128,9 @@ func New() *TestExecutor { return exec } -// NewError provides a server for use in resolver error tests that isn't relying on generated code. It isnt a perfect reproduction of -// a generated server, but it aims to be good enough to test the handler package without relying on codegen. +// NewError provides a server for use in resolver error tests that isn't relying on generated code. +// It isnt a perfect reproduction of a generated server, but it aims to be good enough to test the +// handler package without relying on codegen. func NewError() *TestExecutor { next := make(chan struct{}) diff --git a/graphql/fieldset.go b/graphql/fieldset.go index 351e266fdb..5e08fa2181 100644 --- a/graphql/fieldset.go +++ b/graphql/fieldset.go @@ -33,7 +33,8 @@ func (m *FieldSet) Dispatch() { d := m.delayed[0] m.Values[d.i] = d.f() } else if len(m.delayed) > 1 { - // more than one concurrent task, use the main goroutine to do one, only spawn goroutines for the others + // more than one concurrent task, use the main goroutine to do one, only spawn goroutines + // for the others var wg sync.WaitGroup for _, d := range m.delayed[1:] { diff --git a/graphql/handler.go b/graphql/handler.go index cd358740c8..9289799eed 100644 --- a/graphql/handler.go +++ b/graphql/handler.go @@ -33,13 +33,20 @@ type ( } GraphExecutor interface { - CreateOperationContext(ctx context.Context, params *RawParams) (*OperationContext, gqlerror.List) - DispatchOperation(ctx context.Context, rc *OperationContext) (ResponseHandler, context.Context) + CreateOperationContext( + ctx context.Context, + params *RawParams, + ) (*OperationContext, gqlerror.List) + DispatchOperation( + ctx context.Context, + rc *OperationContext, + ) (ResponseHandler, context.Context) DispatchError(ctx context.Context, list gqlerror.List) *Response } - // HandlerExtension adds functionality to the http handler. See the list of possible hook points below - // Its important to understand the lifecycle of a graphql request and the terminology we use in gqlgen + // HandlerExtension adds functionality to the http handler. See the list of possible hook points + // below Its important to understand the lifecycle of a graphql request and the terminology we + // use in gqlgen // before working with these // // +--- REQUEST POST /graphql --------------------------------------------+ @@ -51,30 +58,36 @@ type ( // | +--------------------------------------------------------------------+ | // +------------------------------------------------------------------------+ HandlerExtension interface { - // ExtensionName should be a CamelCase string version of the extension which may be shown in stats and logging. + // ExtensionName should be a CamelCase string version of the extension which may be shown in + // stats and logging. ExtensionName() string - // Validate is called when adding an extension to the server, it allows validation against the servers schema. + // Validate is called when adding an extension to the server, it allows validation against + // the servers schema. Validate(schema ExecutableSchema) error } - // OperationParameterMutator is called before creating a request context. allows manipulating the raw query + // OperationParameterMutator is called before creating a request context. allows manipulating + // the raw query // on the way in. OperationParameterMutator interface { MutateOperationParameters(ctx context.Context, request *RawParams) *gqlerror.Error } - // OperationContextMutator is called after creating the request context, but before executing the root resolver. + // OperationContextMutator is called after creating the request context, but before executing + // the root resolver. OperationContextMutator interface { MutateOperationContext(ctx context.Context, rc *OperationContext) *gqlerror.Error } - // OperationInterceptor is called for each incoming query, for basic requests the writer will be invoked once, + // OperationInterceptor is called for each incoming query, for basic requests the writer will be + // invoked once, // for subscriptions it will be invoked multiple times. OperationInterceptor interface { InterceptOperation(ctx context.Context, next OperationHandler) ResponseHandler } - // ResponseInterceptor is called around each graphql operation response. This can be called many times for a single + // ResponseInterceptor is called around each graphql operation response. This can be called many + // times for a single // operation the case of subscriptions. ResponseInterceptor interface { InterceptResponse(ctx context.Context, next ResponseHandler) *Response @@ -89,7 +102,8 @@ type ( InterceptField(ctx context.Context, next Resolver) (res interface{}, err error) } - // Transport provides support for different wire level encodings of graphql requests, eg Form, Get, Post, Websocket + // Transport provides support for different wire level encodings of graphql requests, eg Form, + // Get, Post, Websocket Transport interface { Supports(r *http.Request) bool Do(w http.ResponseWriter, r *http.Request, exec GraphExecutor) @@ -110,7 +124,11 @@ func (p *RawParams) AddUpload(upload Upload, key, path string) *gqlerror.Error { for i, p := range parts[1:] { last := i == len(parts)-2 if ptr == nil { - return gqlerror.Errorf("path is missing \"variables.\" prefix, key: %s, path: %s", key, path) + return gqlerror.Errorf( + "path is missing \"variables.\" prefix, key: %s, path: %s", + key, + path, + ) } if index, parseNbrErr := strconv.Atoi(p); parseNbrErr == nil { if last { diff --git a/graphql/handler/apollofederatedtracingv1/tracing.go b/graphql/handler/apollofederatedtracingv1/tracing.go index 689c3c0640..a3df5b97e1 100644 --- a/graphql/handler/apollofederatedtracingv1/tracing.go +++ b/graphql/handler/apollofederatedtracingv1/tracing.go @@ -35,7 +35,8 @@ func (Tracer) ExtensionName() string { return "ApolloFederatedTracingV1" } -// Validate returns errors based on the schema; since this extension doesn't require validation, we return nil +// Validate returns errors based on the schema; since this extension doesn't require validation, we +// return nil func (Tracer) Validate(graphql.ExecutableSchema) error { return nil } @@ -55,15 +56,20 @@ func (t *Tracer) getTreeBuilder(ctx context.Context) *TreeBuilder { return nil } -// InterceptOperation acts on each Graph operation; on each operation, start a tree builder and start the tree's timer for tracing -func (t *Tracer) InterceptOperation(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { +// InterceptOperation acts on each Graph operation; on each operation, start a tree builder and +// start the tree's timer for tracing +func (t *Tracer) InterceptOperation( + ctx context.Context, + next graphql.OperationHandler, +) graphql.ResponseHandler { if !t.shouldTrace(ctx) { return next(ctx) } return next(context.WithValue(ctx, key, NewTreeBuilder())) } -// InterceptField is called on each field's resolution, including information about the path and parent node. +// InterceptField is called on each field's resolution, including information about the path and +// parent node. // This information is then used to build the relevant Node Tree used in the FTV1 tracing format func (t *Tracer) InterceptField(ctx context.Context, next graphql.Resolver) (interface{}, error) { if !t.shouldTrace(ctx) { @@ -76,9 +82,13 @@ func (t *Tracer) InterceptField(ctx context.Context, next graphql.Resolver) (int return next(ctx) } -// InterceptResponse is called before the overall response is sent, but before each field resolves; as a result +// InterceptResponse is called before the overall response is sent, but before each field resolves; +// as a result // the final marshaling is deferred to happen at the end of the operation -func (t *Tracer) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { +func (t *Tracer) InterceptResponse( + ctx context.Context, + next graphql.ResponseHandler, +) *graphql.Response { if !t.shouldTrace(ctx) { return next(ctx) } @@ -100,7 +110,8 @@ func (t *Tracer) InterceptResponse(ctx context.Context, next graphql.ResponseHan fmt.Print(err) } - // ... then set the previously instantiated string as the base64 formatted string as required + // ... then set the previously instantiated string as the base64 formatted string as + // required *val = base64.StdEncoding.EncodeToString(p) }(val) resp := next(ctx) diff --git a/graphql/handler/apollofederatedtracingv1/tracing_test.go b/graphql/handler/apollofederatedtracingv1/tracing_test.go index 9ed91f91f8..cd1b48c419 100644 --- a/graphql/handler/apollofederatedtracingv1/tracing_test.go +++ b/graphql/handler/apollofederatedtracingv1/tracing_test.go @@ -91,7 +91,12 @@ func TestApolloTracing_withFail(t *testing.T) { h.Use(extension.AutomaticPersistedQuery{Cache: lru.New(100)}) h.Use(apollotracing.Tracer{}) - resp := doRequest(h, http.MethodPost, "/graphql", `{"operationName":"A","extensions":{"persistedQuery":{"version":1,"sha256Hash":"338bbc16ac780daf81845339fbf0342061c1e9d2b702c96d3958a13a557083a6"}}}`) + resp := doRequest( + h, + http.MethodPost, + "/graphql", + `{"operationName":"A","extensions":{"persistedQuery":{"version":1,"sha256Hash":"338bbc16ac780daf81845339fbf0342061c1e9d2b702c96d3958a13a557083a6"}}}`, + ) assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) b := resp.Body.Bytes() t.Log(string(b)) @@ -115,7 +120,10 @@ func doRequest(handler http.Handler, method, target, body string) *httptest.Resp type delayMiddleware struct{} -func (*delayMiddleware) InterceptOperation(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { +func (*delayMiddleware) InterceptOperation( + ctx context.Context, + next graphql.OperationHandler, +) graphql.ResponseHandler { time.Sleep(time.Millisecond) return next(ctx) } diff --git a/graphql/handler/apollofederatedtracingv1/tree_builder.go b/graphql/handler/apollofederatedtracingv1/tree_builder.go index a54b12db58..2d827a9fd8 100644 --- a/graphql/handler/apollofederatedtracingv1/tree_builder.go +++ b/graphql/handler/apollofederatedtracingv1/tree_builder.go @@ -26,7 +26,8 @@ type NodeMap struct { parent *generated.Trace_Node } -// NewTreeBuilder is used to start the node tree with a default root node, along with the related tree nodes map entry +// NewTreeBuilder is used to start the node tree with a default root node, along with the related +// tree nodes map entry func NewTreeBuilder() *TreeBuilder { tb := TreeBuilder{ rootNode: generated.Trace_Node{}, @@ -59,7 +60,8 @@ func (tb *TreeBuilder) StartTimer(ctx context.Context) { tb.startTime = &start } -// StopTimer marks the end of the timer, along with setting the related fields in the protobuf representation +// StopTimer marks the end of the timer, along with setting the related fields in the protobuf +// representation func (tb *TreeBuilder) StopTimer(ctx context.Context) { if tb.startTime == nil { fmt.Println(fmt.Errorf("StopTimer called before StartTimer")) @@ -74,8 +76,9 @@ func (tb *TreeBuilder) StopTimer(ctx context.Context) { tb.stopped = true } -// On each field, it calculates the time started at as now - tree.StartTime, as well as a deferred function upon full resolution of the -// field as now - tree.StartTime; these are used by Apollo to calculate how fields are being resolved in the AST +// On each field, it calculates the time started at as now - tree.StartTime, as well as a deferred +// function upon full resolution of the field as now - tree.StartTime; these are used by Apollo to +// calculate how fields are being resolved in the AST func (tb *TreeBuilder) WillResolveField(ctx context.Context) { if tb.startTime == nil { fmt.Println(fmt.Errorf("WillResolveField called before StartTimer")) @@ -97,7 +100,8 @@ func (tb *TreeBuilder) WillResolveField(ctx context.Context) { node.ParentType = fc.Object } -// newNode is called on each new node within the AST and sets related values such as the entry in the tree.node map and ID attribute +// newNode is called on each new node within the AST and sets related values such as the entry in +// the tree.node map and ID attribute func (tb *TreeBuilder) newNode(path *graphql.FieldContext) *generated.Trace_Node { // if the path is empty, it is the root node of the operation if path.Path().String() == "" { diff --git a/graphql/handler/apollotracing/tracer.go b/graphql/handler/apollotracing/tracer.go index 4cfd1592bd..d13dbd6112 100644 --- a/graphql/handler/apollotracing/tracer.go +++ b/graphql/handler/apollotracing/tracer.go @@ -84,7 +84,10 @@ func (Tracer) InterceptField(ctx context.Context, next graphql.Resolver) (interf return next(ctx) } -func (Tracer) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { +func (Tracer) InterceptResponse( + ctx context.Context, + next graphql.ResponseHandler, +) *graphql.Response { rc := graphql.GetOperationContext(ctx) start := rc.Stats.OperationStart diff --git a/graphql/handler/apollotracing/tracer_test.go b/graphql/handler/apollotracing/tracer_test.go index 0b0f30ef2a..304c8a69a3 100644 --- a/graphql/handler/apollotracing/tracer_test.go +++ b/graphql/handler/apollotracing/tracer_test.go @@ -80,7 +80,12 @@ func TestApolloTracing_withFail(t *testing.T) { h.Use(extension.AutomaticPersistedQuery{Cache: lru.New(100)}) h.Use(apollotracing.Tracer{}) - resp := doRequest(h, http.MethodPost, "/graphql", `{"operationName":"A","extensions":{"persistedQuery":{"version":1,"sha256Hash":"338bbc16ac780daf81845339fbf0342061c1e9d2b702c96d3958a13a557083a6"}}}`) + resp := doRequest( + h, + http.MethodPost, + "/graphql", + `{"operationName":"A","extensions":{"persistedQuery":{"version":1,"sha256Hash":"338bbc16ac780daf81845339fbf0342061c1e9d2b702c96d3958a13a557083a6"}}}`, + ) assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) b := resp.Body.Bytes() t.Log(string(b)) diff --git a/graphql/handler/debug/tracer.go b/graphql/handler/debug/tracer.go index be516997d3..125f134b72 100644 --- a/graphql/handler/debug/tracer.go +++ b/graphql/handler/debug/tracer.go @@ -48,7 +48,10 @@ func stringify(value interface{}) string { return fmt.Sprint(value) } -func (a Tracer) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { +func (a Tracer) InterceptResponse( + ctx context.Context, + next graphql.ResponseHandler, +) *graphql.Response { rctx := graphql.GetOperationContext(ctx) fmt.Fprintln(a.out, "GraphQL Request {") diff --git a/graphql/handler/extension/apq.go b/graphql/handler/extension/apq.go index 866276eed9..5bb2fd0a52 100644 --- a/graphql/handler/extension/apq.go +++ b/graphql/handler/extension/apq.go @@ -19,8 +19,9 @@ const ( errPersistedQueryNotFoundCode = "PERSISTED_QUERY_NOT_FOUND" ) -// AutomaticPersistedQuery saves client upload by optimistically sending only the hashes of queries, if the server -// does not yet know what the query is for the hash it will respond telling the client to send the query along with the +// AutomaticPersistedQuery saves client upload by optimistically sending only the hashes of queries, +// if the server does not yet know what the query is for the hash it will respond telling the client +// to send the query along with the // hash in the next request. // see https://github.com/apollographql/apollo-link-persisted-queries type AutomaticPersistedQuery struct { @@ -53,7 +54,10 @@ func (a AutomaticPersistedQuery) Validate(schema graphql.ExecutableSchema) error return nil } -func (a AutomaticPersistedQuery) MutateOperationParameters(ctx context.Context, rawParams *graphql.RawParams) *gqlerror.Error { +func (a AutomaticPersistedQuery) MutateOperationParameters( + ctx context.Context, + rawParams *graphql.RawParams, +) *gqlerror.Error { if rawParams.Extensions["persistedQuery"] == nil { return nil } diff --git a/graphql/handler/extension/apq_test.go b/graphql/handler/extension/apq_test.go index 66970c62e9..108525fe1f 100644 --- a/graphql/handler/extension/apq_test.go +++ b/graphql/handler/extension/apq_test.go @@ -23,7 +23,12 @@ func TestAPQIntegration(t *testing.T) { return next(ctx) }) - resp := doRequest(h, "POST", "/graphql", `{"query":"{ name }","extensions":{"persistedQuery":{"version":1,"sha256Hash":"30166fc3298853f22709fce1e4a00e98f1b6a3160eaaaf9cb3b7db6a16073b07"}}}`) + resp := doRequest( + h, + "POST", + "/graphql", + `{"query":"{ name }","extensions":{"persistedQuery":{"version":1,"sha256Hash":"30166fc3298853f22709fce1e4a00e98f1b6a3160eaaaf9cb3b7db6a16073b07"}}}`, + ) require.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) require.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String()) @@ -41,7 +46,12 @@ func TestAPQ(t *testing.T) { params := &graphql.RawParams{ Query: "original query", } - err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) + err := extension.AutomaticPersistedQuery{ + graphql.MapCache{}, + }.MutateOperationParameters( + ctx, + params, + ) require.Nil(t, err) require.Equal(t, "original query", params.Query) @@ -58,7 +68,12 @@ func TestAPQ(t *testing.T) { }, } - err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) + err := extension.AutomaticPersistedQuery{ + graphql.MapCache{}, + }.MutateOperationParameters( + ctx, + params, + ) require.Equal(t, err.Message, "PersistedQueryNotFound") }) @@ -127,7 +142,12 @@ func TestAPQ(t *testing.T) { }, } - err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) + err := extension.AutomaticPersistedQuery{ + graphql.MapCache{}, + }.MutateOperationParameters( + ctx, + params, + ) require.Equal(t, err.Message, "invalid APQ extension data") }) @@ -140,7 +160,12 @@ func TestAPQ(t *testing.T) { }, }, } - err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) + err := extension.AutomaticPersistedQuery{ + graphql.MapCache{}, + }.MutateOperationParameters( + ctx, + params, + ) require.Equal(t, err.Message, "unsupported APQ version") }) @@ -156,7 +181,12 @@ func TestAPQ(t *testing.T) { }, } - err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) + err := extension.AutomaticPersistedQuery{ + graphql.MapCache{}, + }.MutateOperationParameters( + ctx, + params, + ) require.Equal(t, err.Message, "provided APQ hash does not match query") }) } diff --git a/graphql/handler/extension/complexity.go b/graphql/handler/extension/complexity.go index 2d853802bf..8ebbd55891 100644 --- a/graphql/handler/extension/complexity.go +++ b/graphql/handler/extension/complexity.go @@ -57,7 +57,10 @@ func (c *ComplexityLimit) Validate(schema graphql.ExecutableSchema) error { return nil } -func (c ComplexityLimit) MutateOperationContext(ctx context.Context, rc *graphql.OperationContext) *gqlerror.Error { +func (c ComplexityLimit) MutateOperationContext( + ctx context.Context, + rc *graphql.OperationContext, +) *gqlerror.Error { op := rc.Doc.Operations.ForName(rc.OperationName) complexity := complexity.Calculate(c.es, op, rc.Variables) @@ -69,7 +72,11 @@ func (c ComplexityLimit) MutateOperationContext(ctx context.Context, rc *graphql }) if complexity > limit { - err := gqlerror.Errorf("operation has complexity %d, which exceeds the limit of %d", complexity, limit) + err := gqlerror.Errorf( + "operation has complexity %d, which exceeds the limit of %d", + complexity, + limit, + ) errcode.Set(err, errComplexityLimit) return err } diff --git a/graphql/handler/extension/complexity_test.go b/graphql/handler/extension/complexity_test.go index e533403e1a..21044e0729 100644 --- a/graphql/handler/extension/complexity_test.go +++ b/graphql/handler/extension/complexity_test.go @@ -47,7 +47,11 @@ func TestHandlerComplexity(t *testing.T) { h.SetCalculatedComplexity(4) resp := doRequest(h, "POST", "/graphql", `{"query":"{ name }"}`) require.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) - require.Equal(t, `{"errors":[{"message":"operation has complexity 4, which exceeds the limit of 2","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}],"data":null}`, resp.Body.String()) + require.Equal( + t, + `{"errors":[{"message":"operation has complexity 4, which exceeds the limit of 2","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}],"data":null}`, + resp.Body.String(), + ) require.Equal(t, 2, stats.ComplexityLimit) require.Equal(t, 4, stats.Complexity) @@ -90,7 +94,11 @@ func TestFixedComplexity(t *testing.T) { h.SetCalculatedComplexity(4) resp := doRequest(h, "POST", "/graphql", `{"query":"{ name }"}`) require.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) - require.Equal(t, `{"errors":[{"message":"operation has complexity 4, which exceeds the limit of 2","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}],"data":null}`, resp.Body.String()) + require.Equal( + t, + `{"errors":[{"message":"operation has complexity 4, which exceeds the limit of 2","extensions":{"code":"COMPLEXITY_LIMIT_EXCEEDED"}}],"data":null}`, + resp.Body.String(), + ) require.Equal(t, 2, stats.ComplexityLimit) require.Equal(t, 4, stats.Complexity) @@ -98,7 +106,12 @@ func TestFixedComplexity(t *testing.T) { t.Run("bypass __schema field", func(t *testing.T) { h.SetCalculatedComplexity(4) - resp := doRequest(h, "POST", "/graphql", `{ "operationName":"IntrospectionQuery", "query":"query IntrospectionQuery { __schema { queryType { name } mutationType { name }}}"}`) + resp := doRequest( + h, + "POST", + "/graphql", + `{ "operationName":"IntrospectionQuery", "query":"query IntrospectionQuery { __schema { queryType { name } mutationType { name }}}"}`, + ) require.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) require.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String()) @@ -107,7 +120,12 @@ func TestFixedComplexity(t *testing.T) { }) } -func doRequest(handler http.Handler, method string, target string, body string) *httptest.ResponseRecorder { +func doRequest( + handler http.Handler, + method string, + target string, + body string, +) *httptest.ResponseRecorder { r := httptest.NewRequest(method, target, strings.NewReader(body)) r.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() diff --git a/graphql/handler/extension/introspection.go b/graphql/handler/extension/introspection.go index acc5db2fbc..421e866dd2 100644 --- a/graphql/handler/extension/introspection.go +++ b/graphql/handler/extension/introspection.go @@ -23,7 +23,10 @@ func (c Introspection) Validate(schema graphql.ExecutableSchema) error { return nil } -func (c Introspection) MutateOperationContext(ctx context.Context, rc *graphql.OperationContext) *gqlerror.Error { +func (c Introspection) MutateOperationContext( + ctx context.Context, + rc *graphql.OperationContext, +) *gqlerror.Error { rc.DisableIntrospection = false return nil } diff --git a/graphql/handler/server.go b/graphql/handler/server.go index b6524d8da1..327f011512 100644 --- a/graphql/handler/server.go +++ b/graphql/handler/server.go @@ -69,22 +69,26 @@ func (s *Server) Use(extension graphql.HandlerExtension) { s.exec.Use(extension) } -// AroundFields is a convenience method for creating an extension that only implements field middleware +// AroundFields is a convenience method for creating an extension that only implements field +// middleware func (s *Server) AroundFields(f graphql.FieldMiddleware) { s.exec.AroundFields(f) } -// AroundRootFields is a convenience method for creating an extension that only implements field middleware +// AroundRootFields is a convenience method for creating an extension that only implements field +// middleware func (s *Server) AroundRootFields(f graphql.RootFieldMiddleware) { s.exec.AroundRootFields(f) } -// AroundOperations is a convenience method for creating an extension that only implements operation middleware +// AroundOperations is a convenience method for creating an extension that only implements operation +// middleware func (s *Server) AroundOperations(f graphql.OperationMiddleware) { s.exec.AroundOperations(f) } -// AroundResponses is a convenience method for creating an extension that only implements response middleware +// AroundResponses is a convenience method for creating an extension that only implements response +// middleware func (s *Server) AroundResponses(f graphql.ResponseMiddleware) { s.exec.AroundResponses(f) } @@ -147,7 +151,10 @@ func (r OperationFunc) Validate(schema graphql.ExecutableSchema) error { return nil } -func (r OperationFunc) InterceptOperation(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { +func (r OperationFunc) InterceptOperation( + ctx context.Context, + next graphql.OperationHandler, +) graphql.ResponseHandler { return r(ctx, next) } @@ -164,7 +171,10 @@ func (r ResponseFunc) Validate(schema graphql.ExecutableSchema) error { return nil } -func (r ResponseFunc) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { +func (r ResponseFunc) InterceptResponse( + ctx context.Context, + next graphql.ResponseHandler, +) *graphql.Response { return r(ctx, next) } @@ -181,6 +191,9 @@ func (f FieldFunc) Validate(schema graphql.ExecutableSchema) error { return nil } -func (f FieldFunc) InterceptField(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { +func (f FieldFunc) InterceptField( + ctx context.Context, + next graphql.Resolver, +) (res interface{}, err error) { return f(ctx, next) } diff --git a/graphql/handler/server_test.go b/graphql/handler/server_test.go index e00d06a8d6..cd712b1d65 100644 --- a/graphql/handler/server_test.go +++ b/graphql/handler/server_test.go @@ -25,7 +25,11 @@ func TestServer(t *testing.T) { t.Run("returns an error if no transport matches", func(t *testing.T) { resp := post(srv, "/foo", "application/json") assert.Equal(t, http.StatusBadRequest, resp.Code) - assert.Equal(t, `{"errors":[{"message":"transport not supported"}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"transport not supported"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("calls query on executable schema", func(t *testing.T) { @@ -37,25 +41,37 @@ func TestServer(t *testing.T) { t.Run("mutations are forbidden", func(t *testing.T) { resp := get(srv, "/foo?query=mutation{name}") assert.Equal(t, http.StatusNotAcceptable, resp.Code) - assert.Equal(t, `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("subscriptions are forbidden", func(t *testing.T) { resp := get(srv, "/foo?query=subscription{name}") assert.Equal(t, http.StatusNotAcceptable, resp.Code) - assert.Equal(t, `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("invokes operation middleware in order", func(t *testing.T) { var calls []string - srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { - calls = append(calls, "first") - return next(ctx) - }) - srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { - calls = append(calls, "second") - return next(ctx) - }) + srv.AroundOperations( + func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + calls = append(calls, "first") + return next(ctx) + }, + ) + srv.AroundOperations( + func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + calls = append(calls, "second") + return next(ctx) + }, + ) resp := get(srv, "/foo?query={name}") assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) @@ -64,14 +80,18 @@ func TestServer(t *testing.T) { t.Run("invokes response middleware in order", func(t *testing.T) { var calls []string - srv.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { - calls = append(calls, "first") - return next(ctx) - }) - srv.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { - calls = append(calls, "second") - return next(ctx) - }) + srv.AroundResponses( + func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + calls = append(calls, "first") + return next(ctx) + }, + ) + srv.AroundResponses( + func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + calls = append(calls, "second") + return next(ctx) + }, + ) resp := get(srv, "/foo?query={name}") assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) @@ -80,14 +100,18 @@ func TestServer(t *testing.T) { t.Run("invokes field middleware in order", func(t *testing.T) { var calls []string - srv.AroundFields(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { - calls = append(calls, "first") - return next(ctx) - }) - srv.AroundFields(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { - calls = append(calls, "second") - return next(ctx) - }) + srv.AroundFields( + func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { + calls = append(calls, "first") + return next(ctx) + }, + ) + srv.AroundFields( + func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { + calls = append(calls, "second") + return next(ctx) + }, + ) resp := get(srv, "/foo?query={name}") assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) @@ -97,12 +121,14 @@ func TestServer(t *testing.T) { t.Run("get query parse error in AroundResponses", func(t *testing.T) { var errors1 gqlerror.List var errors2 gqlerror.List - srv.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { - resp := next(ctx) - errors1 = graphql.GetErrors(ctx) - errors2 = resp.Errors - return resp - }) + srv.AroundResponses( + func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + resp := next(ctx) + errors1 = graphql.GetErrors(ctx) + errors2 = resp.Errors + return resp + }, + ) resp := get(srv, "/foo?query=invalid") assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) @@ -149,12 +175,14 @@ func TestErrorServer(t *testing.T) { t.Run("get resolver error in AroundResponses", func(t *testing.T) { var errors1 gqlerror.List var errors2 gqlerror.List - srv.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { - resp := next(ctx) - errors1 = graphql.GetErrors(ctx) - errors2 = resp.Errors - return resp - }) + srv.AroundResponses( + func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + resp := next(ctx) + errors1 = graphql.GetErrors(ctx) + errors2 = resp.Errors + return resp + }, + ) resp := get(srv, "/foo?query={name}") assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) diff --git a/graphql/handler/testserver/testserver.go b/graphql/handler/testserver/testserver.go index abe24f1cba..6fb02e6222 100644 --- a/graphql/handler/testserver/testserver.go +++ b/graphql/handler/testserver/testserver.go @@ -11,8 +11,9 @@ import ( "github.com/vektah/gqlparser/v2/ast" ) -// New provides a server for use in tests that isn't relying on generated code. It isnt a perfect reproduction of -// a generated server, but it aims to be good enough to test the handler package without relying on codegen. +// New provides a server for use in tests that isn't relying on generated code. It isnt a perfect +// reproduction of a generated server, but it aims to be good enough to test the handler package +// without relying on codegen. func New() *TestServer { next := make(chan struct{}) @@ -55,9 +56,10 @@ func New() *TestServer { }, }, }) - res, err := graphql.GetOperationContext(ctx).ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) { - return &graphql.Response{Data: []byte(`{"name":"test"}`)}, nil - }) + res, err := graphql.GetOperationContext(ctx). + ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) { + return &graphql.Response{Data: []byte(`{"name":"test"}`)}, nil + }) if err != nil { panic(err) } @@ -90,8 +92,9 @@ func New() *TestServer { return srv } -// NewError provides a server for use in resolver error tests that isn't relying on generated code. It isnt a perfect reproduction of -// a generated server, but it aims to be good enough to test the handler package without relying on codegen. +// NewError provides a server for use in resolver error tests that isn't relying on generated code. +// It isnt a perfect reproduction of a generated server, but it aims to be good enough to test the +// handler package without relying on codegen. func NewError() *TestServer { next := make(chan struct{}) diff --git a/graphql/handler/transport/error.go b/graphql/handler/transport/error.go index b1aeaf144d..405570f53b 100644 --- a/graphql/handler/transport/error.go +++ b/graphql/handler/transport/error.go @@ -9,7 +9,8 @@ import ( "github.com/vektah/gqlparser/v2/gqlerror" ) -// SendError sends a best effort error to a raw response writer. It assumes the client can understand the standard +// SendError sends a best effort error to a raw response writer. It assumes the client can +// understand the standard // json error response func SendError(w http.ResponseWriter, code int, errors ...*gqlerror.Error) { w.WriteHeader(code) diff --git a/graphql/handler/transport/http_form.go b/graphql/handler/transport/http_form.go index 3d3477b9ba..fa7e184c3f 100644 --- a/graphql/handler/transport/http_form.go +++ b/graphql/handler/transport/http_form.go @@ -10,7 +10,8 @@ import ( "github.com/99designs/gqlgen/graphql" ) -// MultipartForm the Multipart request spec https://github.com/jaydenseric/graphql-multipart-request-spec +// MultipartForm the Multipart request spec +// https://github.com/jaydenseric/graphql-multipart-request-spec type MultipartForm struct { // MaxUploadSize sets the maximum number of bytes used to parse a request body // as multipart/form-data. diff --git a/graphql/handler/transport/http_form_test.go b/graphql/handler/transport/http_form_test.go index 4eb636378b..3d7e2c4190 100644 --- a/graphql/handler/transport/http_form_test.go +++ b/graphql/handler/transport/http_form_test.go @@ -73,7 +73,9 @@ func TestFileUpload(t *testing.T) { op := graphql.GetOperationContext(ctx).Operation require.Equal(t, len(op.VariableDefinitions), 1) require.Equal(t, op.VariableDefinitions[0].Variable, "req") - return graphql.OneShot(&graphql.Response{Data: []byte(`{"singleUploadWithPayload":"test"}`)}) + return graphql.OneShot( + &graphql.Response{Data: []byte(`{"singleUploadWithPayload":"test"}`)}, + ) } operations := `{ "query": "mutation ($req: UploadFile!) { singleUploadWithPayload(req: $req) }", "variables": { "req": {"file": null, "id": 1 } } }` @@ -99,7 +101,9 @@ func TestFileUpload(t *testing.T) { op := graphql.GetOperationContext(ctx).Operation require.Equal(t, len(op.VariableDefinitions), 1) require.Equal(t, op.VariableDefinitions[0].Variable, "files") - return graphql.OneShot(&graphql.Response{Data: []byte(`{"multipleUpload":[{"id":1},{"id":2}]}`)}) + return graphql.OneShot( + &graphql.Response{Data: []byte(`{"multipleUpload":[{"id":1},{"id":2}]}`)}, + ) } operations := `{ "query": "mutation($files: [Upload!]!) { multipleUpload(files: $files) }", "variables": { "files": [null, null] } }` @@ -131,7 +135,11 @@ func TestFileUpload(t *testing.T) { op := graphql.GetOperationContext(ctx).Operation require.Equal(t, len(op.VariableDefinitions), 1) require.Equal(t, op.VariableDefinitions[0].Variable, "req") - return graphql.OneShot(&graphql.Response{Data: []byte(`{"multipleUploadWithPayload":[{"id":1},{"id":2}]}`)}) + return graphql.OneShot( + &graphql.Response{ + Data: []byte(`{"multipleUploadWithPayload":[{"id":1},{"id":2}]}`), + }, + ) } operations := `{ "query": "mutation($req: [UploadFile!]!) { multipleUploadWithPayload(req: $req) }", "variables": { "req": [ { "id": 1, "file": null }, { "id": 2, "file": null } ] } }` @@ -155,7 +163,11 @@ func TestFileUpload(t *testing.T) { resp := httptest.NewRecorder() h.ServeHTTP(resp, req) require.Equal(t, http.StatusOK, resp.Code) - require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1},{"id":2}]}}`, resp.Body.String()) + require.Equal( + t, + `{"data":{"multipleUploadWithPayload":[{"id":1},{"id":2}]}}`, + resp.Body.String(), + ) }) t.Run("valid file list upload with payload and file reuse", func(t *testing.T) { @@ -164,7 +176,11 @@ func TestFileUpload(t *testing.T) { op := graphql.GetOperationContext(ctx).Operation require.Equal(t, len(op.VariableDefinitions), 1) require.Equal(t, op.VariableDefinitions[0].Variable, "req") - return graphql.OneShot(&graphql.Response{Data: []byte(`{"multipleUploadWithPayload":[{"id":1},{"id":2}]}`)}) + return graphql.OneShot( + &graphql.Response{ + Data: []byte(`{"multipleUploadWithPayload":[{"id":1},{"id":2}]}`), + }, + ) } multipartForm.MaxMemory = uploadMaxMemory @@ -183,7 +199,11 @@ func TestFileUpload(t *testing.T) { resp := httptest.NewRecorder() h.ServeHTTP(resp, req) require.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) - require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1},{"id":2}]}}`, resp.Body.String()) + require.Equal( + t, + `{"data":{"multipleUploadWithPayload":[{"id":1},{"id":2}]}}`, + resp.Body.String(), + ) } t.Run("payload smaller than UploadMaxMemory, stored in memory", func(t *testing.T) { @@ -215,7 +235,11 @@ func TestFileUpload(t *testing.T) { resp := httptest.NewRecorder() h.ServeHTTP(resp, req) require.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) - require.Equal(t, `{"errors":[{"message":"first part must be operations"}],"data":null}`, resp.Body.String()) + require.Equal( + t, + `{"errors":[{"message":"first part must be operations"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("fail parse operation", func(t *testing.T) { @@ -225,7 +249,11 @@ func TestFileUpload(t *testing.T) { resp := httptest.NewRecorder() h.ServeHTTP(resp, req) require.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) - require.Equal(t, `{"errors":[{"message":"operations form field could not be decoded"}],"data":null}`, resp.Body.String()) + require.Equal( + t, + `{"errors":[{"message":"operations form field could not be decoded"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("fail parse map", func(t *testing.T) { @@ -235,7 +263,11 @@ func TestFileUpload(t *testing.T) { resp := httptest.NewRecorder() h.ServeHTTP(resp, req) require.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) - require.Equal(t, `{"errors":[{"message":"map form field could not be decoded"}],"data":null}`, resp.Body.String()) + require.Equal( + t, + `{"errors":[{"message":"map form field could not be decoded"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("fail missing file", func(t *testing.T) { @@ -245,7 +277,11 @@ func TestFileUpload(t *testing.T) { resp := httptest.NewRecorder() h.ServeHTTP(resp, req) require.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) - require.Equal(t, `{"errors":[{"message":"failed to get key 0 from form"}],"data":null}`, resp.Body.String()) + require.Equal( + t, + `{"errors":[{"message":"failed to get key 0 from form"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("fail map entry with invalid operations paths prefix", func(t *testing.T) { @@ -255,7 +291,11 @@ func TestFileUpload(t *testing.T) { resp := httptest.NewRecorder() h.ServeHTTP(resp, req) require.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) - require.Equal(t, `{"errors":[{"message":"invalid operations paths for key 0"}],"data":null}`, resp.Body.String()) + require.Equal( + t, + `{"errors":[{"message":"invalid operations paths for key 0"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("fail parse request big body", func(t *testing.T) { @@ -265,7 +305,11 @@ func TestFileUpload(t *testing.T) { resp := httptest.NewRecorder() h.ServeHTTP(resp, req) require.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) - require.Equal(t, `{"errors":[{"message":"failed to parse multipart form, request body too large"}],"data":null}`, resp.Body.String()) + require.Equal( + t, + `{"errors":[{"message":"failed to parse multipart form, request body too large"}],"data":null}`, + resp.Body.String(), + ) }) } @@ -288,7 +332,10 @@ func createUploadRequest(t *testing.T, operations, mapData string, files []file) for i := range files { h := make(textproto.MIMEHeader) - h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, files[i].mapKey, files[i].name)) + h.Set( + "Content-Disposition", + fmt.Sprintf(`form-data; name="%s"; filename="%s"`, files[i].mapKey, files[i].name), + ) h.Set("Content-Type", files[i].contentType) ff, err := bodyWriter.CreatePart(h) require.NoError(t, err) diff --git a/graphql/handler/transport/http_get_test.go b/graphql/handler/transport/http_get_test.go index 307b2b9035..4013a8a1bb 100644 --- a/graphql/handler/transport/http_get_test.go +++ b/graphql/handler/transport/http_get_test.go @@ -27,24 +27,45 @@ func TestGET(t *testing.T) { t.Run("decode failure", func(t *testing.T) { resp := doRequest(h, "GET", "/graphql?query={name}&variables=notjson", "") assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String()) - assert.Equal(t, `{"errors":[{"message":"variables could not be decoded"}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"variables could not be decoded"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("invalid variable", func(t *testing.T) { - resp := doRequest(h, "GET", `/graphql?query=query($id:Int!){find(id:$id)}&variables={"id":false}`, "") + resp := doRequest( + h, + "GET", + `/graphql?query=query($id:Int!){find(id:$id)}&variables={"id":false}`, + "", + ) assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) - assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + resp.Body.String(), + ) }) t.Run("parse failure", func(t *testing.T) { resp := doRequest(h, "GET", "/graphql?query=!", "") assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) - assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, + resp.Body.String(), + ) }) t.Run("no mutations", func(t *testing.T) { resp := doRequest(h, "GET", "/graphql?query=mutation{name}", "") assert.Equal(t, http.StatusNotAcceptable, resp.Code, resp.Body.String()) - assert.Equal(t, `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, + resp.Body.String(), + ) }) } diff --git a/graphql/handler/transport/http_post_test.go b/graphql/handler/transport/http_post_test.go index b27ffb3977..a3b9ce0875 100644 --- a/graphql/handler/transport/http_post_test.go +++ b/graphql/handler/transport/http_post_test.go @@ -26,35 +26,60 @@ func TestPOST(t *testing.T) { resp := doRequest(h, "POST", "/graphql", "notjson") assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String()) assert.Equal(t, resp.Header().Get("Content-Type"), "application/json") - assert.Equal(t, `{"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("parse failure", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", `{"query": "!"}`) assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) assert.Equal(t, resp.Header().Get("Content-Type"), "application/json") - assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, + resp.Body.String(), + ) }) t.Run("validation failure", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", `{"query": "{ title }"}`) assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) assert.Equal(t, resp.Header().Get("Content-Type"), "application/json") - assert.Equal(t, `{"errors":[{"message":"Cannot query field \"title\" on type \"Query\".","locations":[{"line":1,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"Cannot query field \"title\" on type \"Query\".","locations":[{"line":1,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + resp.Body.String(), + ) }) t.Run("invalid variable", func(t *testing.T) { - resp := doRequest(h, "POST", "/graphql", `{"query": "query($id:Int!){find(id:$id)}","variables":{"id":false}}`) + resp := doRequest( + h, + "POST", + "/graphql", + `{"query": "query($id:Int!){find(id:$id)}","variables":{"id":false}}`, + ) assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String()) assert.Equal(t, resp.Header().Get("Content-Type"), "application/json") - assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, + resp.Body.String(), + ) }) t.Run("execution failure", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", `{"query": "mutation { name }"}`) assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) assert.Equal(t, resp.Header().Get("Content-Type"), "application/json") - assert.Equal(t, `{"errors":[{"message":"mutations are not supported"}],"data":null}`, resp.Body.String()) + assert.Equal( + t, + `{"errors":[{"message":"mutations are not supported"}],"data":null}`, + resp.Body.String(), + ) }) t.Run("validate content type", func(t *testing.T) { @@ -86,7 +111,8 @@ func TestPOST(t *testing.T) { "", "text/plain", - // These content types are currently not supported, but they are supported by other GraphQL servers, like express-graphql. + // These content types are currently not supported, but they are supported by other + // GraphQL servers, like express-graphql. "application/x-www-form-urlencoded", "application/graphql", } @@ -95,13 +121,25 @@ func TestPOST(t *testing.T) { t.Run(fmt.Sprintf("reject for content type %s", tc), func(t *testing.T) { resp := doReq(h, "POST", "/graphql", `{"query":"{ name }"}`, tc) assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String()) - assert.Equal(t, fmt.Sprintf(`{"errors":[{"message":"%s"}],"data":null}`, "transport not supported"), resp.Body.String()) + assert.Equal( + t, + fmt.Sprintf( + `{"errors":[{"message":"%s"}],"data":null}`, + "transport not supported", + ), + resp.Body.String(), + ) }) } }) } -func doRequest(handler http.Handler, method string, target string, body string) *httptest.ResponseRecorder { +func doRequest( + handler http.Handler, + method string, + target string, + body string, +) *httptest.ResponseRecorder { r := httptest.NewRequest(method, target, strings.NewReader(body)) r.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() diff --git a/graphql/handler/transport/websocket.go b/graphql/handler/transport/websocket.go index 51b1104ccc..d1782f3029 100644 --- a/graphql/handler/transport/websocket.go +++ b/graphql/handler/transport/websocket.go @@ -84,11 +84,15 @@ func (t Websocket) Do(w http.ResponseWriter, r *http.Request, exec graphql.Graph var me messageExchanger switch ws.Subprotocol() { default: - msg := websocket.FormatCloseMessage(websocket.CloseProtocolError, fmt.Sprintf("unsupported negotiated subprotocol %s", ws.Subprotocol())) + msg := websocket.FormatCloseMessage( + websocket.CloseProtocolError, + fmt.Sprintf("unsupported negotiated subprotocol %s", ws.Subprotocol()), + ) ws.WriteMessage(websocket.CloseMessage, msg) return case graphqlwsSubprotocol, "": - // clients are required to send a subprotocol, to be backward compatible with the previous implementation we select + // clients are required to send a subprotocol, to be backward compatible with the previous + // implementation we select // "graphql-ws" by default me = graphqlwsMessageExchanger{c: ws} case graphqltransportwsSubprotocol: @@ -216,7 +220,8 @@ func (c *wsConnection) run() { // If we're running in graphql-ws mode, create a timer that will trigger a // keep alive message every interval - if (c.conn.Subprotocol() == "" || c.conn.Subprotocol() == graphqlwsSubprotocol) && c.KeepAlivePingInterval != 0 { + if (c.conn.Subprotocol() == "" || c.conn.Subprotocol() == graphqlwsSubprotocol) && + c.KeepAlivePingInterval != 0 { c.mu.Lock() c.keepAliveTicker = time.NewTicker(c.KeepAlivePingInterval) c.mu.Unlock() @@ -422,7 +427,10 @@ func (c *wsConnection) sendConnectionError(format string, args ...interface{}) { func (c *wsConnection) close(closeCode int, message string) { c.mu.Lock() - _ = c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(closeCode, message)) + _ = c.conn.WriteMessage( + websocket.CloseMessage, + websocket.FormatCloseMessage(closeCode, message), + ) for _, closer := range c.active { closer() } diff --git a/graphql/handler/transport/websocket_test.go b/graphql/handler/transport/websocket_test.go index fb2a07bf8c..20c44e7abf 100644 --- a/graphql/handler/transport/websocket_test.go +++ b/graphql/handler/transport/websocket_test.go @@ -103,7 +103,11 @@ func TestWebsocket(t *testing.T) { msg := readOp(c) assert.Equal(t, errorMsg, msg.Type) - assert.Equal(t, `[{"message":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}]`, string(msg.Payload)) + assert.Equal( + t, + `[{"message":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}]`, + string(msg.Payload), + ) }) t.Run("client can receive data", func(t *testing.T) { @@ -149,7 +153,6 @@ func TestWebsocket(t *testing.T) { } else { assert.Contains(t, err.Error(), "timeout") } - }) } @@ -205,44 +208,50 @@ func TestWebsocketInitFunc(t *testing.T) { assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) }) - t.Run("accept connection if WebsocketInitFunc is provided and is accepting connection", func(t *testing.T) { - h := testserver.New() - h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { - return context.WithValue(ctx, ckey("newkey"), "newvalue"), nil - }, - }) - srv := httptest.NewServer(h) - defer srv.Close() - - c := wsConnect(srv.URL) - defer c.Close() - - require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionInitMsg})) - - assert.Equal(t, connectionAckMsg, readOp(c).Type) - assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) - }) - - t.Run("reject connection if WebsocketInitFunc is provided and is accepting connection", func(t *testing.T) { - h := testserver.New() - h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { - return ctx, errors.New("invalid init payload") - }, - }) - srv := httptest.NewServer(h) - defer srv.Close() - - c := wsConnect(srv.URL) - defer c.Close() - - require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionInitMsg})) - - msg := readOp(c) - assert.Equal(t, connectionErrorMsg, msg.Type) - assert.Equal(t, `{"message":"invalid init payload"}`, string(msg.Payload)) - }) + t.Run( + "accept connection if WebsocketInitFunc is provided and is accepting connection", + func(t *testing.T) { + h := testserver.New() + h.AddTransport(transport.Websocket{ + InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { + return context.WithValue(ctx, ckey("newkey"), "newvalue"), nil + }, + }) + srv := httptest.NewServer(h) + defer srv.Close() + + c := wsConnect(srv.URL) + defer c.Close() + + require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionInitMsg})) + + assert.Equal(t, connectionAckMsg, readOp(c).Type) + assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) + }, + ) + + t.Run( + "reject connection if WebsocketInitFunc is provided and is accepting connection", + func(t *testing.T) { + h := testserver.New() + h.AddTransport(transport.Websocket{ + InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { + return ctx, errors.New("invalid init payload") + }, + }) + srv := httptest.NewServer(h) + defer srv.Close() + + c := wsConnect(srv.URL) + defer c.Close() + + require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionInitMsg})) + + msg := readOp(c) + assert.Equal(t, connectionErrorMsg, msg.Type) + assert.Equal(t, `{"message":"invalid init payload"}`, string(msg.Payload)) + }, + ) t.Run("can return context for request from WebsocketInitFunc", func(t *testing.T) { es := &graphql.ExecutableSchemaMock{ @@ -279,50 +288,60 @@ func TestWebsocketInitFunc(t *testing.T) { assert.Equal(t, "ok", resp.Empty) }) - t.Run("can set a deadline on a websocket connection and close it with a reason", func(t *testing.T) { - h := testserver.New() - var cancel func() - h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, _ transport.InitPayload) (newCtx context.Context, _ error) { - newCtx, cancel = context.WithTimeout(transport.AppendCloseReason(ctx, "beep boop"), time.Millisecond*5) - return - }, - }) - srv := httptest.NewServer(h) - defer srv.Close() - - c := wsConnect(srv.URL) - require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionInitMsg})) - assert.Equal(t, connectionAckMsg, readOp(c).Type) - assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) - - // Cancel should contain an actual value now, so let's call it when we exit this scope (to make the linter happy) - defer cancel() - - time.Sleep(time.Millisecond * 10) - m := readOp(c) - assert.Equal(t, m.Type, connectionErrorMsg) - assert.Equal(t, string(m.Payload), `{"message":"beep boop"}`) - }) + t.Run( + "can set a deadline on a websocket connection and close it with a reason", + func(t *testing.T) { + h := testserver.New() + var cancel func() + h.AddTransport(transport.Websocket{ + InitFunc: func(ctx context.Context, _ transport.InitPayload) (newCtx context.Context, _ error) { + newCtx, cancel = context.WithTimeout( + transport.AppendCloseReason(ctx, "beep boop"), + time.Millisecond*5, + ) + return + }, + }) + srv := httptest.NewServer(h) + defer srv.Close() + + c := wsConnect(srv.URL) + require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionInitMsg})) + assert.Equal(t, connectionAckMsg, readOp(c).Type) + assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) + + // Cancel should contain an actual value now, so let's call it when we exit this scope + // (to make the linter happy) + defer cancel() + + time.Sleep(time.Millisecond * 10) + m := readOp(c) + assert.Equal(t, m.Type, connectionErrorMsg) + assert.Equal(t, string(m.Payload), `{"message":"beep boop"}`) + }, + ) } func TestWebSocketInitTimeout(t *testing.T) { - t.Run("times out if no init message is received within the configured duration", func(t *testing.T) { - h := testserver.New() - h.AddTransport(transport.Websocket{ - InitTimeout: 5 * time.Millisecond, - }) - srv := httptest.NewServer(h) - defer srv.Close() - - c := wsConnect(srv.URL) - defer c.Close() + t.Run( + "times out if no init message is received within the configured duration", + func(t *testing.T) { + h := testserver.New() + h.AddTransport(transport.Websocket{ + InitTimeout: 5 * time.Millisecond, + }) + srv := httptest.NewServer(h) + defer srv.Close() + + c := wsConnect(srv.URL) + defer c.Close() - var msg operationMessage - err := c.ReadJSON(&msg) - assert.Error(t, err) - assert.Contains(t, err.Error(), "timeout") - }) + var msg operationMessage + err := c.ReadJSON(&msg) + assert.Error(t, err) + assert.Contains(t, err.Error(), "timeout") + }, + ) t.Run("keeps waiting for an init message if no time out is configured", func(t *testing.T) { h := testserver.New() @@ -370,7 +389,10 @@ func TestWebSocketErrorFunc(t *testing.T) { require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionInitMsg})) assert.Equal(t, connectionAckMsg, readOp(c).Type) assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) - require.NoError(t, c.WriteMessage(websocket.TextMessage, []byte("mark my words, you will regret this"))) + require.NoError( + t, + c.WriteMessage(websocket.TextMessage, []byte("mark my words, you will regret this")), + ) select { case res := <-errFuncCalled: @@ -387,7 +409,11 @@ func TestWebSocketErrorFunc(t *testing.T) { return ctx, errors.New("this is not what we agreed upon") }, ErrorFunc: func(_ context.Context, err error) { - assert.Fail(t, "the error handler got called when it shouldn't have", "error: "+err.Error()) + assert.Fail( + t, + "the error handler got called when it shouldn't have", + "error: "+err.Error(), + ) }, }) srv := httptest.NewServer(h) @@ -407,7 +433,11 @@ func TestWebSocketErrorFunc(t *testing.T) { return newCtx, nil }, ErrorFunc: func(_ context.Context, err error) { - assert.Fail(t, "the error handler got called when it shouldn't have", "error: "+err.Error()) + assert.Fail( + t, + "the error handler got called when it shouldn't have", + "error: "+err.Error(), + ) }, }) srv := httptest.NewServer(h) @@ -429,7 +459,11 @@ func TestWebSocketErrorFunc(t *testing.T) { return newCtx, nil }, ErrorFunc: func(_ context.Context, err error) { - assert.Fail(t, "the error handler got called when it shouldn't have", "error: "+err.Error()) + assert.Fail( + t, + "the error handler got called when it shouldn't have", + "error: "+err.Error(), + ) }, }) srv := httptest.NewServer(h) @@ -440,7 +474,8 @@ func TestWebSocketErrorFunc(t *testing.T) { assert.Equal(t, connectionAckMsg, readOp(c).Type) assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) - // Cancel should contain an actual value now, so let's call it when we exit this scope (to make the linter happy) + // Cancel should contain an actual value now, so let's call it when we exit this scope (to + // make the linter happy) defer cancel() time.Sleep(time.Millisecond * 20) @@ -461,7 +496,10 @@ func TestWebsocketGraphqltransportwsSubprotocol(t *testing.T) { c := wsConnectWithSubprocotol(srv.URL, graphqltransportwsSubprotocol) defer c.Close() - require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg})) + require.NoError( + t, + c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg}), + ) assert.Equal(t, graphqltransportwsConnectionAckMsg, readOp(c).Type) }) @@ -472,7 +510,10 @@ func TestWebsocketGraphqltransportwsSubprotocol(t *testing.T) { c := wsConnectWithSubprocotol(srv.URL, graphqltransportwsSubprotocol) defer c.Close() - require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg})) + require.NoError( + t, + c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg}), + ) assert.Equal(t, graphqltransportwsConnectionAckMsg, readOp(c).Type) require.NoError(t, c.WriteJSON(&operationMessage{ @@ -493,7 +534,10 @@ func TestWebsocketGraphqltransportwsSubprotocol(t *testing.T) { require.Equal(t, "test_1", msg.ID, string(msg.Payload)) require.Equal(t, `{"data":{"name":"test"}}`, string(msg.Payload)) - require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsCompleteMsg, ID: "test_1"})) + require.NoError( + t, + c.WriteJSON(&operationMessage{Type: graphqltransportwsCompleteMsg, ID: "test_1"}), + ) msg = readOp(c) require.Equal(t, graphqltransportwsCompleteMsg, msg.Type) @@ -507,10 +551,14 @@ func TestWebsocketGraphqltransportwsSubprotocol(t *testing.T) { c := wsConnectWithSubprocotol(srv.URL, graphqltransportwsSubprotocol) defer c.Close() - require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg})) + require.NoError( + t, + c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg}), + ) assert.Equal(t, graphqltransportwsConnectionAckMsg, readOp(c).Type) - // If the keep-alives are sent, this deadline will not be used, and no timeout error will be found + // If the keep-alives are sent, this deadline will not be used, and no timeout error will be + // found c.SetReadDeadline(time.Now().UTC().Add(50 * time.Millisecond)) var msg operationMessage err := c.ReadJSON(&msg) @@ -533,7 +581,10 @@ func TestWebsocketWithPingPongInterval(t *testing.T) { c := wsConnectWithSubprocotol(srv.URL, graphqltransportwsSubprotocol) defer c.Close() - require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg})) + require.NoError( + t, + c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg}), + ) assert.Equal(t, graphqltransportwsConnectionAckMsg, readOp(c).Type) assert.Equal(t, graphqltransportwsPingMsg, readOp(c).Type) @@ -548,7 +599,10 @@ func TestWebsocketWithPingPongInterval(t *testing.T) { c := wsConnectWithSubprocotol(srv.URL, graphqltransportwsSubprotocol) defer c.Close() - require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg})) + require.NoError( + t, + c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg}), + ) assert.Equal(t, graphqltransportwsConnectionAckMsg, readOp(c).Type) require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsPingMsg})) @@ -558,7 +612,8 @@ func TestWebsocketWithPingPongInterval(t *testing.T) { t.Run("ping-pongs are not sent when the graphql-ws sub protocol is used", func(t *testing.T) { // Regression test // --- - // Before the refactor, the code would try to convert a ping message to a graphql-ws message type + // Before the refactor, the code would try to convert a ping message to a graphql-ws message + // type // But since this message type does not exist in the graphql-ws sub protocol, it would fail _, srv := initialize(transport.Websocket{ diff --git a/graphql/handler_test.go b/graphql/handler_test.go index 3ba421f392..116b360a0a 100644 --- a/graphql/handler_test.go +++ b/graphql/handler_test.go @@ -23,7 +23,11 @@ func TestAddUploadToOperations(t *testing.T) { path := "variables.req.0.file" err := params.AddUpload(upload, key, path) require.NotNil(t, err) - require.Equal(t, "input: path is missing \"variables.\" prefix, key: 0, path: variables.req.0.file", err.Error()) + require.Equal( + t, + "input: path is missing \"variables.\" prefix, key: 0, path: variables.req.0.file", + err.Error(), + ) }) t.Run("valid variable", func(t *testing.T) { diff --git a/graphql/input.go b/graphql/input.go index 88c3efaa6e..69fbdf7aad 100644 --- a/graphql/input.go +++ b/graphql/input.go @@ -22,7 +22,8 @@ func BuildUnmarshalerMap(unmarshaler ...interface{}) map[reflect.Type]reflect.Va return maps } -// WithUnmarshalerMap returns a new context with a map from input types to their unmarshaler functions. +// WithUnmarshalerMap returns a new context with a map from input types to their unmarshaler +// functions. func WithUnmarshalerMap(ctx context.Context, maps map[reflect.Type]reflect.Value) context.Context { return context.WithValue(ctx, unmarshalInputCtx, maps) } diff --git a/graphql/introspection/introspection.go b/graphql/introspection/introspection.go index 8482d62a86..889b20411d 100644 --- a/graphql/introspection/introspection.go +++ b/graphql/introspection/introspection.go @@ -1,4 +1,5 @@ -// introspection implements the spec defined in https://github.com/facebook/graphql/blob/master/spec/Section%204%20--%20Introspection.md#schema-introspection +// introspection implements the spec defined in +// https://github.com/facebook/graphql/blob/master/spec/Section%204%20--%20Introspection.md#schema-introspection package introspection import "github.com/vektah/gqlparser/v2/ast" diff --git a/graphql/jsonw_test.go b/graphql/jsonw_test.go index 1bba9fcf37..2cb1d7947b 100644 --- a/graphql/jsonw_test.go +++ b/graphql/jsonw_test.go @@ -44,5 +44,9 @@ func TestJsonWriter(t *testing.T) { b := &bytes.Buffer{} obj.MarshalGQL(b) - require.Equal(t, `{"test":10,"array":[1,"2",true,false,null,1.3,true],"emptyArray":[],"child":{"child":{"child":null}}}`, b.String()) + require.Equal( + t, + `{"test":10,"array":[1,"2",true,false,null,1.3,true],"emptyArray":[],"child":{"child":{"child":null}}}`, + b.String(), + ) } diff --git a/graphql/playground/playground_test.go b/graphql/playground/playground_test.go index 9b873691d3..4411bb0568 100644 --- a/graphql/playground/playground_test.go +++ b/graphql/playground/playground_test.go @@ -31,12 +31,16 @@ func TestHandler_createsAbsoluteURLs(t *testing.T) { t.Errorf("no match for %s in response body", want.String()) } - wantSubURL := regexp.MustCompile(`(?m)^.*subscriptionUrl\s*=\s*['"]wss:\/\/example\.org\/query["'].*$`) + wantSubURL := regexp.MustCompile( + `(?m)^.*subscriptionUrl\s*=\s*['"]wss:\/\/example\.org\/query["'].*$`, + ) if !wantSubURL.Match(b) { t.Errorf("no match for %s in response body", wantSubURL.String()) } - wantMetaCharsetElement := regexp.MustCompile(`\n\s{0,}\n\s{0,}.*`) // <meta> element must be in <head> and before <title> + wantMetaCharsetElement := regexp.MustCompile( + `<head>\n\s{0,}<meta charset="utf-8">\n\s{0,}.*<title>`, + ) // <meta> element must be in <head> and before <title> if !wantMetaCharsetElement.Match(b) { t.Errorf("no match for %s in response body", wantMetaCharsetElement.String()) } @@ -54,7 +58,11 @@ func TestHandler_createsRelativeURLs(t *testing.T) { t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, http.StatusOK) } if res.Header.Get("Content-Type") != "text/html; charset=UTF-8" { - t.Errorf("res.Header.Get(\"Content-Type\") = %q; want %q", res.Header.Get("Content-Type"), "text/html; charset=UTF-8") + t.Errorf( + "res.Header.Get(\"Content-Type\") = %q; want %q", + res.Header.Get("Content-Type"), + "text/html; charset=UTF-8", + ) } b, err := io.ReadAll(res.Body) @@ -66,7 +74,9 @@ func TestHandler_createsRelativeURLs(t *testing.T) { if !wantURL.Match(b) { t.Errorf("no match for %s in response body", wantURL.String()) } - wantSubURL := regexp.MustCompile(`(?m)^.*subscriptionUrl\s*=\s*wsProto.*['"]\/customquery['"].*$`) + wantSubURL := regexp.MustCompile( + `(?m)^.*subscriptionUrl\s*=\s*wsProto.*['"]\/customquery['"].*$`, + ) if !wantSubURL.Match(b) { t.Errorf("no match for %s in response body", wantSubURL.String()) } diff --git a/graphql/stats.go b/graphql/stats.go index a52e143ebe..4451626adf 100644 --- a/graphql/stats.go +++ b/graphql/stats.go @@ -12,7 +12,8 @@ type Stats struct { Parsing TraceTiming Validation TraceTiming - // Stats collected by handler extensions. Dont use directly, the extension should provide a type safe way to + // Stats collected by handler extensions. Dont use directly, the extension should provide a type + // safe way to // access this. extension map[string]interface{} } @@ -24,9 +25,10 @@ type TraceTiming struct { var ctxTraceStart key = "trace_start" -// StartOperationTrace captures the current time and stores it in context. This will eventually be added to request -// context but we want to grab it as soon as possible. For transports that can only handle a single graphql query -// per http requests you dont need to call this at all, the server will do it for you. For transports that handle +// StartOperationTrace captures the current time and stores it in context. This will eventually be +// added to request context but we want to grab it as soon as possible. For transports that can only +// handle a single graphql query per http requests you dont need to call this at all, the server +// will do it for you. For transports that handle // multiple (eg batching, subscriptions) this should be called before decoding each request. func StartOperationTrace(ctx context.Context) context.Context { return context.WithValue(ctx, ctxTraceStart, Now()) diff --git a/graphql/string_test.go b/graphql/string_test.go index 3a29cdeea9..cc07c6cef2 100644 --- a/graphql/string_test.go +++ b/graphql/string_test.go @@ -15,7 +15,11 @@ func TestString(t *testing.T) { assert.Equal(t, `"he\nllo"`, m2s(MarshalString("he\nllo"))) assert.Equal(t, `"he\r\nllo"`, m2s(MarshalString("he\r\nllo"))) assert.Equal(t, `"he\\llo"`, m2s(MarshalString(`he\llo`))) - assert.Equal(t, `"quotes\"nested\"in\"quotes\""`, m2s(MarshalString(`quotes"nested"in"quotes"`))) + assert.Equal( + t, + `"quotes\"nested\"in\"quotes\""`, + m2s(MarshalString(`quotes"nested"in"quotes"`)), + ) assert.Equal(t, `"\u0000"`, m2s(MarshalString("\u0000"))) assert.Equal(t, `"\u0000"`, m2s(MarshalString("\u0000"))) assert.Equal(t, "\"\U000fe4ed\"", m2s(MarshalString("\U000fe4ed"))) diff --git a/graphql/time_test.go b/graphql/time_test.go index 32876436a6..e9380ec5f2 100644 --- a/graphql/time_test.go +++ b/graphql/time_test.go @@ -20,6 +20,12 @@ func TestTime(t *testing.T) { newTime, err := UnmarshalTime(str) require.Nil(t, err) - require.True(t, initialTime.Equal(newTime), "expected times %v and %v to equal", initialTime, newTime) + require.True( + t, + initialTime.Equal(newTime), + "expected times %v and %v to equal", + initialTime, + newTime, + ) }) } diff --git a/handler/handler.go b/handler/handler.go index 386b194627..0764e7e22e 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -108,8 +108,9 @@ func RecoverFunc(recover graphql.RecoverFunc) Option { } } -// ErrorPresenter transforms errors found while resolving into errors that will be returned to the user. It provides -// a good place to add any extra fields, like error.type, that might be desired by your frontend. Check the default +// ErrorPresenter transforms errors found while resolving into errors that will be returned to the +// user. It provides a good place to add any extra fields, like error.type, that might be desired by +// your frontend. Check the default // implementation in graphql.DefaultErrorPresenter for an example. // Deprecated: switch to graphql/handler.New func ErrorPresenter(f graphql.ErrorPresenterFunc) Option { @@ -118,7 +119,8 @@ func ErrorPresenter(f graphql.ErrorPresenterFunc) Option { } } -// IntrospectionEnabled = false will forbid clients from calling introspection endpoints. Can be useful in prod when you dont +// IntrospectionEnabled = false will forbid clients from calling introspection endpoints. Can be +// useful in prod when you dont // want clients introspecting the full schema. // Deprecated: switch to graphql/handler.New func IntrospectionEnabled(enabled bool) Option { @@ -136,7 +138,8 @@ func ComplexityLimit(limit int) Option { } } -// ComplexityLimitFunc allows you to define a function to dynamically set the maximum query complexity that is allowed +// ComplexityLimitFunc allows you to define a function to dynamically set the maximum query +// complexity that is allowed // to be executed. // If a query is submitted that exceeds the limit, a 422 status code will be returned. // Deprecated: switch to graphql/handler.New diff --git a/internal/code/compare_test.go b/internal/code/compare_test.go index 0100d57423..f6463a8e26 100644 --- a/internal/code/compare_test.go +++ b/internal/code/compare_test.go @@ -81,5 +81,6 @@ func parseTypeStr(t *testing.T, s string) types.Type { pkg, err := conf.Check("test", fset, []*ast.File{f}, nil) require.NoError(t, err) - return pkg.Scope().Lookup("Foo").Type().(*types.Named).Underlying().(*types.Struct).Field(0).Type() + return pkg.Scope().Lookup("Foo").Type().(*types.Named).Underlying().(*types.Struct).Field(0). + Type() } diff --git a/internal/code/imports.go b/internal/code/imports.go index 0e499a171f..b741ce3da0 100644 --- a/internal/code/imports.go +++ b/internal/code/imports.go @@ -21,7 +21,8 @@ func init() { } } -// NameForDir manually looks for package stanzas in files located in the given directory. This can be +// NameForDir manually looks for package stanzas in files located in the given directory. This can +// be // much faster than having to consult go list, because we already know exactly where to look. func NameForDir(dir string) string { dir, err := filepath.Abs(dir) @@ -55,7 +56,8 @@ type goModuleSearchResult struct { var goModuleRootCache = map[string]goModuleSearchResult{} -// goModuleRoot returns the root of the current go module if there is a go.mod file in the directory tree +// goModuleRoot returns the root of the current go module if there is a go.mod file in the directory +// tree // If not, it returns false func goModuleRoot(dir string) (string, bool) { dir, err := filepath.Abs(dir) @@ -99,7 +101,8 @@ func goModuleRoot(dir string) (string, bool) { // create a cache for each path in a tree traversed, except the top one as it is already cached for _, d := range dirs[:len(dirs)-1] { if result.moduleName == "" { - // go.mod is not found in the tree, so the same sentinel value fits all the directories in a tree + // go.mod is not found in the tree, so the same sentinel value fits all the directories + // in a tree goModuleRootCache[d] = result } else { if relPath, err := filepath.Rel(result.goModPath, d); err != nil { diff --git a/internal/code/imports_test.go b/internal/code/imports_test.go index f8ab888c6d..794ea6da32 100644 --- a/internal/code/imports_test.go +++ b/internal/code/imports_test.go @@ -28,13 +28,25 @@ func TestImportPathForDir(t *testing.T) { assert.Equal(t, "github.com/99designs/gqlgen/internal/code", ImportPathForDir(wd)) assert.Equal(t, "github.com/99designs/gqlgen/internal/code", ImportPathForDir(wd)) - assert.Equal(t, "github.com/99designs/gqlgen/api", ImportPathForDir(filepath.Join(wd, "..", "..", "api"))) + assert.Equal( + t, + "github.com/99designs/gqlgen/api", + ImportPathForDir(filepath.Join(wd, "..", "..", "api")), + ) // doesnt contain go code, but should still give a valid import path - assert.Equal(t, "github.com/99designs/gqlgen/docs", ImportPathForDir(filepath.Join(wd, "..", "..", "docs"))) + assert.Equal( + t, + "github.com/99designs/gqlgen/docs", + ImportPathForDir(filepath.Join(wd, "..", "..", "docs")), + ) // directory does not exist - assert.Equal(t, "github.com/99designs/gqlgen/dos", ImportPathForDir(filepath.Join(wd, "..", "..", "dos"))) + assert.Equal( + t, + "github.com/99designs/gqlgen/dos", + ImportPathForDir(filepath.Join(wd, "..", "..", "dos")), + ) // out of module assert.Equal(t, "", ImportPathForDir(filepath.Join(wd, "..", "..", ".."))) diff --git a/internal/code/packages.go b/internal/code/packages.go index c800d3d84f..746a43cb90 100644 --- a/internal/code/packages.go +++ b/internal/code/packages.go @@ -20,7 +20,8 @@ var mode = packages.NeedName | packages.NeedModule | packages.NeedDeps -// Packages is a wrapper around x/tools/go/packages that maintains a (hopefully prewarmed) cache of packages +// Packages is a wrapper around x/tools/go/packages that maintains a (hopefully prewarmed) cache of +// packages // that can be invalidated as writes are made and packages are known to change. type Packages struct { packages map[string]*packages.Package @@ -114,8 +115,9 @@ func (p *Packages) Load(importPath string) *packages.Package { return pkgs[0] } -// LoadWithTypes tries a standard load, which may not have enough type info (TypesInfo== nil) available if the imported package is a -// second order dependency. Fortunately this doesnt happen very often, so we can just issue a load when we detect it. +// LoadWithTypes tries a standard load, which may not have enough type info (TypesInfo== nil) +// available if the imported package is a second order dependency. Fortunately this doesnt happen +// very often, so we can just issue a load when we detect it. func (p *Packages) LoadWithTypes(importPath string) *packages.Package { pkg := p.Load(importPath) if pkg == nil || pkg.TypesInfo == nil { @@ -131,7 +133,8 @@ func (p *Packages) LoadWithTypes(importPath string) *packages.Package { return pkg } -// NameForPackage looks up the package name from the package stanza in the go files at the given import path. +// NameForPackage looks up the package name from the package stanza in the go files at the given +// import path. func (p *Packages) NameForPackage(importPath string) string { if importPath == "" { panic(errors.New("import path can not be empty")) @@ -170,7 +173,8 @@ func (p *Packages) NameForPackage(importPath string) string { return pkg.Name } -// Evict removes a given package import path from the cache, along with any packages that depend on it. Further calls +// Evict removes a given package import path from the cache, along with any packages that depend on +// it. Further calls // to Load will fetch it from disk. func (p *Packages) Evict(importPath string) { delete(p.packages, importPath) @@ -195,7 +199,8 @@ func (p *Packages) ModTidy() error { return nil } -// Errors returns any errors that were returned by Load, either from the call itself or any of the loaded packages. +// Errors returns any errors that were returned by Load, either from the call itself or any of the +// loaded packages. func (p *Packages) Errors() PkgErrors { var res []error //nolint:prealloc res = append(res, p.loadErrors...) diff --git a/internal/code/packages_test.go b/internal/code/packages_test.go index 2fbf780c55..feec9179d1 100644 --- a/internal/code/packages_test.go +++ b/internal/code/packages_test.go @@ -10,13 +10,21 @@ import ( func TestPackages(t *testing.T) { t.Run("name for existing package does not load again", func(t *testing.T) { p := initialState(t) - require.Equal(t, "a", p.NameForPackage("github.com/99designs/gqlgen/internal/code/testdata/a")) + require.Equal( + t, + "a", + p.NameForPackage("github.com/99designs/gqlgen/internal/code/testdata/a"), + ) require.Equal(t, 1, p.numLoadCalls) }) t.Run("name for unknown package makes name only load", func(t *testing.T) { p := initialState(t) - require.Equal(t, "c", p.NameForPackage("github.com/99designs/gqlgen/internal/code/testdata/c")) + require.Equal( + t, + "c", + p.NameForPackage("github.com/99designs/gqlgen/internal/code/testdata/c"), + ) require.Equal(t, 1, p.numLoadCalls) require.Equal(t, 1, p.numNameCalls) }) diff --git a/internal/code/util.go b/internal/code/util.go index cbe40858e2..731ef1d681 100644 --- a/internal/code/util.go +++ b/internal/code/util.go @@ -36,7 +36,8 @@ func NormalizeVendor(pkg string) string { // github.com/99designs/gqlgen/graphql becomes // github.com/foo/vendor/github.com/99designs/gqlgen/graphql // -// x/tools/packages only supports 'qualified package paths' so this will need to be done prior to calling it +// x/tools/packages only supports 'qualified package paths' so this will need to be done prior to +// calling it // See https://github.com/golang/go/issues/30289 func QualifyPackagePath(importPath string) string { wd, _ := os.Getwd() diff --git a/internal/imports/prune.go b/internal/imports/prune.go index d42a415791..3b132df5e9 100644 --- a/internal/imports/prune.go +++ b/internal/imports/prune.go @@ -43,7 +43,11 @@ func Prune(filename string, src []byte, packages *code.Packages) ([]byte, error) return nil, err } - return imports.Process(filename, buf.Bytes(), &imports.Options{FormatOnly: true, Comments: true, TabIndent: true, TabWidth: 8}) + return imports.Process( + filename, + buf.Bytes(), + &imports.Options{FormatOnly: true, Comments: true, TabIndent: true, TabWidth: 8}, + ) } func getUnusedImports(file ast.Node, packages *code.Packages) map[string]string { diff --git a/internal/imports/prune_test.go b/internal/imports/prune_test.go index 15af13dcd2..b0158e3a1a 100644 --- a/internal/imports/prune_test.go +++ b/internal/imports/prune_test.go @@ -14,7 +14,11 @@ func TestPrune(t *testing.T) { b, err := Prune("testdata/unused.go", mustReadFile("testdata/unused.go"), &code.Packages{}) require.NoError(t, err) - require.Equal(t, strings.ReplaceAll(string(mustReadFile("testdata/unused.expected.go")), "\r\n", "\n"), string(b)) + require.Equal( + t, + strings.ReplaceAll(string(mustReadFile("testdata/unused.expected.go")), "\r\n", "\n"), + string(b), + ) } func mustReadFile(filename string) []byte { diff --git a/internal/rewrite/rewriter.go b/internal/rewrite/rewriter.go index a8a6485cff..156d0f76f7 100644 --- a/internal/rewrite/rewriter.go +++ b/internal/rewrite/rewriter.go @@ -99,6 +99,7 @@ func (r *Rewriter) GetMethodComment(structname string, methodname string) string return "" } + func (r *Rewriter) GetMethodBody(structname string, methodname string) string { for _, f := range r.pkg.Syntax { for _, d := range f.Decls { diff --git a/main.go b/main.go index d13a9c4f49..e0420d1502 100644 --- a/main.go +++ b/main.go @@ -12,12 +12,13 @@ import ( "os" "path/filepath" + "github.com/urfave/cli/v2" + "github.com/99designs/gqlgen/api" "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/internal/code" "github.com/99designs/gqlgen/plugin/servergen" - "github.com/urfave/cli/v2" ) //go:embed init-templates/schema.graphqls @@ -39,6 +40,28 @@ func fileExists(filename string) bool { return !errors.Is(err, fs.ErrNotExist) } +// see Go source code: +// https://github.com/golang/go/blob/f57ebed35132d02e5cf016f324853217fb545e91/src/cmd/go/internal/modload/init.go#L1283 +func findModuleRoot(dir string) (roots string) { + if dir == "" { + panic("dir not set") + } + dir = filepath.Clean(dir) + + // Look for enclosing go.mod. + for { + if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() { + return dir + } + d := filepath.Dir(dir) + if d == dir { // the parent of the root is itself, so we can go no further + break + } + dir = d + } + return "" +} + func initFile(filename, contents string) error { if err := os.MkdirAll(filepath.Dir(filename), 0o755); err != nil { return fmt.Errorf("unable to create directory for file '%s': %w\n", filename, err) @@ -56,20 +79,35 @@ var initCmd = &cli.Command{ Flags: []cli.Flag{ &cli.BoolFlag{Name: "verbose, v", Usage: "show logs"}, &cli.StringFlag{Name: "config, c", Usage: "the config filename", Value: "gqlgen.yml"}, - &cli.StringFlag{Name: "server", Usage: "where to write the server stub to", Value: "server.go"}, - &cli.StringFlag{Name: "schema", Usage: "where to write the schema stub to", Value: "graph/schema.graphqls"}, + &cli.StringFlag{ + Name: "server", + Usage: "where to write the server stub to", + Value: "server.go", + }, + &cli.StringFlag{ + Name: "schema", + Usage: "where to write the schema stub to", + Value: "graph/schema.graphqls", + }, }, Action: func(ctx *cli.Context) error { configFilename := ctx.String("config") serverFilename := ctx.String("server") schemaFilename := ctx.String("schema") - pkgName := code.ImportPathForDir(".") + cwd, err := os.Getwd() + if err != nil { + log.Println(err) + return fmt.Errorf("unable to determine current directory:%w", err) + } + pkgName := code.ImportPathForDir(cwd) if pkgName == "" { - return fmt.Errorf("unable to determine import path for current directory, you probably need to run 'go mod init' first") + return fmt.Errorf( + "unable to determine import path for current directory, you probably need to run 'go mod init' first", + ) } - - if !fileExists("go.mod") { + modRoot := findModuleRoot(cwd) + if modRoot == "" { return fmt.Errorf("go.mod is missing. Please, do 'go mod init' first\n") } @@ -79,7 +117,7 @@ var initCmd = &cli.Command{ return fmt.Errorf("%s already exists", filename) } } - _, err := config.LoadConfigFromDefaultLocations() + _, err = config.LoadConfigFromDefaultLocations() if err == nil { return fmt.Errorf("gqlgen.yml already exists in a parent directory\n") } diff --git a/plugin/federation/federation.go b/plugin/federation/federation.go index cd60acee25..ce1598d5e9 100644 --- a/plugin/federation/federation.go +++ b/plugin/federation/federation.go @@ -63,7 +63,10 @@ func (f *federation) MutateConfig(cfg *config.Config) error { for typeName, entry := range builtins { if cfg.Models.Exists(typeName) { - return fmt.Errorf("%v already exists which must be reserved when Federation is enabled", typeName) + return fmt.Errorf( + "%v already exists which must be reserved when Federation is enabled", + typeName, + ) } cfg.Models[typeName] = entry } @@ -95,7 +98,8 @@ func (f *federation) InjectSourceEarly() *ast.Source { directive @provides(fields: _FieldSet!) on FIELD_DEFINITION directive @extends on OBJECT | INTERFACE ` - // add version-specific changes on key directive, as well as adding the new directives for federation 2 + // add version-specific changes on key directive, as well as adding the new directives for + // federation 2 if f.Version == 1 { input += ` directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE @@ -136,10 +140,19 @@ func (f *federation) InjectSourceLate(schema *ast.Schema) *ast.Source { } entityResolverInputDefinitions += "input " + r.InputType + " {\n" for _, keyField := range r.KeyFields { - entityResolverInputDefinitions += fmt.Sprintf("\t%s: %s\n", keyField.Field.ToGo(), keyField.Definition.Type.String()) + entityResolverInputDefinitions += fmt.Sprintf( + "\t%s: %s\n", + keyField.Field.ToGo(), + keyField.Definition.Type.String(), + ) } entityResolverInputDefinitions += "}" - resolvers += fmt.Sprintf("\t%s(reps: [%s!]!): [%s]\n", r.ResolverName, r.InputType, e.Name) + resolvers += fmt.Sprintf( + "\t%s(reps: [%s!]!): [%s]\n", + r.ResolverName, + r.InputType, + e.Name, + ) } else { resolverArgs := "" for _, keyField := range r.KeyFields { @@ -330,7 +343,8 @@ func (f *federation) setEntities(schema *ast.Schema) { } var arg *ast.Argument - // since keys are able to now have multiple arguments, we need to check both possible for a possible @key(fields="" fields="") + // since keys are able to now have multiple arguments, we need to check both + // possible for a possible @key(fields="" fields="") for _, a := range dir.Arguments { if a.Name == "fields" { if arg != nil { @@ -408,7 +422,10 @@ func isFederatedEntity(schemaType *ast.Definition) ([]*ast.Directive, bool) { case ast.Interface: // TODO: support @key and @extends for interfaces if dir := schemaType.Directives.ForName("key"); dir != nil { - fmt.Printf("@key directive found on \"interface %s\". Will be ignored.\n", schemaType.Name) + fmt.Printf( + "@key directive found on \"interface %s\". Will be ignored.\n", + schemaType.Name, + ) } if dir := schemaType.Directives.ForName("extends"); dir != nil { panic( diff --git a/plugin/federation/federation_entityresolver_test.go b/plugin/federation/federation_entityresolver_test.go index 4cbc160245..d2f1df0c17 100644 --- a/plugin/federation/federation_entityresolver_test.go +++ b/plugin/federation/federation_entityresolver_test.go @@ -95,8 +95,16 @@ func TestEntityResolver(t *testing.T) { entityErrors[1].Message, } - require.Contains(t, errMessages, "resolving Entity \"HelloWithErrors\": error (empty key) resolving HelloWithErrorsByName") - require.Contains(t, errMessages, "resolving Entity \"HelloWithErrors\": error resolving HelloWithErrorsByName") + require.Contains( + t, + errMessages, + "resolving Entity \"HelloWithErrors\": error (empty key) resolving HelloWithErrorsByName", + ) + require.Contains( + t, + errMessages, + "resolving Entity \"HelloWithErrors\": error resolving HelloWithErrorsByName", + ) require.Len(t, resp.Entities, 5) require.Equal(t, resp.Entities[0].Name, "first name - 1") @@ -311,46 +319,49 @@ func TestEntityResolver(t *testing.T) { require.Equal(t, resp.Entities[1].Density, 850) }) - t.Run("PlanetRequiresNested entities with requires directive having nested field", func(t *testing.T) { - representations := []map[string]interface{}{ - { - "__typename": "PlanetRequiresNested", - "name": "earth", - "world": map[string]interface{}{ - "foo": "A", + t.Run( + "PlanetRequiresNested entities with requires directive having nested field", + func(t *testing.T) { + representations := []map[string]interface{}{ + { + "__typename": "PlanetRequiresNested", + "name": "earth", + "world": map[string]interface{}{ + "foo": "A", + }, + }, { + "__typename": "PlanetRequiresNested", + "name": "mars", + "world": map[string]interface{}{ + "foo": "B", + }, }, - }, { - "__typename": "PlanetRequiresNested", - "name": "mars", - "world": map[string]interface{}{ - "foo": "B", - }, - }, - } - - var resp struct { - Entities []struct { - Name string `json:"name"` - World struct { - Foo string `json:"foo"` - } `json:"world"` - } `json:"_entities"` - } + } - err := c.Post( - entityQuery([]string{ - "PlanetRequiresNested {name, world { foo }}", - }), - &resp, - client.Var("representations", representations), - ) + var resp struct { + Entities []struct { + Name string `json:"name"` + World struct { + Foo string `json:"foo"` + } `json:"world"` + } `json:"_entities"` + } - require.NoError(t, err) - require.Equal(t, resp.Entities[0].Name, "earth") - require.Equal(t, resp.Entities[0].World.Foo, "A") - require.Equal(t, resp.Entities[1].Name, "mars") - require.Equal(t, resp.Entities[1].World.Foo, "B") - }) + err := c.Post( + entityQuery([]string{ + "PlanetRequiresNested {name, world { foo }}", + }), + &resp, + client.Var("representations", representations), + ) + + require.NoError(t, err) + require.Equal(t, resp.Entities[0].Name, "earth") + require.Equal(t, resp.Entities[0].World.Foo, "A") + require.Equal(t, resp.Entities[1].Name, "mars") + require.Equal(t, resp.Entities[1].World.Foo, "B") + }, + ) } func TestMultiEntityResolver(t *testing.T) { @@ -388,7 +399,11 @@ func TestMultiEntityResolver(t *testing.T) { require.NoError(t, err) for i := 0; i < itemCount; i++ { - require.Equal(t, resp.Entities[i].Name, "world name - "+strconv.Itoa(i)+" - from multiget") + require.Equal( + t, + resp.Entities[i].Name, + "world name - "+strconv.Itoa(i)+" - from multiget", + ) } }) @@ -431,7 +446,11 @@ func TestMultiEntityResolver(t *testing.T) { for i := 0; i < itemCount; i++ { if i%2 == 0 { - require.Equal(t, resp.Entities[i].Name, "world name - "+strconv.Itoa(i)+" - from multiget") + require.Equal( + t, + resp.Entities[i].Name, + "world name - "+strconv.Itoa(i)+" - from multiget", + ) } else { require.Equal(t, resp.Entities[i].Name, "hello - "+strconv.Itoa(i)) } @@ -545,57 +564,64 @@ func TestMultiEntityResolver(t *testing.T) { require.Equal(t, resp.Entities[1].Key2, "key2 - 2") }) - t.Run("MultiPlanetRequiresNested entities with requires directive having nested field", func(t *testing.T) { - representations := []map[string]interface{}{ - { - "__typename": "MultiPlanetRequiresNested", - "name": "earth", - "world": map[string]interface{}{ - "foo": "A", - }, - }, { - "__typename": "MultiPlanetRequiresNested", - "name": "mars", - "world": map[string]interface{}{ - "foo": "B", + t.Run( + "MultiPlanetRequiresNested entities with requires directive having nested field", + func(t *testing.T) { + representations := []map[string]interface{}{ + { + "__typename": "MultiPlanetRequiresNested", + "name": "earth", + "world": map[string]interface{}{ + "foo": "A", + }, + }, { + "__typename": "MultiPlanetRequiresNested", + "name": "mars", + "world": map[string]interface{}{ + "foo": "B", + }, }, - }, - } - - var resp struct { - Entities []struct { - Name string `json:"name"` - World struct { - Foo string `json:"foo"` - } `json:"world"` - } `json:"_entities"` - } + } - err := c.Post( - entityQuery([]string{ - "MultiPlanetRequiresNested {name, world { foo }}", - }), - &resp, - client.Var("representations", representations), - ) + var resp struct { + Entities []struct { + Name string `json:"name"` + World struct { + Foo string `json:"foo"` + } `json:"world"` + } `json:"_entities"` + } - require.NoError(t, err) - require.Equal(t, resp.Entities[0].Name, "earth") - require.Equal(t, resp.Entities[0].World.Foo, "A") - require.Equal(t, resp.Entities[1].Name, "mars") - require.Equal(t, resp.Entities[1].World.Foo, "B") - }) + err := c.Post( + entityQuery([]string{ + "MultiPlanetRequiresNested {name, world { foo }}", + }), + &resp, + client.Var("representations", representations), + ) + + require.NoError(t, err) + require.Equal(t, resp.Entities[0].Name, "earth") + require.Equal(t, resp.Entities[0].World.Foo, "A") + require.Equal(t, resp.Entities[1].Name, "mars") + require.Equal(t, resp.Entities[1].World.Foo, "B") + }, + ) } func entityQuery(queries []string) string { // What we want! - // query($representations:[_Any!]!){_entities(representations:$representations){ ...on Hello{secondary} }} + // query($representations:[_Any!]!){_entities(representations:$representations){ ...on + // Hello{secondary} }} entityQueries := make([]string, len(queries)) for i, query := range queries { entityQueries[i] = " ... on " + query } - return "query($representations:[_Any!]!){_entities(representations:$representations){" + strings.Join(entityQueries, "") + "}}" + return "query($representations:[_Any!]!){_entities(representations:$representations){" + strings.Join( + entityQueries, + "", + ) + "}}" } type entityResolverError struct { diff --git a/plugin/federation/federation_test.go b/plugin/federation/federation_test.go index 75fb462b8c..aaf1233b52 100644 --- a/plugin/federation/federation_test.go +++ b/plugin/federation/federation_test.go @@ -11,7 +11,18 @@ import ( func TestWithEntities(t *testing.T) { f, cfg := load(t, "testdata/allthethings/gqlgen.yml") - require.Equal(t, []string{"ExternalExtension", "Hello", "MoreNesting", "NestedKey", "VeryNestedKey", "World"}, cfg.Schema.Types["_Entity"].Types) + require.Equal( + t, + []string{ + "ExternalExtension", + "Hello", + "MoreNesting", + "NestedKey", + "VeryNestedKey", + "World", + }, + cfg.Schema.Types["_Entity"].Types, + ) require.Len(t, cfg.Schema.Types["Entity"].Fields, 6) @@ -20,7 +31,11 @@ func TestWithEntities(t *testing.T) { // missing on purpose: all @external fields: // require.Equal(t, "findMoreNestingByID", cfg.Schema.Types["Entity"].Fields[2].Name) require.Equal(t, "findNestedKeyByIDAndHelloName", cfg.Schema.Types["Entity"].Fields[2].Name) - require.Equal(t, "findVeryNestedKeyByIDAndHelloNameAndWorldFooAndWorldBarAndMoreWorldFoo", cfg.Schema.Types["Entity"].Fields[3].Name) + require.Equal( + t, + "findVeryNestedKeyByIDAndHelloNameAndWorldFooAndWorldBarAndMoreWorldFoo", + cfg.Schema.Types["Entity"].Fields[3].Name, + ) require.Equal(t, "findWorldByFoo", cfg.Schema.Types["Entity"].Fields[4].Name) require.Equal(t, "findWorldByBar", cfg.Schema.Types["Entity"].Fields[5].Name) diff --git a/plugin/federation/fieldset/fieldset.go b/plugin/federation/fieldset/fieldset.go index 059a3c8325..fcc4fc4ae8 100644 --- a/plugin/federation/fieldset/fieldset.go +++ b/plugin/federation/fieldset/fieldset.go @@ -45,7 +45,10 @@ func New(raw string, prefix []string) Set { } // FieldDefinition looks up a field in the type. -func (f Field) FieldDefinition(schemaType *ast.Definition, schema *ast.Schema) *ast.FieldDefinition { +func (f Field) FieldDefinition( + schemaType *ast.Definition, + schema *ast.Schema, +) *ast.FieldDefinition { objType := schemaType def := objType.Fields.ForName(f[0]) @@ -112,7 +115,8 @@ func (f Field) Join(str string) string { return strings.Join(f, str) } -// JoinGo concatenates the Go name of field parts with a string separator between. Useful in templates. +// JoinGo concatenates the Go name of field parts with a string separator between. Useful in +// templates. func (f Field) JoinGo(str string) string { strs := []string{} @@ -147,7 +151,13 @@ func extractSubs(str string) (string, string, string) { if start < 0 || end < 0 { panic("invalid key fieldSet: " + str) } - return strings.TrimSpace(str[:start]), strings.TrimSpace(str[start+1 : end]), strings.TrimSpace(str[end+1:]) + return strings.TrimSpace( + str[:start], + ), strings.TrimSpace( + str[start+1 : end], + ), strings.TrimSpace( + str[end+1:], + ) } // matchingBracketIndex returns the index of the closing bracket, assuming an open bracket at start. diff --git a/plugin/federation/testdata/entityresolver/generated/errors.go b/plugin/federation/testdata/entityresolver/generated/errors.go index b001e0e36a..4505ecaad0 100644 --- a/plugin/federation/testdata/entityresolver/generated/errors.go +++ b/plugin/federation/testdata/entityresolver/generated/errors.go @@ -3,8 +3,9 @@ package generated import "errors" // Errors defined for retained code that we want to stick around between generations. -// var ( ErrResolvingHelloWithErrorsByName = errors.New("error resolving HelloWithErrorsByName") - ErrEmptyKeyResolvingHelloWithErrorsByName = errors.New("error (empty key) resolving HelloWithErrorsByName") + ErrEmptyKeyResolvingHelloWithErrorsByName = errors.New( + "error (empty key) resolving HelloWithErrorsByName", + ) ) diff --git a/plugin/modelgen/models.go b/plugin/modelgen/models.go index 45c32715c6..50e8a9bcee 100644 --- a/plugin/modelgen/models.go +++ b/plugin/modelgen/models.go @@ -92,7 +92,6 @@ func (m *Plugin) Name() string { } func (m *Plugin) MutateConfig(cfg *config.Config) error { - b := &ModelBuild{ PackageName: cfg.Model.Package, } @@ -121,7 +120,8 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { b.Interfaces = append(b.Interfaces, it) case ast.Object, ast.InputObject: - if schemaType == cfg.Schema.Query || schemaType == cfg.Schema.Mutation || schemaType == cfg.Schema.Subscription { + if schemaType == cfg.Schema.Query || schemaType == cfg.Schema.Mutation || + schemaType == cfg.Schema.Subscription { continue } @@ -138,7 +138,8 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { // If Interface A implements interface B, and Interface C also implements interface B // then both A and C have methods of B. - // The reason for checking unique is to prevent the same method B from being generated twice. + // The reason for checking unique is to prevent the same method B from being generated + // twice. uniqueMap := map[string]bool{} for _, implementor := range cfg.Schema.GetImplements(schemaType) { if !uniqueMap[implementor.Name] { @@ -175,9 +176,13 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { } sort.Slice(b.Enums, func(i, j int) bool { return b.Enums[i].Name < b.Enums[j].Name }) sort.Slice(b.Models, func(i, j int) bool { return b.Models[i].Name < b.Models[j].Name }) - sort.Slice(b.Interfaces, func(i, j int) bool { return b.Interfaces[i].Name < b.Interfaces[j].Name }) + sort.Slice( + b.Interfaces, + func(i, j int) bool { return b.Interfaces[i].Name < b.Interfaces[j].Name }, + ) - // if we are not just turning all struct-type fields in generated structs into pointers, we need to at least + // if we are not just turning all struct-type fields in generated structs into pointers, we need + // to at least // check for cyclical relationships and recursive structs if !cfg.StructFieldsAlwaysPointers { findAndHandleCyclicalRelationships(b) @@ -243,10 +248,22 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { } goType := templates.CurrentImports.LookupType(field.Type) if strings.HasPrefix(goType, "[]") { - getter := fmt.Sprintf("func (this %s) Get%s() %s {\n", templates.ToGo(model.Name), field.GoName, goType) + getter := fmt.Sprintf( + "func (this %s) Get%s() %s {\n", + templates.ToGo(model.Name), + field.GoName, + goType, + ) getter += fmt.Sprintf("\tif this.%s == nil { return nil }\n", field.GoName) - getter += fmt.Sprintf("\tinterfaceSlice := make(%s, 0, len(this.%s))\n", goType, field.GoName) - getter += fmt.Sprintf("\tfor _, concrete := range this.%s { interfaceSlice = append(interfaceSlice, ", field.GoName) + getter += fmt.Sprintf( + "\tinterfaceSlice := make(%s, 0, len(this.%s))\n", + goType, + field.GoName, + ) + getter += fmt.Sprintf( + "\tfor _, concrete := range this.%s { interfaceSlice = append(interfaceSlice, ", + field.GoName, + ) if interfaceFieldTypeIsPointer && !structFieldTypeIsPointer { getter += "&" } else if !interfaceFieldTypeIsPointer && structFieldTypeIsPointer { @@ -371,7 +388,12 @@ func (m *Plugin) generateFields(cfg *config.Config, schemaType *ast.Definition) if m.FieldHook != nil { mf, err := m.FieldHook(schemaType, field, f) if err != nil { - return nil, fmt.Errorf("generror: field %v.%v: %w", schemaType.Name, field.Name, err) + return nil, fmt.Errorf( + "generror: field %v.%v: %w", + schemaType.Name, + field.Name, + err, + ) } f = mf } @@ -382,7 +404,8 @@ func (m *Plugin) generateFields(cfg *config.Config, schemaType *ast.Definition) return fields, nil } -// GoTagFieldHook applies the goTag directive to the generated Field f. When applying the Tag to the field, the field +// GoTagFieldHook applies the goTag directive to the generated Field f. When applying the Tag to the +// field, the field // name is used when no value argument is present. func GoTagFieldHook(td *ast.Definition, fd *ast.FieldDefinition, f *Field) (*Field, error) { args := make([]string, 0) @@ -417,7 +440,8 @@ func isStruct(t types.Type) bool { return is } -// findAndHandleCyclicalRelationships checks for cyclical relationships between generated structs and replaces them +// findAndHandleCyclicalRelationships checks for cyclical relationships between generated structs +// and replaces them // with pointers. These relationships will produce compilation errors if they are not pointers. // Also handles recursive structs. func findAndHandleCyclicalRelationships(b *ModelBuild) { @@ -430,9 +454,11 @@ func findAndHandleCyclicalRelationships(b *ModelBuild) { continue } - // the field Type string will be in the form "github.com/99designs/gqlgen/codegen/testserver/followschema.LoopA" + // the field Type string will be in the form + // "github.com/99designs/gqlgen/codegen/testserver/followschema.LoopA" // we only want the part after the last dot: "LoopA" - // this could lead to false positives, as we are only checking the name of the struct type, but these + // this could lead to false positives, as we are only checking the name of the struct + // type, but these // should be extremely rare, if it is even possible at all. fieldAStructNameParts := strings.Split(fieldA.Type.String(), ".") fieldAStructName := fieldAStructNameParts[len(fieldAStructNameParts)-1] @@ -459,7 +485,8 @@ func findAndHandleCyclicalRelationships(b *ModelBuild) { } } - // if this is a recursive struct (i.e. structA == structB), ensure that we only change this field to a pointer once + // if this is a recursive struct (i.e. structA == structB), ensure that we only + // change this field to a pointer once if cyclicalReferenceFound && ii != jj { fieldA.Type = types.NewPointer(fieldA.Type) break diff --git a/plugin/modelgen/models_test.go b/plugin/modelgen/models_test.go index dab490305b..1f280a6f5d 100644 --- a/plugin/modelgen/models_test.go +++ b/plugin/modelgen/models_test.go @@ -48,12 +48,22 @@ func TestModelGeneration(t *testing.T) { }) t.Run("description is generated", func(t *testing.T) { - node, err := parser.ParseFile(token.NewFileSet(), "./out/generated.go", nil, parser.ParseComments) + node, err := parser.ParseFile( + token.NewFileSet(), + "./out/generated.go", + nil, + parser.ParseComments, + ) require.NoError(t, err) for _, commentGroup := range node.Comments { text := commentGroup.Text() words := strings.Split(text, " ") - require.True(t, len(words) > 1, "expected description %q to have more than one word", text) + require.True( + t, + len(words) > 1, + "expected description %q to have more than one word", + text, + ) } }) diff --git a/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go b/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go index c1412cb918..5e53c6caa0 100644 --- a/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go +++ b/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go @@ -29,8 +29,10 @@ func (r *CustomResolverType) Resolver() customresolver.ResolverResolver { return &resolverCustomResolverType{r} } -type queryCustomResolverType struct{ *CustomResolverType } -type resolverCustomResolverType struct{ *CustomResolverType } +type ( + queryCustomResolverType struct{ *CustomResolverType } + resolverCustomResolverType struct{ *CustomResolverType } +) // !!! WARNING !!! // The code below was going to be deleted when updating resolvers. It has been copied here so you have diff --git a/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go b/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go index c1412cb918..5e53c6caa0 100644 --- a/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go +++ b/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go @@ -29,8 +29,10 @@ func (r *CustomResolverType) Resolver() customresolver.ResolverResolver { return &resolverCustomResolverType{r} } -type queryCustomResolverType struct{ *CustomResolverType } -type resolverCustomResolverType struct{ *CustomResolverType } +type ( + queryCustomResolverType struct{ *CustomResolverType } + resolverCustomResolverType struct{ *CustomResolverType } +) // !!! WARNING !!! // The code below was going to be deleted when updating resolvers. It has been copied here so you have diff --git a/plugin/resolvergen/testdata/return_values/return_values_test.go b/plugin/resolvergen/testdata/return_values/return_values_test.go index d8e32cdb35..744a33a924 100644 --- a/plugin/resolvergen/testdata/return_values/return_values_test.go +++ b/plugin/resolvergen/testdata/return_values/return_values_test.go @@ -1,9 +1,10 @@ package return_values import ( - "github.com/stretchr/testify/require" "reflect" "testing" + + "github.com/stretchr/testify/require" ) //go:generate rm -f resolvers.go diff --git a/plugin/resolvergen/testdata/singlefile/out/resolver.go b/plugin/resolvergen/testdata/singlefile/out/resolver.go index b4bc684e95..9da3005341 100644 --- a/plugin/resolvergen/testdata/singlefile/out/resolver.go +++ b/plugin/resolvergen/testdata/singlefile/out/resolver.go @@ -24,5 +24,7 @@ func (r *CustomResolverType) Query() QueryResolver { return &queryCustomResolver // Resolver returns ResolverResolver implementation. func (r *CustomResolverType) Resolver() ResolverResolver { return &resolverCustomResolverType{r} } -type queryCustomResolverType struct{ *CustomResolverType } -type resolverCustomResolverType struct{ *CustomResolverType } +type ( + queryCustomResolverType struct{ *CustomResolverType } + resolverCustomResolverType struct{ *CustomResolverType } +)