From e22d1aa406dc1f4a66fdebd73346997be501bd7b Mon Sep 17 00:00:00 2001 From: Niklas Kapelle Date: Wed, 8 Jan 2025 02:00:34 +0100 Subject: [PATCH] added gql shit --- go.mod | 2 + go.sum | 4 + internal/web/gqlSchema.go | 242 ++++++++++++++++++++++++++++++++++++++ internal/web/web.go | 10 ++ 4 files changed, 258 insertions(+) create mode 100644 internal/web/gqlSchema.go diff --git a/go.mod b/go.mod index 576c41c..ef7f9d3 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,8 @@ require github.com/alexflint/go-arg v1.5.1 require ( github.com/alexflint/go-scalar v1.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/graphql-go/graphql v0.8.1 // indirect + github.com/graphql-go/handler v0.2.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 221386a..1eecb00 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,10 @@ github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+W github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/graphql-go/graphql v0.8.1 h1:p7/Ou/WpmulocJeEx7wjQy611rtXGQaAcXGqanuMMgc= +github.com/graphql-go/graphql v0.8.1/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ= +github.com/graphql-go/handler v0.2.4 h1:gz9q11TUHPNUpqzV8LMa+rkqM5NUuH/nkE3oF2LS3rI= +github.com/graphql-go/handler v0.2.4/go.mod h1:gsQlb4gDvURR0bgN8vWQEh+s5vJALM2lYL3n3cf6OxQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/internal/web/gqlSchema.go b/internal/web/gqlSchema.go new file mode 100644 index 0000000..96ee87d --- /dev/null +++ b/internal/web/gqlSchema.go @@ -0,0 +1,242 @@ +package web + +import ( + "log" + + "git.kapelle.org/niklas/beerpong-elo/internal/model" + "git.kapelle.org/niklas/beerpong-elo/internal/repo" + "github.com/graphql-go/graphql" +) + +func createShema(repo repo.Repo) graphql.Schema { + + player := graphql.NewObject(graphql.ObjectConfig{ + Name: "Player", + Description: "A player. Can also be authors of games", + Fields: graphql.Fields{ + "ID": &graphql.Field{ + Type: graphql.NewNonNull(graphql.ID), + }, + }, + }) + + game := graphql.NewObject(graphql.ObjectConfig{ + Name: "Game", + Description: "A game played", + Fields: graphql.Fields{ + "id": &graphql.Field{ + Type: graphql.NewNonNull(graphql.ID), + }, + "added": &graphql.Field{ + Type: graphql.NewNonNull(graphql.String), + }, + "overtime": &graphql.Field{ + Type: graphql.NewNonNull(graphql.Boolean), + }, + "score": &graphql.Field{ + Type: graphql.NewNonNull(graphql.Int), + }, + "team0player0": &graphql.Field{ + Type: graphql.NewNonNull(player), + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + game, ok := p.Source.(*model.Game) + if !ok { + return nil, nil + } + + player, err := repo.GetPlayer(game.Team0Player0) + if err != nil { + return nil, err + } + + return player, nil + }, + }, + "team0player1": &graphql.Field{ + Type: graphql.NewNonNull(player), + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + game, ok := p.Source.(*model.Game) + if !ok { + return nil, nil + } + + player, err := repo.GetPlayer(game.Team0Player1) + if err != nil { + return nil, err + } + + return player, nil + }, + }, + "team1player0": &graphql.Field{ + Type: graphql.NewNonNull(player), + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + game, ok := p.Source.(*model.Game) + if !ok { + return nil, nil + } + + player, err := repo.GetPlayer(game.Team1Player0) + if err != nil { + return nil, err + } + + return player, nil + }, + }, + "team1player1": &graphql.Field{ + Type: graphql.NewNonNull(player), + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + game, ok := p.Source.(*model.Game) + if !ok { + return nil, nil + } + + player, err := repo.GetPlayer(game.Team1Player1) + if err != nil { + return nil, err + } + + return player, nil + }, + }, + }, + }) + + gameResult := graphql.NewObject(graphql.ObjectConfig{ + Name: "GameResult", + Description: "The ELO change for a player in a game", + Fields: graphql.Fields{ + "id": &graphql.Field{ + Type: graphql.NewNonNull(graphql.ID), + }, + "player": &graphql.Field{ + Type: player, + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + gameResult, ok := p.Source.(*model.GameResult) + if !ok { + return nil, nil + } + + player, err := repo.GetPlayer(gameResult.Player) + if err != nil { + return nil, err + } + + return player, nil + }, + }, + "game": &graphql.Field{ + Type: graphql.NewNonNull(game), + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + gameResult, ok := p.Source.(*model.GameResult) + if !ok { + return nil, nil + } + + game, err := repo.GetGame(gameResult.Game) + if err != nil { + return nil, err + } + + return game, nil + }, + }, + "startElo": &graphql.Field{ + Type: graphql.NewNonNull(graphql.Int), + }, + "endElo": &graphql.Field{ + Type: graphql.NewNonNull(graphql.Int), + }, + }, + }) + + queryFields := graphql.Fields{ + "players": &graphql.Field{ + Type: graphql.NewList(player), + Description: "All players", + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + return repo.GetAllPlayers() + }, + }, + "player": &graphql.Field{ + Type: player, + Description: "Get player by ID", + Args: graphql.FieldConfigArgument{ + "id": &graphql.ArgumentConfig{ + Type: graphql.NewNonNull(graphql.ID), + }, + }, + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + id, ok := p.Args["id"].(model.PlayerID) + if !ok { + return nil, nil + } + + player, err := repo.GetPlayer(model.PlayerID(id)) + if err != nil { + return nil, err + } + + return player, nil + }, + }, + "game": &graphql.Field{ + Type: game, + Description: "Get game by ID", + Args: graphql.FieldConfigArgument{ + "id": &graphql.ArgumentConfig{ + Type: graphql.NewNonNull(graphql.ID), + }, + }, + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + id, ok := p.Args["id"].(model.GameID) + if !ok { + return nil, nil + } + + game, err := repo.GetGame(model.GameID(id)) + if err != nil { + return nil, err + } + + return game, nil + }, + }, + "gameResult": &graphql.Field{ + Type: gameResult, + Description: "Result of a game on a players ELO", + Args: graphql.FieldConfigArgument{ + "id": &graphql.ArgumentConfig{ + Type: graphql.NewNonNull(graphql.ID), + }, + }, + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + id, ok := p.Args["id"].(model.GameResultID) + if !ok { + return nil, nil + } + + gameResult, err := repo.GetGameResult(model.GameResultID(id)) + if err != nil { + return nil, err + } + + return gameResult, nil + }, + }, + } + + querySchema := graphql.ObjectConfig{ + Name: "Query", + Fields: queryFields, + } + + schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(querySchema)} + schema, err := graphql.NewSchema(schemaConfig) + if err != nil { + log.Fatalf("failed to create new schema, error: %v", err) + } + + return schema +} diff --git a/internal/web/web.go b/internal/web/web.go index bb14719..d828837 100644 --- a/internal/web/web.go +++ b/internal/web/web.go @@ -5,14 +5,24 @@ import ( "net/http" "git.kapelle.org/niklas/beerpong-elo/internal/repo" + "github.com/graphql-go/handler" ) func CreateWebserver(repo repo.Repo) *http.ServeMux { router := http.NewServeMux() + schema := createShema(repo) router.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path) }) + gqlHandler := handler.New(&handler.Config{ + Schema: &schema, + Pretty: true, + GraphiQL: true, + }) + + router.Handle("/graphql", gqlHandler) + return router }